Compare commits
58 Commits
Author | SHA1 | Date |
---|---|---|
|
af8244e53a | |
|
0e85028f68 | |
|
63281440c1 | |
|
7e4ac4cc45 | |
|
9fb5e5a384 | |
|
0b10874e04 | |
|
77a6191735 | |
|
bb7ea39bcd | |
|
3a8ff7b8fa | |
|
e96a7ee7f1 | |
|
31aa78b0cf | |
|
9d6dfb2d65 | |
|
a4c31076d4 | |
|
2b2646ea7e | |
|
dc17ee1399 | |
|
fe0bf63328 | |
|
361a7649cb | |
|
f1afe838dd | |
|
ba4d2f704c | |
|
2d84728732 | |
|
d864dde90f | |
|
e2641540a9 | |
|
6819a4be12 | |
|
de73ffdd63 | |
|
522c4dd8d8 | |
|
d2a310ac30 | |
|
dc8f3597d3 | |
|
8909abc5c2 | |
|
d019f63af5 | |
|
ed0899559a | |
|
06ff37d414 | |
|
ccd88854bd | |
|
852d1203d4 | |
|
c97b2b90e1 | |
|
3a5f576c5b | |
|
5ea32522f0 | |
|
184224e2d2 | |
|
9cf6a6b9b7 | |
|
3998ae9f43 | |
|
aa8bea8162 | |
|
e7f9ae680a | |
|
d7645eaac5 | |
|
155d6cd729 | |
|
feb7100c35 | |
|
6b272cd656 | |
|
054c3e2a97 | |
|
66266db7fd | |
|
a47df5d5c7 | |
|
de7c74a937 | |
|
00233519bd | |
|
f3873a0417 | |
|
d39bc1fc09 | |
|
30feb53ddf | |
|
e5b440b5cd | |
|
463651570a | |
|
466b8aba39 | |
|
3d12d34d20 | |
|
b7f908ff8c |
|
@ -1,10 +0,0 @@
|
||||||
component_depth: 2
|
|
||||||
languages:
|
|
||||||
- go
|
|
||||||
exclude:
|
|
||||||
- /vendor/.*
|
|
||||||
- /pkg/client/.*
|
|
||||||
- /pkg/apis/litmuschaos/v1alpha1/zz_generated.*\.go
|
|
||||||
test:
|
|
||||||
include:
|
|
||||||
- .*/test/.*\.go
|
|
|
@ -2,4 +2,4 @@
|
||||||
# Each line is a file pattern followed by one or more owners.
|
# Each line is a file pattern followed by one or more owners.
|
||||||
|
|
||||||
# These owners will be the default owners for everything in the repo.
|
# These owners will be the default owners for everything in the repo.
|
||||||
* @rahulchheda @ksatchit @chandankumar4 @rajdas98
|
* @ksatchit @ispeakc0de @imrajdas
|
|
@ -11,7 +11,7 @@ jobs:
|
||||||
# Install golang
|
# Install golang
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.5
|
go-version: 1.22
|
||||||
|
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
|
@ -22,27 +22,13 @@ jobs:
|
||||||
run: make gofmt-check
|
run: make gofmt-check
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: reviewdog/action-golangci-lint@v1
|
uses: reviewdog/action-golangci-lint@v2
|
||||||
|
with:
|
||||||
|
golangci_lint_flags: "--timeout=10m"
|
||||||
|
|
||||||
- name: unused-package check
|
- name: unused-package check
|
||||||
run: make unused-package-check
|
run: make unused-package-check
|
||||||
|
|
||||||
security:
|
|
||||||
container:
|
|
||||||
image: litmuschaos/snyk:1.0
|
|
||||||
volumes:
|
|
||||||
- /home/runner/work/_actions/:/home/runner/work/_actions/
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: snyk/actions/setup@master
|
|
||||||
- run: snyk auth ${SNYK_TOKEN}
|
|
||||||
- uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: '1.17'
|
|
||||||
- name: Snyk monitor
|
|
||||||
run: snyk test
|
|
||||||
|
|
||||||
trivy:
|
trivy:
|
||||||
needs: pre-checks
|
needs: pre-checks
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -54,7 +40,7 @@ jobs:
|
||||||
- name: Build an image from Dockerfile
|
- name: Build an image from Dockerfile
|
||||||
run: |
|
run: |
|
||||||
docker build -f build/Dockerfile -t docker.io/litmuschaos/chaos-operator:${{ github.sha }} . --build-arg TARGETPLATFORM=linux/amd64
|
docker build -f build/Dockerfile -t docker.io/litmuschaos/chaos-operator:${{ github.sha }} . --build-arg TARGETPLATFORM=linux/amd64
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner
|
- name: Run Trivy vulnerability scanner
|
||||||
uses: aquasecurity/trivy-action@master
|
uses: aquasecurity/trivy-action@master
|
||||||
with:
|
with:
|
||||||
|
@ -63,7 +49,19 @@ jobs:
|
||||||
exit-code: '1'
|
exit-code: '1'
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
vuln-type: 'os,library'
|
vuln-type: 'os,library'
|
||||||
severity: 'CRITICAL,HIGH'
|
severity: 'CRITICAL,HIGH'
|
||||||
|
|
||||||
|
gitleaks-scan:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Run GitLeaks
|
||||||
|
run: |
|
||||||
|
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.2/gitleaks_8.18.2_linux_x64.tar.gz && \
|
||||||
|
tar -zxvf gitleaks_8.18.2_linux_x64.tar.gz && \
|
||||||
|
sudo mv gitleaks /usr/local/bin && gitleaks detect --source . -v
|
||||||
|
|
||||||
image-build:
|
image-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -83,9 +81,9 @@ jobs:
|
||||||
make build-amd64
|
make build-amd64
|
||||||
docker save -o ${{ github.workspace }}/image.tar litmuschaos/chaos-operator:ci
|
docker save -o ${{ github.workspace }}/image.tar litmuschaos/chaos-operator:ci
|
||||||
chmod +x ${{ github.workspace }}/image.tar
|
chmod +x ${{ github.workspace }}/image.tar
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: myimage
|
name: myimage
|
||||||
path: |
|
path: |
|
||||||
|
@ -98,7 +96,7 @@ jobs:
|
||||||
# Install golang
|
# Install golang
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.5
|
go-version: 1.22
|
||||||
|
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
|
@ -107,7 +105,7 @@ jobs:
|
||||||
|
|
||||||
#Install and configure a kind cluster
|
#Install and configure a kind cluster
|
||||||
- name: Installing Prerequisites (K3S Cluster)
|
- name: Installing Prerequisites (K3S Cluster)
|
||||||
env:
|
env:
|
||||||
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
|
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
|
||||||
run: |
|
run: |
|
||||||
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.20.14-rc1+k3s1 sh -s - --docker --write-kubeconfig-mode 664
|
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.20.14-rc1+k3s1 sh -s - --docker --write-kubeconfig-mode 664
|
||||||
|
@ -121,16 +119,17 @@ jobs:
|
||||||
make deps
|
make deps
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: myimage
|
name: myimage
|
||||||
path: ${{ github.workspace }}
|
path: ${{ github.workspace }}
|
||||||
|
|
||||||
- name: Load Docker image
|
- name: Load Docker image
|
||||||
run: |
|
run: |
|
||||||
docker load --input ${{ github.workspace }}/image.tar
|
docker load --input ${{ github.workspace }}/image.tar
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Running Go BDD Test
|
- name: Running Go BDD Test
|
||||||
run: |
|
run: |
|
||||||
|
go mod tidy
|
||||||
make test
|
make test
|
||||||
|
|
|
@ -2,13 +2,13 @@ name: ChaosOperator-E2E-pipeline
|
||||||
on:
|
on:
|
||||||
issue_comment:
|
issue_comment:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Tests:
|
Tests:
|
||||||
if: contains(github.event.comment.html_url, '/pull/') && startsWith(github.event.comment.body, '/run-e2e')
|
if: contains(github.event.comment.html_url, '/pull/') && startsWith(github.event.comment.body, '/run-e2e')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Notification for e2e Start
|
- name: Notification for e2e Start
|
||||||
uses: peter-evans/create-or-update-comment@v1
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
with:
|
with:
|
||||||
|
@ -19,13 +19,13 @@ jobs:
|
||||||
|
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '^1.13.1'
|
go-version: 1.22
|
||||||
|
|
||||||
- name: Setting up GOPATH
|
- name: Setting up GOPATH
|
||||||
run: |
|
run: |
|
||||||
echo ::set-env name=GOPATH::${GITHUB_WORKSPACE}/go
|
echo ::set-env name=GOPATH::${GITHUB_WORKSPACE}/go
|
||||||
env:
|
env:
|
||||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||||
|
|
||||||
#Using the last commit id of pull request
|
#Using the last commit id of pull request
|
||||||
- uses: octokit/request-action@v2.x
|
- uses: octokit/request-action@v2.x
|
||||||
|
@ -36,20 +36,20 @@ jobs:
|
||||||
pull_number: ${{ github.event.issue.number }}
|
pull_number: ${{ github.event.issue.number }}
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: set commit to output
|
- name: set commit to output
|
||||||
id: getcommit
|
id: getcommit
|
||||||
run: |
|
run: |
|
||||||
prsha=$(echo $response | jq '.[-1].sha' | tr -d '"')
|
prsha=$(echo $response | jq '.[-1].sha' | tr -d '"')
|
||||||
echo "::set-output name=sha::$prsha"
|
echo "::set-output name=sha::$prsha"
|
||||||
env:
|
env:
|
||||||
response: ${{ steps.get_PR_commits.outputs.data }}
|
response: ${{ steps.get_PR_commits.outputs.data }}
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: ${{steps.getcommit.outputs.sha}}
|
ref: ${{steps.getcommit.outputs.sha}}
|
||||||
path: go/src/github.com/litmuschaos/chaos-operator
|
path: go/src/github.com/litmuschaos/chaos-operator
|
||||||
|
|
||||||
- name: Build docker image
|
- name: Build docker image
|
||||||
run: |
|
run: |
|
||||||
export PATH=$PATH:$(go env GOPATH)/bin
|
export PATH=$PATH:$(go env GOPATH)/bin
|
||||||
|
@ -61,12 +61,14 @@ jobs:
|
||||||
- name: Installing Prerequisites (KinD Cluster)
|
- name: Installing Prerequisites (KinD Cluster)
|
||||||
uses: engineerd/setup-kind@v0.5.0
|
uses: engineerd/setup-kind@v0.5.0
|
||||||
with:
|
with:
|
||||||
version: "v0.7.0"
|
version: "v0.22.0"
|
||||||
|
|
||||||
- name: Configuring and testing kind Installation
|
- name: Configuring and testing kind Installation
|
||||||
run: |
|
run: |
|
||||||
kubectl cluster-info --context kind-kind
|
kubectl cluster-info
|
||||||
kind get kubeconfig --internal >$HOME/.kube/config
|
kubectl get pods -n kube-system
|
||||||
|
echo "current-context:" $(kubectl config current-context)
|
||||||
|
echo "environment-kubeconfig:" ${KUBECONFIG}
|
||||||
kubectl get nodes
|
kubectl get nodes
|
||||||
|
|
||||||
- name: Load image on the nodes of the cluster
|
- name: Load image on the nodes of the cluster
|
||||||
|
@ -76,7 +78,7 @@ jobs:
|
||||||
- name: Getting litmus-e2e repository
|
- name: Getting litmus-e2e repository
|
||||||
run: |
|
run: |
|
||||||
cd ${GOPATH}/src/github.com/litmuschaos/
|
cd ${GOPATH}/src/github.com/litmuschaos/
|
||||||
git clone https://github.com/litmuschaos/litmus-e2e.git -b generic
|
git clone https://github.com/litmuschaos/litmus-e2e.git -b master
|
||||||
|
|
||||||
- name: Install LitmusChaos
|
- name: Install LitmusChaos
|
||||||
run: |
|
run: |
|
||||||
|
@ -86,25 +88,25 @@ jobs:
|
||||||
env:
|
env:
|
||||||
OPERATOR_IMAGE: litmuschaos/chaos-operator:ci
|
OPERATOR_IMAGE: litmuschaos/chaos-operator:ci
|
||||||
IMAGE_PULL_POLICY: IfNotPresent
|
IMAGE_PULL_POLICY: IfNotPresent
|
||||||
KUBECONFIG: /home/runner/.kube/config
|
KUBECONFIG: /home/runner/.kube/config
|
||||||
|
|
||||||
- name: Run Admin mode test
|
- name: Run Admin mode test
|
||||||
if: startsWith(github.event.comment.body, '/run-e2e-admin-mode') || startsWith(github.event.comment.body, '/run-e2e-all')
|
if: startsWith(github.event.comment.body, '/run-e2e-admin-mode') || startsWith(github.event.comment.body, '/run-e2e-all')
|
||||||
run: |
|
run: |
|
||||||
export PATH=$PATH:$(go env GOPATH)/bin
|
export PATH=$PATH:$(go env GOPATH)/bin
|
||||||
cd ${GOPATH}/src/github.com/litmuschaos/litmus-e2e
|
cd ${GOPATH}/src/github.com/litmuschaos/litmus-e2e
|
||||||
go test operator/admin-mode_test.go -v -count=1
|
go test components/operator/admin-mode_test.go -v -count=1
|
||||||
env:
|
env:
|
||||||
KUBECONFIG: /home/runner/.kube/config
|
KUBECONFIG: /home/runner/.kube/config
|
||||||
|
|
||||||
- name: Run Reconcile Resiliency test
|
- name: Run Reconcile Resiliency test
|
||||||
if: startsWith(github.event.comment.body, '/run-e2e-reconcile-resiliency') || startsWith(github.event.comment.body, '/run-e2e-all')
|
if: startsWith(github.event.comment.body, '/run-e2e-reconcile-resiliency') || startsWith(github.event.comment.body, '/run-e2e-all')
|
||||||
run: |
|
run: |
|
||||||
export PATH=$PATH:$(go env GOPATH)/bin
|
export PATH=$PATH:$(go env GOPATH)/bin
|
||||||
cd ${GOPATH}/src/github.com/litmuschaos/litmus-e2e
|
cd ${GOPATH}/src/github.com/litmuschaos/litmus-e2e
|
||||||
go test operator/reconcile-resiliency_test.go -v -count=1
|
go test components/operator/reconcile-resiliency_test.go -v -count=1
|
||||||
env:
|
env:
|
||||||
KUBECONFIG: /home/runner/.kube/config
|
KUBECONFIG: /home/runner/.kube/config
|
||||||
|
|
||||||
- name: Check the test run
|
- name: Check the test run
|
||||||
if: |
|
if: |
|
||||||
|
@ -113,7 +115,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo ::set-env name=TEST_RUN::true
|
echo ::set-env name=TEST_RUN::true
|
||||||
env:
|
env:
|
||||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||||
|
|
||||||
- name: Check for all the jobs are succeeded
|
- name: Check for all the jobs are succeeded
|
||||||
if: ${{ success() && env.TEST_RUN == 'true' }}
|
if: ${{ success() && env.TEST_RUN == 'true' }}
|
||||||
|
@ -123,11 +125,11 @@ jobs:
|
||||||
body: |
|
body: |
|
||||||
**Test Result:** All tests are passed
|
**Test Result:** All tests are passed
|
||||||
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
||||||
|
|
||||||
reactions: hooray
|
reactions: hooray
|
||||||
env:
|
env:
|
||||||
RUN_ID: ${{ github.run_id }}
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
|
||||||
- name: Check for any job failed
|
- name: Check for any job failed
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
uses: peter-evans/create-or-update-comment@v1
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
|
@ -135,23 +137,23 @@ jobs:
|
||||||
comment-id: "${{ github.event.comment.id }}"
|
comment-id: "${{ github.event.comment.id }}"
|
||||||
body: |
|
body: |
|
||||||
**Test Failed:** Some tests are failed please check
|
**Test Failed:** Some tests are failed please check
|
||||||
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
||||||
reactions: confused
|
reactions: confused
|
||||||
env:
|
env:
|
||||||
RUN_ID: ${{ github.run_id }}
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
|
||||||
- name: Deleting KinD cluster
|
- name: Deleting KinD cluster
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
run: kind delete cluster
|
run: kind delete cluster
|
||||||
|
|
||||||
- name: Check if any test ran or not
|
- name: Check if any test ran or not
|
||||||
if: env.TEST_RUN != 'true'
|
if: env.TEST_RUN != 'true'
|
||||||
uses: peter-evans/create-or-update-comment@v1
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
with:
|
with:
|
||||||
comment-id: "${{ github.event.comment.id }}"
|
comment-id: "${{ github.event.comment.id }}"
|
||||||
body: |
|
body: |
|
||||||
**Test Result:** No test found
|
**Test Result:** No test found try /run-e2e-all
|
||||||
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
**Logs:** [${{ env.RUN_ID }}](https://github.com/litmuschaos/chaos-operator/actions/runs/${{ env.RUN_ID }})
|
||||||
reactions: eyes
|
reactions: eyes
|
||||||
env:
|
env:
|
||||||
RUN_ID: ${{ github.run_id }}
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
|
|
@ -13,7 +13,7 @@ jobs:
|
||||||
# Install golang
|
# Install golang
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.5
|
go-version: 1.22
|
||||||
|
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
|
@ -24,14 +24,13 @@ jobs:
|
||||||
run: make gofmt-check
|
run: make gofmt-check
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: reviewdog/action-golangci-lint@v1
|
uses: reviewdog/action-golangci-lint@v2
|
||||||
|
|
||||||
- name: unused-package check
|
- name: unused-package check
|
||||||
run: make unused-package-check
|
run: make unused-package-check
|
||||||
|
|
||||||
image-build:
|
image-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: tests
|
|
||||||
steps:
|
steps:
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
|
@ -59,45 +58,4 @@ jobs:
|
||||||
DOCKER_TAG: ci
|
DOCKER_TAG: ci
|
||||||
DNAME: ${{ secrets.DNAME }}
|
DNAME: ${{ secrets.DNAME }}
|
||||||
DPASS: ${{ secrets.DPASS }}
|
DPASS: ${{ secrets.DPASS }}
|
||||||
run: make push-chaos-operator
|
run: make push-chaos-operator
|
||||||
|
|
||||||
tests:
|
|
||||||
needs: pre-checks
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# Checkout to the latest commit
|
|
||||||
# On specific directory/path
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Install golang
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.17.5
|
|
||||||
|
|
||||||
#Install and configure a kind cluster
|
|
||||||
- name: Installing Prerequisites (K3S Cluster)
|
|
||||||
env:
|
|
||||||
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
|
|
||||||
run: |
|
|
||||||
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.20.14-rc1+k3s1 sh -s - --docker --write-kubeconfig-mode 664
|
|
||||||
kubectl wait node --all --for condition=ready --timeout=90s
|
|
||||||
mkdir -p $HOME/.kube
|
|
||||||
cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
|
|
||||||
kubectl get nodes
|
|
||||||
|
|
||||||
- name: Dependency checks
|
|
||||||
run: |
|
|
||||||
make deps
|
|
||||||
|
|
||||||
- name: Build Docker Image
|
|
||||||
env:
|
|
||||||
DOCKER_REPO: litmuschaos
|
|
||||||
DOCKER_IMAGE: chaos-operator
|
|
||||||
DOCKER_TAG: ci
|
|
||||||
run: |
|
|
||||||
make build-amd64
|
|
||||||
|
|
||||||
- name: Running Go BDD Test
|
|
||||||
run: |
|
|
||||||
make test
|
|
|
@ -11,25 +11,15 @@ jobs:
|
||||||
# Install golang
|
# Install golang
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.5
|
go-version: 1.22
|
||||||
|
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: gofmt check
|
|
||||||
run: make gofmt-check
|
|
||||||
|
|
||||||
- name: golangci-lint
|
|
||||||
uses: reviewdog/action-golangci-lint@v1
|
|
||||||
|
|
||||||
- name: unused-package check
|
|
||||||
run: make unused-package-check
|
|
||||||
|
|
||||||
image-build:
|
image-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: tests
|
|
||||||
steps:
|
steps:
|
||||||
# Checkout to the latest commit
|
# Checkout to the latest commit
|
||||||
# On specific directory/path
|
# On specific directory/path
|
||||||
|
@ -73,44 +63,3 @@ jobs:
|
||||||
DNAME: ${{ secrets.DNAME }}
|
DNAME: ${{ secrets.DNAME }}
|
||||||
DPASS: ${{ secrets.DPASS }}
|
DPASS: ${{ secrets.DPASS }}
|
||||||
run: make push-chaos-operator
|
run: make push-chaos-operator
|
||||||
|
|
||||||
tests:
|
|
||||||
needs: pre-checks
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# Checkout to the latest commit
|
|
||||||
# On specific directory/path
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Install golang
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.17.5
|
|
||||||
|
|
||||||
#Install and configure a kind cluster
|
|
||||||
- name: Installing Prerequisites (K3S Cluster)
|
|
||||||
env:
|
|
||||||
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
|
|
||||||
run: |
|
|
||||||
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.20.14-rc1+k3s1 sh -s - --docker --write-kubeconfig-mode 664
|
|
||||||
kubectl wait node --all --for condition=ready --timeout=90s
|
|
||||||
mkdir -p $HOME/.kube
|
|
||||||
cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
|
|
||||||
kubectl get nodes
|
|
||||||
|
|
||||||
- name: Dependency checks
|
|
||||||
run: |
|
|
||||||
make deps
|
|
||||||
|
|
||||||
- name: Build Docker Image
|
|
||||||
env:
|
|
||||||
DOCKER_REPO: litmuschaos
|
|
||||||
DOCKER_IMAGE: chaos-operator
|
|
||||||
DOCKER_TAG: ci
|
|
||||||
run: |
|
|
||||||
make build-amd64
|
|
||||||
|
|
||||||
- name: Running Go BDD Test
|
|
||||||
run: |
|
|
||||||
make test
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
name: Security Scan
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
trivy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Build an image from Dockerfile
|
||||||
|
run: |
|
||||||
|
docker build -f build/Dockerfile -t docker.io/litmuschaos/chaos-operator:${{ github.sha }} . --build-arg TARGETARCH=amd64
|
||||||
|
|
||||||
|
- name: Run Trivy vulnerability scanner
|
||||||
|
uses: aquasecurity/trivy-action@master
|
||||||
|
with:
|
||||||
|
image-ref: 'docker.io/litmuschaos/chaos-operator:${{ github.sha }}'
|
||||||
|
format: 'table'
|
||||||
|
exit-code: '1'
|
||||||
|
ignore-unfixed: true
|
||||||
|
vuln-type: 'os,library'
|
||||||
|
severity: 'CRITICAL,HIGH'
|
12
Makefile
12
Makefile
|
@ -72,21 +72,21 @@ gofmt-check:
|
||||||
.PHONY: build-chaos-operator
|
.PHONY: build-chaos-operator
|
||||||
build-chaos-operator:
|
build-chaos-operator:
|
||||||
@echo "-------------------------"
|
@echo "-------------------------"
|
||||||
@echo "--> Build go-runner image"
|
@echo "--> Build go-runner image"
|
||||||
@echo "-------------------------"
|
@echo "-------------------------"
|
||||||
@docker buildx build --file build/Dockerfile --progress plane --no-cache --platform linux/arm64,linux/amd64 --tag $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) .
|
@docker buildx build --file build/Dockerfile --progress plain --no-cache --platform linux/arm64,linux/amd64 --tag $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||||
|
|
||||||
.PHONY: push-chaos-operator
|
.PHONY: push-chaos-operator
|
||||||
push-chaos-operator:
|
push-chaos-operator:
|
||||||
@echo "------------------------------"
|
@echo "------------------------------"
|
||||||
@echo "--> Pushing image"
|
@echo "--> Pushing image"
|
||||||
@echo "------------------------------"
|
@echo "------------------------------"
|
||||||
@docker buildx build --file build/Dockerfile --progress plane --no-cache --push --platform linux/arm64,linux/amd64 --tag $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) .
|
@docker buildx build --file build/Dockerfile --progress plain --no-cache --push --platform linux/arm64,linux/amd64 --tag $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) .
|
||||||
|
|
||||||
.PHONY: build-amd64
|
.PHONY: build-amd64
|
||||||
build-amd64:
|
build-amd64:
|
||||||
@echo "-------------------------"
|
@echo "-------------------------"
|
||||||
@echo "--> Build go-runner image"
|
@echo "--> Build go-runner image"
|
||||||
@echo "-------------------------"
|
@echo "-------------------------"
|
||||||
@docker build -f build/Dockerfile --no-cache -t $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) . --build-arg TARGETPLATFORM="linux/amd64"
|
@docker build -f build/Dockerfile --no-cache -t $(DOCKER_REGISTRY)/$(DOCKER_REPO)/$(DOCKER_IMAGE):$(DOCKER_TAG) . --build-arg TARGETPLATFORM="linux/amd64"
|
||||||
|
|
||||||
|
@ -109,4 +109,4 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
|
||||||
|
|
||||||
.PHONY: generate
|
.PHONY: generate
|
||||||
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
|
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
|
||||||
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
[](https://www.codacy.com/manual/litmuschaos/chaos-operator?utm_source=github.com&utm_medium=referral&utm_content=litmuschaos/chaos-operator&utm_campaign=Badge_Grade)
|
[](https://www.codacy.com/manual/litmuschaos/chaos-operator?utm_source=github.com&utm_medium=referral&utm_content=litmuschaos/chaos-operator&utm_campaign=Badge_Grade)
|
||||||
[](https://goreportcard.com/report/github.com/litmuschaos/chaos-operator)
|
[](https://goreportcard.com/report/github.com/litmuschaos/chaos-operator)
|
||||||
[](https://bestpractices.coreinfrastructure.org/projects/5290)
|
[](https://bestpractices.coreinfrastructure.org/projects/5290)
|
||||||
[](https://bettercodehub.com/)
|
|
||||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-operator?ref=badge_shield)
|
[](https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-operator?ref=badge_shield)
|
||||||
[](https://codecov.io/gh/litmuschaos/chaos-operator)
|
[](https://codecov.io/gh/litmuschaos/chaos-operator)
|
||||||
[](https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw)
|
[](https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw)
|
||||||
|
|
|
@ -25,13 +25,11 @@ import (
|
||||||
// ChaosEngineSpec describes a user-facing custom resource which is used by developers
|
// ChaosEngineSpec describes a user-facing custom resource which is used by developers
|
||||||
// to create a chaos profile
|
// to create a chaos profile
|
||||||
type ChaosEngineSpec struct {
|
type ChaosEngineSpec struct {
|
||||||
//Appinfo contains deployment details of AUT
|
//Appinfo contains the AUT details
|
||||||
Appinfo ApplicationParams `json:"appinfo,omitempty"`
|
Appinfo ApplicationParams `json:"appinfo,omitempty"`
|
||||||
//AnnotationCheck defines whether annotation check is allowed or not. It can be true or false
|
|
||||||
AnnotationCheck string `json:"annotationCheck,omitempty"`
|
|
||||||
//DefaultHealthCheck defines whether default health checks should be executed or not. It can be true or false
|
//DefaultHealthCheck defines whether default health checks should be executed or not. It can be true or false
|
||||||
// default value is true
|
// default value is true
|
||||||
DefaultHealthCheck string `json:"defaultHealthCheck,omitempty"`
|
DefaultHealthCheck bool `json:"defaultHealthCheck,omitempty"`
|
||||||
//ChaosServiceAccount is the SvcAcc specified for chaos runner pods
|
//ChaosServiceAccount is the SvcAcc specified for chaos runner pods
|
||||||
ChaosServiceAccount string `json:"chaosServiceAccount"`
|
ChaosServiceAccount string `json:"chaosServiceAccount"`
|
||||||
//Components contains the image, imagePullPolicy, arguments, and commands of runner
|
//Components contains the image, imagePullPolicy, arguments, and commands of runner
|
||||||
|
@ -46,6 +44,8 @@ type ChaosEngineSpec struct {
|
||||||
EngineState EngineState `json:"engineState"`
|
EngineState EngineState `json:"engineState"`
|
||||||
// TerminationGracePeriodSeconds contains terminationGracePeriod for the chaos resources
|
// TerminationGracePeriodSeconds contains terminationGracePeriod for the chaos resources
|
||||||
TerminationGracePeriodSeconds int64 `json:"terminationGracePeriodSeconds,omitempty"`
|
TerminationGracePeriodSeconds int64 `json:"terminationGracePeriodSeconds,omitempty"`
|
||||||
|
// Selectors contains the target application details
|
||||||
|
Selectors *Selector `json:"selectors,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EngineState provides interface for all supported strings in spec.EngineState
|
// EngineState provides interface for all supported strings in spec.EngineState
|
||||||
|
@ -119,10 +119,52 @@ type ApplicationParams struct {
|
||||||
AppKind string `json:"appkind,omitempty"`
|
AppKind string `json:"appkind,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Selector struct {
|
||||||
|
Workloads []Workload `json:"workloads,omitempty"`
|
||||||
|
Pods []Pod `json:"pods,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WorkloadKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
WorkloadDeployment WorkloadKind = "deployment"
|
||||||
|
WorkloadStatefulSet WorkloadKind = "statefulset"
|
||||||
|
WorkloadDaemonSet WorkloadKind = "daemonSet"
|
||||||
|
WorkloadDeploymentConfig WorkloadKind = "deploymentconfig"
|
||||||
|
WorkloadRollout WorkloadKind = "rollout"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Workload struct {
|
||||||
|
Kind WorkloadKind `json:"kind"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
Names string `json:"names,omitempty"`
|
||||||
|
Labels string `json:"labels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pod struct {
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
Names string `json:"names"`
|
||||||
|
}
|
||||||
|
|
||||||
// ComponentParams defines information about the runner
|
// ComponentParams defines information about the runner
|
||||||
type ComponentParams struct {
|
type ComponentParams struct {
|
||||||
//Contains informations of the the runner pod
|
//Contains information of the runner pod
|
||||||
Runner RunnerInfo `json:"runner"`
|
Runner RunnerInfo `json:"runner"`
|
||||||
|
// Contains information of the sidecar
|
||||||
|
Sidecar []Sidecar `json:"sidecar,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Sidecar struct {
|
||||||
|
//Image of the sidecar container
|
||||||
|
Image string `json:"image"`
|
||||||
|
//ImagePullPolicy of the sidecar container
|
||||||
|
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||||
|
// Secrets for the sidecar container
|
||||||
|
Secrets []Secret `json:"secrets,omitempty"`
|
||||||
|
// EnvFrom for the sidecar container
|
||||||
|
EnvFrom []corev1.EnvFromSource `json:"envFrom"`
|
||||||
|
// ENV contains ENV passed to the sidecar container
|
||||||
|
ENV []corev1.EnvVar `json:"env,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunnerInfo defines the information of the runnerinfo pod
|
// RunnerInfo defines the information of the runnerinfo pod
|
||||||
|
@ -166,8 +208,6 @@ type ExperimentList struct {
|
||||||
|
|
||||||
// ExperimentAttributes defines attributes of experiments
|
// ExperimentAttributes defines attributes of experiments
|
||||||
type ExperimentAttributes struct {
|
type ExperimentAttributes struct {
|
||||||
//Execution priority of the chaos experiment
|
|
||||||
Rank uint32 `json:"rank"`
|
|
||||||
// It contains env, configmaps, secrets, experimentImage, node selector, custom experiment annotation
|
// It contains env, configmaps, secrets, experimentImage, node selector, custom experiment annotation
|
||||||
// which can be provided or overridden from the chaos engine
|
// which can be provided or overridden from the chaos engine
|
||||||
Components ExperimentComponents `json:"components,omitempty"`
|
Components ExperimentComponents `json:"components,omitempty"`
|
||||||
|
@ -179,22 +219,24 @@ type ExperimentAttributes struct {
|
||||||
// ProbeAttributes contains details of probe, which can be applied on the experiments
|
// ProbeAttributes contains details of probe, which can be applied on the experiments
|
||||||
type ProbeAttributes struct {
|
type ProbeAttributes struct {
|
||||||
// Name of probe
|
// Name of probe
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name"`
|
||||||
// Type of probe
|
// Type of probe
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type"`
|
||||||
// inputs needed for the k8s probe
|
// inputs needed for the k8s probe
|
||||||
K8sProbeInputs K8sProbeInputs `json:"k8sProbe/inputs,omitempty"`
|
K8sProbeInputs *K8sProbeInputs `json:"k8sProbe/inputs,omitempty"`
|
||||||
// inputs needed for the http probe
|
// inputs needed for the http probe
|
||||||
HTTPProbeInputs HTTPProbeInputs `json:"httpProbe/inputs,omitempty"`
|
HTTPProbeInputs *HTTPProbeInputs `json:"httpProbe/inputs,omitempty"`
|
||||||
// inputs needed for the cmd probe
|
// inputs needed for the cmd probe
|
||||||
CmdProbeInputs CmdProbeInputs `json:"cmdProbe/inputs,omitempty"`
|
CmdProbeInputs *CmdProbeInputs `json:"cmdProbe/inputs,omitempty"`
|
||||||
// inputs needed for the prometheus probe
|
// inputs needed for the prometheus probe
|
||||||
PromProbeInputs PromProbeInputs `json:"promProbe/inputs,omitempty"`
|
PromProbeInputs *PromProbeInputs `json:"promProbe/inputs,omitempty"`
|
||||||
|
// inputs needed for the SLO probe
|
||||||
|
SLOProbeInputs *SLOProbeInputs `json:"sloProbe/inputs,omitempty"`
|
||||||
// RunProperty contains timeout, retry and interval for the probe
|
// RunProperty contains timeout, retry and interval for the probe
|
||||||
RunProperties RunProperty `json:"runProperties,omitempty"`
|
RunProperties RunProperty `json:"runProperties"`
|
||||||
// mode for k8s probe
|
// mode for k8s probe
|
||||||
// it can be SOT, EOT, Edge
|
// it can be SOT, EOT, Edge
|
||||||
Mode string `json:"mode,omitempty"`
|
Mode string `json:"mode"`
|
||||||
// Data contains the manifest/data for the resource, which need to be created
|
// Data contains the manifest/data for the resource, which need to be created
|
||||||
// it supported for create operation only
|
// it supported for create operation only
|
||||||
Data string `json:"data,omitempty"`
|
Data string `json:"data,omitempty"`
|
||||||
|
@ -205,9 +247,11 @@ type K8sProbeInputs struct {
|
||||||
// group of the resource
|
// group of the resource
|
||||||
Group string `json:"group,omitempty"`
|
Group string `json:"group,omitempty"`
|
||||||
// apiversion of the resource
|
// apiversion of the resource
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version"`
|
||||||
// kind of resource
|
// kind of resource
|
||||||
Resource string `json:"resource,omitempty"`
|
Resource string `json:"resource"`
|
||||||
|
// ResourceNames to get the resources using their list of comma separated names
|
||||||
|
ResourceNames string `json:"resourceNames,omitempty"`
|
||||||
// namespace of the resource
|
// namespace of the resource
|
||||||
Namespace string `json:"namespace,omitempty"`
|
Namespace string `json:"namespace,omitempty"`
|
||||||
// fieldselector to get the resource using fields selector
|
// fieldselector to get the resource using fields selector
|
||||||
|
@ -216,24 +260,24 @@ type K8sProbeInputs struct {
|
||||||
LabelSelector string `json:"labelSelector,omitempty"`
|
LabelSelector string `json:"labelSelector,omitempty"`
|
||||||
// Operation performed by the k8s probe
|
// Operation performed by the k8s probe
|
||||||
// it can be create, delete, present, absent
|
// it can be create, delete, present, absent
|
||||||
Operation string `json:"operation,omitempty"`
|
Operation string `json:"operation"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//CmdProbeInputs contains all the inputs required for cmd probe
|
// CmdProbeInputs contains all the inputs required for cmd probe
|
||||||
type CmdProbeInputs struct {
|
type CmdProbeInputs struct {
|
||||||
// Command need to be executed for the probe
|
// Command need to be executed for the probe
|
||||||
Command string `json:"command,omitempty"`
|
Command string `json:"command"`
|
||||||
// Comparator check for the correctness of the probe output
|
// Comparator check for the correctness of the probe output
|
||||||
Comparator ComparatorInfo `json:"comparator,omitempty"`
|
Comparator ComparatorInfo `json:"comparator"`
|
||||||
// The source where we have to run the command
|
// The source where we have to run the command
|
||||||
// It will run in inline(inside experiment itself) mode if source is nil
|
// It will run in inline(inside experiment itself) mode if source is nil
|
||||||
Source SourceDetails `json:"source,omitempty"`
|
Source *SourceDetails `json:"source,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SourceDetails contains source details of the cmdProbe
|
// SourceDetails contains source details of the cmdProbe
|
||||||
type SourceDetails struct {
|
type SourceDetails struct {
|
||||||
// Image for the source pod
|
// Image for the source pod
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image"`
|
||||||
// HostNetwork define the hostNetwork of the external pod
|
// HostNetwork define the hostNetwork of the external pod
|
||||||
// it supports boolean values and default value is false
|
// it supports boolean values and default value is false
|
||||||
HostNetwork bool `json:"hostNetwork,omitempty"`
|
HostNetwork bool `json:"hostNetwork,omitempty"`
|
||||||
|
@ -256,6 +300,8 @@ type SourceDetails struct {
|
||||||
Privileged bool `json:"privileged,omitempty"`
|
Privileged bool `json:"privileged,omitempty"`
|
||||||
// NodeSelector for the source pod
|
// NodeSelector for the source pod
|
||||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
|
// Tolerations for the source pod
|
||||||
|
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
|
||||||
// Volumes for the source pod
|
// Volumes for the source pod
|
||||||
Volumes []corev1.Volume `json:"volumes,omitempty"`
|
Volumes []corev1.Volume `json:"volumes,omitempty"`
|
||||||
// VolumesMount for the source pod
|
// VolumesMount for the source pod
|
||||||
|
@ -264,16 +310,57 @@ type SourceDetails struct {
|
||||||
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
|
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//PromProbeInputs contains all the inputs required for prometheus probe
|
// PromProbeInputs contains all the inputs required for prometheus probe
|
||||||
type PromProbeInputs struct {
|
type PromProbeInputs struct {
|
||||||
// Endpoint for the prometheus probe
|
// Endpoint for the prometheus probe
|
||||||
Endpoint string `json:"endpoint,omitempty"`
|
Endpoint string `json:"endpoint"`
|
||||||
// Query to get promethus metrics
|
// Query to get promethus metrics
|
||||||
Query string `json:"query,omitempty"`
|
Query string `json:"query,omitempty"`
|
||||||
// QueryPath contains filePath, which contains prometheus query
|
// QueryPath contains filePath, which contains prometheus query
|
||||||
QueryPath string `json:"queryPath,omitempty"`
|
QueryPath string `json:"queryPath,omitempty"`
|
||||||
// Comparator check for the correctness of the probe output
|
// Comparator check for the correctness of the probe output
|
||||||
Comparator ComparatorInfo `json:"comparator,omitempty"`
|
Comparator ComparatorInfo `json:"comparator"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SLOProbeInputs contains all the inputs required for SLO probe
|
||||||
|
type SLOProbeInputs struct {
|
||||||
|
// PlatformEndpoint for the monitoring service endpoint
|
||||||
|
PlatformEndpoint string `json:"platformEndpoint"`
|
||||||
|
// SLOIdentifier for fetching the details of the SLO
|
||||||
|
SLOIdentifier string `json:"sloIdentifier"`
|
||||||
|
// InsecureSkipVerify flag to skip certificate checks
|
||||||
|
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||||
|
// EvaluationWindow is the time period for which the metrics will be evaluated
|
||||||
|
EvaluationWindow *EvaluationWindow `json:"evaluationWindow,omitempty"`
|
||||||
|
// SLOSourceMetadata consists of required metadata details to fetch metric data
|
||||||
|
SLOSourceMetadata SLOSourceMetadata `json:"sloSourceMetadata"`
|
||||||
|
// Comparator check for the correctness of the probe output
|
||||||
|
Comparator ComparatorInfo `json:"comparator"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EvaluationWindow is the time period for which the SLO probe will work
|
||||||
|
type EvaluationWindow struct {
|
||||||
|
// Start time of evaluation
|
||||||
|
EvaluationStartTime int `json:"evaluationStartTime,omitempty"`
|
||||||
|
// End time of evaluation
|
||||||
|
EvaluationEndTime int `json:"evaluationEndTime,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SLOSourceMetadata struct {
|
||||||
|
// APITokenSecret for authenticating with the platform service
|
||||||
|
APITokenSecret string `json:"apiTokenSecret"`
|
||||||
|
// Scope required for fetching details
|
||||||
|
Scope Identifier `json:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifier required for fetching details from the Platform APIs
|
||||||
|
type Identifier struct {
|
||||||
|
// AccountIdentifier for account ID
|
||||||
|
AccountIdentifier string `json:"accountIdentifier"`
|
||||||
|
// OrgIdentifier for organization ID
|
||||||
|
OrgIdentifier string `json:"orgIdentifier"`
|
||||||
|
// ProjectIdentifier for project ID
|
||||||
|
ProjectIdentifier string `json:"projectIdentifier"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComparatorInfo contains the comparator details
|
// ComparatorInfo contains the comparator details
|
||||||
|
@ -284,34 +371,34 @@ type ComparatorInfo struct {
|
||||||
// Criteria for matching data
|
// Criteria for matching data
|
||||||
// it supports >=, <=, ==, >, <, != for int and float
|
// it supports >=, <=, ==, >, <, != for int and float
|
||||||
// it supports equal, notEqual, contains for string
|
// it supports equal, notEqual, contains for string
|
||||||
Criteria string `json:"criteria,omitempty"`
|
Criteria string `json:"criteria"`
|
||||||
// Value contains relative value for criteria
|
// Value contains relative value for criteria
|
||||||
Value string `json:"value,omitempty"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//HTTPProbeInputs contains all the inputs required for http probe
|
// HTTPProbeInputs contains all the inputs required for http probe
|
||||||
type HTTPProbeInputs struct {
|
type HTTPProbeInputs struct {
|
||||||
// URL which needs to curl, to check the status
|
// URL which needs to curl, to check the status
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url"`
|
||||||
// InsecureSkipVerify flag to skip certificate checks
|
// InsecureSkipVerify flag to skip certificate checks
|
||||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||||
// Method define the http method, it can be get or post
|
// Method define the http method, it can be get or post
|
||||||
Method HTTPMethod `json:"method,omitempty"`
|
Method HTTPMethod `json:"method"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPMethod define the http method details
|
// HTTPMethod define the http method details
|
||||||
type HTTPMethod struct {
|
type HTTPMethod struct {
|
||||||
Get GetMethod `json:"get,omitempty"`
|
Get *GetMethod `json:"get,omitempty"`
|
||||||
Post PostMethod `json:"post,omitempty"`
|
Post *PostMethod `json:"post,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMethod define the http Get method
|
// GetMethod define the http Get method
|
||||||
type GetMethod struct {
|
type GetMethod struct {
|
||||||
// Criteria for matching data
|
// Criteria for matching data
|
||||||
// it supports == != operations
|
// it supports == != operations
|
||||||
Criteria string `json:"criteria,omitempty"`
|
Criteria string `json:"criteria"`
|
||||||
// Value contains relative value for criteria
|
// Value contains relative value for criteria
|
||||||
ResponseCode string `json:"responseCode,omitempty"`
|
ResponseCode string `json:"responseCode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostMethod define the http Post method
|
// PostMethod define the http Post method
|
||||||
|
@ -324,24 +411,33 @@ type PostMethod struct {
|
||||||
BodyPath string `json:"bodyPath,omitempty"`
|
BodyPath string `json:"bodyPath,omitempty"`
|
||||||
// Criteria for matching data
|
// Criteria for matching data
|
||||||
// it supports == != operations
|
// it supports == != operations
|
||||||
Criteria string `json:"criteria,omitempty"`
|
Criteria string `json:"criteria"`
|
||||||
// Value contains relative value for criteria
|
// Value contains relative value for criteria
|
||||||
ResponseCode string `json:"responseCode,omitempty"`
|
ResponseCode string `json:"responseCode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//RunProperty contains timeout, retry and interval for the probe
|
// RunProperty contains timeout, retry and interval for the probe
|
||||||
type RunProperty struct {
|
type RunProperty struct {
|
||||||
//ProbeTimeout contains timeout for the probe
|
//ProbeTimeout contains timeout for the probe
|
||||||
ProbeTimeout int `json:"probeTimeout,omitempty"`
|
ProbeTimeout string `json:"probeTimeout"`
|
||||||
// Interval contains the inverval for the probe
|
// Interval contains the interval for the probe
|
||||||
Interval int `json:"interval,omitempty"`
|
Interval string `json:"interval"`
|
||||||
// Retry contains the retry count for the probe
|
// Retry contains the retry count for the probe
|
||||||
Retry int `json:"retry,omitempty"`
|
Retry int `json:"retry,omitempty"`
|
||||||
|
// Attempt contains the total attempt count for the probe
|
||||||
|
Attempt int `json:"attempt,omitempty"`
|
||||||
//ProbePollingInterval contains time interval, for which continuous probe should be sleep
|
//ProbePollingInterval contains time interval, for which continuous probe should be sleep
|
||||||
// after each iteration
|
// after each iteration
|
||||||
ProbePollingInterval int `json:"probePollingInterval,omitempty"`
|
ProbePollingInterval string `json:"probePollingInterval,omitempty"`
|
||||||
//InitialDelaySeconds time interval for which probe will wait before run
|
//InitialDelaySeconds time interval for which probe will wait before run
|
||||||
InitialDelaySeconds int `json:"initialDelaySeconds,omitempty"`
|
InitialDelaySeconds int `json:"initialDelaySeconds,omitempty"`
|
||||||
|
//InitialDelay time interval for which probe will wait before run
|
||||||
|
InitialDelay string `json:"initialDelay,omitempty"`
|
||||||
|
// EvaluationTimeout is the timeout window in which the SLO metrics
|
||||||
|
// will be fetched and will be evaluated
|
||||||
|
EvaluationTimeout string `json:"evaluationTimeout,omitempty"`
|
||||||
|
// Verbosity contains flags for type of logging while running the Continuous and onChaos Probes
|
||||||
|
Verbosity string `json:"verbosity,omitempty"`
|
||||||
// StopOnFailure contains flag to stop/continue experiment execution, if probe fails
|
// StopOnFailure contains flag to stop/continue experiment execution, if probe fails
|
||||||
// it will stop the experiment execution, if provided true
|
// it will stop the experiment execution, if provided true
|
||||||
// it will continue the experiment execution, if provided false or not provided(default case)
|
// it will continue the experiment execution, if provided false or not provided(default case)
|
||||||
|
|
|
@ -40,8 +40,14 @@ const (
|
||||||
ResultPhaseRunning ResultPhase = "Running"
|
ResultPhaseRunning ResultPhase = "Running"
|
||||||
// ResultPhaseCompleted is phase of chaosresult which is in completed state
|
// ResultPhaseCompleted is phase of chaosresult which is in completed state
|
||||||
ResultPhaseCompleted ResultPhase = "Completed"
|
ResultPhaseCompleted ResultPhase = "Completed"
|
||||||
|
// Retained For Backward Compatibility: ResultPhaseCompletedWithError is phase of chaosresult when probe is failed in 3.0beta5
|
||||||
|
ResultPhaseCompletedWithError ResultPhase = "Completed_With_Error"
|
||||||
|
// ResultPhaseCompletedWithProbeFailure is phase of chaosresult when probe is failed from 3.0beta6
|
||||||
|
ResultPhaseCompletedWithProbeFailure ResultPhase = "Completed_With_Probe_Failure"
|
||||||
// ResultPhaseStopped is phase of chaosresult which is in stopped state
|
// ResultPhaseStopped is phase of chaosresult which is in stopped state
|
||||||
ResultPhaseStopped ResultPhase = "Stopped"
|
ResultPhaseStopped ResultPhase = "Stopped"
|
||||||
|
// ResultPhaseError is phase of chaosresult, which indicates that the experiment is terminated due to an error
|
||||||
|
ResultPhaseError ResultPhase = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResultVerdict is typecasted to string for supporting the values below.
|
// ResultVerdict is typecasted to string for supporting the values below.
|
||||||
|
@ -54,6 +60,10 @@ const (
|
||||||
ResultVerdictFailed ResultVerdict = "Fail"
|
ResultVerdictFailed ResultVerdict = "Fail"
|
||||||
// ResultVerdictStopped is verdict of chaosresult when experiment aborted
|
// ResultVerdictStopped is verdict of chaosresult when experiment aborted
|
||||||
ResultVerdictStopped ResultVerdict = "Stopped"
|
ResultVerdictStopped ResultVerdict = "Stopped"
|
||||||
|
// ResultVerdictAwaited is verdict of chaosresult when experiment is yet to evaluated(experiment is in running state)
|
||||||
|
ResultVerdictAwaited ResultVerdict = "Awaited"
|
||||||
|
// ResultVerdictError is verdict of chaosresult when experiment is completed because of an error
|
||||||
|
ResultVerdictError ResultVerdict = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProbeVerdict string
|
type ProbeVerdict string
|
||||||
|
@ -116,12 +126,20 @@ type TestStatus struct {
|
||||||
Phase ResultPhase `json:"phase"`
|
Phase ResultPhase `json:"phase"`
|
||||||
// Verdict defines whether an experiment result is pass or fail
|
// Verdict defines whether an experiment result is pass or fail
|
||||||
Verdict ResultVerdict `json:"verdict"`
|
Verdict ResultVerdict `json:"verdict"`
|
||||||
// FailStep defines step where the experiments fails
|
// ErrorOutput defines error message and error code
|
||||||
FailStep string `json:"failStep,omitempty"`
|
ErrorOutput *ErrorOutput `json:"errorOutput,omitempty"`
|
||||||
// ProbeSuccessPercentage defines the score of the probes
|
// ProbeSuccessPercentage defines the score of the probes
|
||||||
ProbeSuccessPercentage string `json:"probeSuccessPercentage,omitempty"`
|
ProbeSuccessPercentage string `json:"probeSuccessPercentage,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorOutput defines error reason and error code
|
||||||
|
type ErrorOutput struct {
|
||||||
|
// ErrorCode defines error code of the experiment
|
||||||
|
ErrorCode string `json:"errorCode,omitempty"`
|
||||||
|
// Reason contains the error reason
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
//+kubebuilder:object:root=true
|
//+kubebuilder:object:root=true
|
||||||
//+kubebuilder:subresource:status
|
//+kubebuilder:subresource:status
|
||||||
// +genclient
|
// +genclient
|
||||||
|
|
|
@ -15,8 +15,8 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package v1alpha1 contains API Schema definitions for the litmuschaos.io v1alpha1 API group
|
// Package v1alpha1 contains API Schema definitions for the litmuschaos.io v1alpha1 API group
|
||||||
//+kubebuilder:object:generate=true
|
// +kubebuilder:object:generate=true
|
||||||
//+groupName=litmuschaos.io
|
// +groupName=litmuschaos.io
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -113,6 +113,11 @@ func (in *ChaosEngineSpec) DeepCopyInto(out *ChaosEngineSpec) {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if in.Selectors != nil {
|
||||||
|
in, out := &in.Selectors, &out.Selectors
|
||||||
|
*out = new(Selector)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChaosEngineSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChaosEngineSpec.
|
||||||
|
@ -314,7 +319,7 @@ func (in *ChaosResultSpec) DeepCopy() *ChaosResultSpec {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ChaosResultStatus) DeepCopyInto(out *ChaosResultStatus) {
|
func (in *ChaosResultStatus) DeepCopyInto(out *ChaosResultStatus) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.ExperimentStatus = in.ExperimentStatus
|
in.ExperimentStatus.DeepCopyInto(&out.ExperimentStatus)
|
||||||
if in.ProbeStatuses != nil {
|
if in.ProbeStatuses != nil {
|
||||||
in, out := &in.ProbeStatuses, &out.ProbeStatuses
|
in, out := &in.ProbeStatuses, &out.ProbeStatuses
|
||||||
*out = make([]ProbeStatuses, len(*in))
|
*out = make([]ProbeStatuses, len(*in))
|
||||||
|
@ -341,7 +346,11 @@ func (in *ChaosResultStatus) DeepCopy() *ChaosResultStatus {
|
||||||
func (in *CmdProbeInputs) DeepCopyInto(out *CmdProbeInputs) {
|
func (in *CmdProbeInputs) DeepCopyInto(out *CmdProbeInputs) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.Comparator = in.Comparator
|
out.Comparator = in.Comparator
|
||||||
in.Source.DeepCopyInto(&out.Source)
|
if in.Source != nil {
|
||||||
|
in, out := &in.Source, &out.Source
|
||||||
|
*out = new(SourceDetails)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CmdProbeInputs.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CmdProbeInputs.
|
||||||
|
@ -373,6 +382,13 @@ func (in *ComparatorInfo) DeepCopy() *ComparatorInfo {
|
||||||
func (in *ComponentParams) DeepCopyInto(out *ComponentParams) {
|
func (in *ComponentParams) DeepCopyInto(out *ComponentParams) {
|
||||||
*out = *in
|
*out = *in
|
||||||
in.Runner.DeepCopyInto(&out.Runner)
|
in.Runner.DeepCopyInto(&out.Runner)
|
||||||
|
if in.Sidecar != nil {
|
||||||
|
in, out := &in.Sidecar, &out.Sidecar
|
||||||
|
*out = make([]Sidecar, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentParams.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentParams.
|
||||||
|
@ -407,6 +423,36 @@ func (in *ConfigMap) DeepCopy() *ConfigMap {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ErrorOutput) DeepCopyInto(out *ErrorOutput) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ErrorOutput.
|
||||||
|
func (in *ErrorOutput) DeepCopy() *ErrorOutput {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ErrorOutput)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *EvaluationWindow) DeepCopyInto(out *EvaluationWindow) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EvaluationWindow.
|
||||||
|
func (in *EvaluationWindow) DeepCopy() *EvaluationWindow {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(EvaluationWindow)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ExperimentAttributes) DeepCopyInto(out *ExperimentAttributes) {
|
func (in *ExperimentAttributes) DeepCopyInto(out *ExperimentAttributes) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -613,8 +659,16 @@ func (in *GetMethod) DeepCopy() *GetMethod {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HTTPMethod) DeepCopyInto(out *HTTPMethod) {
|
func (in *HTTPMethod) DeepCopyInto(out *HTTPMethod) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.Get = in.Get
|
if in.Get != nil {
|
||||||
out.Post = in.Post
|
in, out := &in.Get, &out.Get
|
||||||
|
*out = new(GetMethod)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.Post != nil {
|
||||||
|
in, out := &in.Post, &out.Post
|
||||||
|
*out = new(PostMethod)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPMethod.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPMethod.
|
||||||
|
@ -630,7 +684,7 @@ func (in *HTTPMethod) DeepCopy() *HTTPMethod {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HTTPProbeInputs) DeepCopyInto(out *HTTPProbeInputs) {
|
func (in *HTTPProbeInputs) DeepCopyInto(out *HTTPProbeInputs) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.Method = in.Method
|
in.Method.DeepCopyInto(&out.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPProbeInputs.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPProbeInputs.
|
||||||
|
@ -678,6 +732,21 @@ func (in *HostFile) DeepCopy() *HostFile {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Identifier) DeepCopyInto(out *Identifier) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Identifier.
|
||||||
|
func (in *Identifier) DeepCopy() *Identifier {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Identifier)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *K8sProbeInputs) DeepCopyInto(out *K8sProbeInputs) {
|
func (in *K8sProbeInputs) DeepCopyInto(out *K8sProbeInputs) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -693,6 +762,21 @@ func (in *K8sProbeInputs) DeepCopy() *K8sProbeInputs {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Pod) DeepCopyInto(out *Pod) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Pod.
|
||||||
|
func (in *Pod) DeepCopy() *Pod {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Pod)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *PostMethod) DeepCopyInto(out *PostMethod) {
|
func (in *PostMethod) DeepCopyInto(out *PostMethod) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -711,10 +795,31 @@ func (in *PostMethod) DeepCopy() *PostMethod {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ProbeAttributes) DeepCopyInto(out *ProbeAttributes) {
|
func (in *ProbeAttributes) DeepCopyInto(out *ProbeAttributes) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.K8sProbeInputs = in.K8sProbeInputs
|
if in.K8sProbeInputs != nil {
|
||||||
out.HTTPProbeInputs = in.HTTPProbeInputs
|
in, out := &in.K8sProbeInputs, &out.K8sProbeInputs
|
||||||
in.CmdProbeInputs.DeepCopyInto(&out.CmdProbeInputs)
|
*out = new(K8sProbeInputs)
|
||||||
out.PromProbeInputs = in.PromProbeInputs
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.HTTPProbeInputs != nil {
|
||||||
|
in, out := &in.HTTPProbeInputs, &out.HTTPProbeInputs
|
||||||
|
*out = new(HTTPProbeInputs)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
if in.CmdProbeInputs != nil {
|
||||||
|
in, out := &in.CmdProbeInputs, &out.CmdProbeInputs
|
||||||
|
*out = new(CmdProbeInputs)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
if in.PromProbeInputs != nil {
|
||||||
|
in, out := &in.PromProbeInputs, &out.PromProbeInputs
|
||||||
|
*out = new(PromProbeInputs)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.SLOProbeInputs != nil {
|
||||||
|
in, out := &in.SLOProbeInputs, &out.SLOProbeInputs
|
||||||
|
*out = new(SLOProbeInputs)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
out.RunProperties = in.RunProperties
|
out.RunProperties = in.RunProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,6 +966,44 @@ func (in *RunnerInfo) DeepCopy() *RunnerInfo {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *SLOProbeInputs) DeepCopyInto(out *SLOProbeInputs) {
|
||||||
|
*out = *in
|
||||||
|
if in.EvaluationWindow != nil {
|
||||||
|
in, out := &in.EvaluationWindow, &out.EvaluationWindow
|
||||||
|
*out = new(EvaluationWindow)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
out.SLOSourceMetadata = in.SLOSourceMetadata
|
||||||
|
out.Comparator = in.Comparator
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SLOProbeInputs.
|
||||||
|
func (in *SLOProbeInputs) DeepCopy() *SLOProbeInputs {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(SLOProbeInputs)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *SLOSourceMetadata) DeepCopyInto(out *SLOSourceMetadata) {
|
||||||
|
*out = *in
|
||||||
|
out.Scope = in.Scope
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SLOSourceMetadata.
|
||||||
|
func (in *SLOSourceMetadata) DeepCopy() *SLOSourceMetadata {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(SLOSourceMetadata)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Secret) DeepCopyInto(out *Secret) {
|
func (in *Secret) DeepCopyInto(out *Secret) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -893,6 +1036,65 @@ func (in *SecurityContext) DeepCopy() *SecurityContext {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Selector) DeepCopyInto(out *Selector) {
|
||||||
|
*out = *in
|
||||||
|
if in.Workloads != nil {
|
||||||
|
in, out := &in.Workloads, &out.Workloads
|
||||||
|
*out = make([]Workload, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.Pods != nil {
|
||||||
|
in, out := &in.Pods, &out.Pods
|
||||||
|
*out = make([]Pod, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Selector.
|
||||||
|
func (in *Selector) DeepCopy() *Selector {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Selector)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Sidecar) DeepCopyInto(out *Sidecar) {
|
||||||
|
*out = *in
|
||||||
|
if in.Secrets != nil {
|
||||||
|
in, out := &in.Secrets, &out.Secrets
|
||||||
|
*out = make([]Secret, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.EnvFrom != nil {
|
||||||
|
in, out := &in.EnvFrom, &out.EnvFrom
|
||||||
|
*out = make([]v1.EnvFromSource, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.ENV != nil {
|
||||||
|
in, out := &in.ENV, &out.ENV
|
||||||
|
*out = make([]v1.EnvVar, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Sidecar.
|
||||||
|
func (in *Sidecar) DeepCopy() *Sidecar {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Sidecar)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *SourceDetails) DeepCopyInto(out *SourceDetails) {
|
func (in *SourceDetails) DeepCopyInto(out *SourceDetails) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -934,6 +1136,13 @@ func (in *SourceDetails) DeepCopyInto(out *SourceDetails) {
|
||||||
(*out)[key] = val
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if in.Tolerations != nil {
|
||||||
|
in, out := &in.Tolerations, &out.Tolerations
|
||||||
|
*out = make([]v1.Toleration, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
if in.Volumes != nil {
|
if in.Volumes != nil {
|
||||||
in, out := &in.Volumes, &out.Volumes
|
in, out := &in.Volumes, &out.Volumes
|
||||||
*out = make([]v1.Volume, len(*in))
|
*out = make([]v1.Volume, len(*in))
|
||||||
|
@ -998,6 +1207,11 @@ func (in *TargetDetails) DeepCopy() *TargetDetails {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TestStatus) DeepCopyInto(out *TestStatus) {
|
func (in *TestStatus) DeepCopyInto(out *TestStatus) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.ErrorOutput != nil {
|
||||||
|
in, out := &in.ErrorOutput, &out.ErrorOutput
|
||||||
|
*out = new(ErrorOutput)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestStatus.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestStatus.
|
||||||
|
@ -1009,3 +1223,18 @@ func (in *TestStatus) DeepCopy() *TestStatus {
|
||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Workload) DeepCopyInto(out *Workload) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workload.
|
||||||
|
func (in *Workload) DeepCopy() *Workload {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Workload)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
|
@ -17,13 +17,15 @@ RUN go env
|
||||||
RUN CGO_ENABLED=0 go build -buildvcs=false -o /output/chaos-operator -v ./main.go
|
RUN CGO_ENABLED=0 go build -buildvcs=false -o /output/chaos-operator -v ./main.go
|
||||||
|
|
||||||
# Packaging stage
|
# Packaging stage
|
||||||
# Image source: https://github.com/litmuschaos/test-tools/blob/master/custom/hardened-alpine/infra/Dockerfile
|
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.5
|
||||||
# The base image is non-root (have litmus user) with default litmus directory.
|
|
||||||
FROM litmuschaos/infra-alpine
|
|
||||||
|
|
||||||
LABEL maintainer="LitmusChaos"
|
LABEL maintainer="LitmusChaos"
|
||||||
|
|
||||||
ENV OPERATOR=/usr/local/bin/chaos-operator
|
ENV OPERATOR=/usr/local/bin/chaos-operator
|
||||||
|
|
||||||
COPY --from=builder /output/chaos-operator ${OPERATOR}
|
COPY --from=builder /output/chaos-operator ${OPERATOR}
|
||||||
|
RUN chown 65534:0 ${OPERATOR} && chmod 755 ${OPERATOR}
|
||||||
|
|
||||||
|
USER 65534
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/chaos-operator"]
|
ENTRYPOINT ["/usr/local/bin/chaos-operator"]
|
||||||
|
|
|
@ -19,12 +19,15 @@ package controllers
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
|
litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
|
||||||
"github.com/litmuschaos/chaos-operator/pkg/analytics"
|
"github.com/litmuschaos/chaos-operator/pkg/analytics"
|
||||||
dynamicclientset "github.com/litmuschaos/chaos-operator/pkg/client/dynamic"
|
dynamicclientset "github.com/litmuschaos/chaos-operator/pkg/client/dynamic"
|
||||||
clientset "github.com/litmuschaos/chaos-operator/pkg/client/kubernetes"
|
|
||||||
"github.com/litmuschaos/chaos-operator/pkg/resource"
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
||||||
"github.com/litmuschaos/chaos-operator/pkg/utils"
|
"github.com/litmuschaos/chaos-operator/pkg/utils"
|
||||||
"github.com/litmuschaos/chaos-operator/pkg/utils/retry"
|
"github.com/litmuschaos/chaos-operator/pkg/utils/retry"
|
||||||
|
@ -39,14 +42,10 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const finalizer = "chaosengine.litmuschaos.io/finalizer"
|
const finalizer = "chaosengine.litmuschaos.io/finalizer"
|
||||||
|
@ -104,13 +103,16 @@ func (r *ChaosEngineReconciler) Reconcile(ctx context.Context, request ctrl.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the reconcile by setting default values into ChaosEngine
|
// Start the reconcile by setting default values into ChaosEngine
|
||||||
if err := r.initEngine(engine); err != nil {
|
if requeue, err := r.initEngine(engine); err != nil {
|
||||||
|
if requeue {
|
||||||
|
return reconcile.Result{Requeue: true}, nil
|
||||||
|
}
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handling of normal execution of ChaosEngine
|
// Handling of normal execution of ChaosEngine
|
||||||
if engine.Instance.Spec.EngineState == litmuschaosv1alpha1.EngineStateActive && engine.Instance.Status.EngineStatus == litmuschaosv1alpha1.EngineStatusInitialized {
|
if engine.Instance.Spec.EngineState == litmuschaosv1alpha1.EngineStateActive && engine.Instance.Status.EngineStatus == litmuschaosv1alpha1.EngineStatusInitialized {
|
||||||
return r.reconcileForCreationAndRunning(engine, reqLogger)
|
return r.reconcileForCreationAndRunning(engine, *reqLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handling Graceful completion of ChaosEngine
|
// Handling Graceful completion of ChaosEngine
|
||||||
|
@ -137,24 +139,16 @@ func (r *ChaosEngineReconciler) Reconcile(ctx context.Context, request ctrl.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
// getChaosRunnerENV return the env required for chaos-runner
|
// getChaosRunnerENV return the env required for chaos-runner
|
||||||
func getChaosRunnerENV(cr *litmuschaosv1alpha1.ChaosEngine, aExList []string, ClientUUID string) []corev1.EnvVar {
|
func getChaosRunnerENV(engine *chaosTypes.EngineInfo, ClientUUID string) []corev1.EnvVar {
|
||||||
appNS := cr.Spec.Appinfo.Appns
|
|
||||||
if appNS == "" {
|
|
||||||
appNS = cr.Namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
var envDetails utils.ENVDetails
|
var envDetails utils.ENVDetails
|
||||||
envDetails.SetEnv("CHAOSENGINE", cr.Name).
|
envDetails.SetEnv("CHAOSENGINE", engine.Instance.Name).
|
||||||
SetEnv("APP_LABEL", cr.Spec.Appinfo.Applabel).
|
SetEnv("TARGETS", engine.Targets).
|
||||||
SetEnv("APP_KIND", cr.Spec.Appinfo.AppKind).
|
SetEnv("EXPERIMENT_LIST", fmt.Sprint(strings.Join(engine.AppExperiments, ","))).
|
||||||
SetEnv("APP_NAMESPACE", appNS).
|
SetEnv("CHAOS_SVC_ACC", engine.Instance.Spec.ChaosServiceAccount).
|
||||||
SetEnv("EXPERIMENT_LIST", fmt.Sprint(strings.Join(aExList, ","))).
|
SetEnv("AUXILIARY_APPINFO", engine.Instance.Spec.AuxiliaryAppInfo).
|
||||||
SetEnv("CHAOS_SVC_ACC", cr.Spec.ChaosServiceAccount).
|
|
||||||
SetEnv("AUXILIARY_APPINFO", cr.Spec.AuxiliaryAppInfo).
|
|
||||||
SetEnv("CLIENT_UUID", ClientUUID).
|
SetEnv("CLIENT_UUID", ClientUUID).
|
||||||
SetEnv("CHAOS_NAMESPACE", cr.Namespace).
|
SetEnv("CHAOS_NAMESPACE", engine.Instance.Namespace)
|
||||||
SetEnv("ANNOTATION_CHECK", cr.Spec.AnnotationCheck).
|
|
||||||
SetEnv("ANNOTATION_KEY", resource.GetAnnotationKey())
|
|
||||||
|
|
||||||
return envDetails.ENV
|
return envDetails.ENV
|
||||||
}
|
}
|
||||||
|
@ -175,10 +169,15 @@ func getChaosRunnerLabels(cr *litmuschaosv1alpha1.ChaosEngine) map[string]string
|
||||||
|
|
||||||
// newGoRunnerPodForCR defines a new go-based Runner Pod
|
// newGoRunnerPodForCR defines a new go-based Runner Pod
|
||||||
func (r *ChaosEngineReconciler) newGoRunnerPodForCR(engine *chaosTypes.EngineInfo) (*corev1.Pod, error) {
|
func (r *ChaosEngineReconciler) newGoRunnerPodForCR(engine *chaosTypes.EngineInfo) (*corev1.Pod, error) {
|
||||||
|
var experiment litmuschaosv1alpha1.ChaosExperiment
|
||||||
|
if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: engine.Instance.Spec.Experiments[0].Name, Namespace: engine.Instance.Namespace}, &experiment); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
engine.VolumeOpts.VolumeOperations(engine.Instance.Spec.Components.Runner.ConfigMaps, engine.Instance.Spec.Components.Runner.Secrets)
|
engine.VolumeOpts.VolumeOperations(engine.Instance.Spec.Components.Runner.ConfigMaps, engine.Instance.Spec.Components.Runner.Secrets)
|
||||||
|
|
||||||
containerForRunner := container.NewBuilder().
|
containerForRunner := container.NewBuilder().
|
||||||
WithEnvsNew(getChaosRunnerENV(engine.Instance, engine.AppExperiments, analytics.ClientUUID)).
|
WithEnvsNew(getChaosRunnerENV(engine, analytics.ClientUUID)).
|
||||||
WithName("chaos-runner").
|
WithName("chaos-runner").
|
||||||
WithImage(engine.Instance.Spec.Components.Runner.Image).
|
WithImage(engine.Instance.Spec.Components.Runner.Image).
|
||||||
WithImagePullPolicy(corev1.PullIfNotPresent)
|
WithImagePullPolicy(corev1.PullIfNotPresent)
|
||||||
|
@ -203,6 +202,10 @@ func (r *ChaosEngineReconciler) newGoRunnerPodForCR(engine *chaosTypes.EngineInf
|
||||||
containerForRunner.WithResourceRequirements(engine.Instance.Spec.Components.Runner.Resources)
|
containerForRunner.WithResourceRequirements(engine.Instance.Spec.Components.Runner.Resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(experiment.Spec.Definition.SecurityContext.ContainerSecurityContext, corev1.SecurityContext{}) {
|
||||||
|
containerForRunner.WithSecurityContext(experiment.Spec.Definition.SecurityContext.ContainerSecurityContext)
|
||||||
|
}
|
||||||
|
|
||||||
podForRunner := pod.NewBuilder().
|
podForRunner := pod.NewBuilder().
|
||||||
WithName(engine.Instance.Name + "-runner").
|
WithName(engine.Instance.Name + "-runner").
|
||||||
WithNamespace(engine.Instance.Namespace).
|
WithNamespace(engine.Instance.Namespace).
|
||||||
|
@ -228,6 +231,10 @@ func (r *ChaosEngineReconciler) newGoRunnerPodForCR(engine *chaosTypes.EngineInf
|
||||||
podForRunner.WithImagePullSecrets(engine.Instance.Spec.Components.Runner.ImagePullSecrets)
|
podForRunner.WithImagePullSecrets(engine.Instance.Spec.Components.Runner.ImagePullSecrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(experiment.Spec.Definition.SecurityContext.PodSecurityContext, corev1.PodSecurityContext{}) {
|
||||||
|
podForRunner.WithSecurityContext(experiment.Spec.Definition.SecurityContext.PodSecurityContext)
|
||||||
|
}
|
||||||
|
|
||||||
runnerPod, err := podForRunner.Build()
|
runnerPod, err := podForRunner.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -238,29 +245,6 @@ func (r *ChaosEngineReconciler) newGoRunnerPodForCR(engine *chaosTypes.EngineInf
|
||||||
return runnerPod, nil
|
return runnerPod, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializeApplicationInfo to initialize application info
|
|
||||||
func initializeApplicationInfo(instance *litmuschaosv1alpha1.ChaosEngine, appInfo *chaosTypes.ApplicationInfo) (*chaosTypes.ApplicationInfo, error) {
|
|
||||||
if instance == nil {
|
|
||||||
return nil, errors.New("chaosengine is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if instance.Spec.Appinfo.Applabel != "" {
|
|
||||||
appInfo.Label = instance.Spec.Appinfo.Applabel
|
|
||||||
}
|
|
||||||
|
|
||||||
if instance.Spec.Appinfo.Appns != "" {
|
|
||||||
appInfo.Namespace = instance.Spec.Appinfo.Appns
|
|
||||||
} else {
|
|
||||||
appInfo.Namespace = instance.Namespace
|
|
||||||
}
|
|
||||||
appInfo.Kind = instance.Spec.Appinfo.AppKind
|
|
||||||
|
|
||||||
appInfo.ExperimentList = instance.Spec.Experiments
|
|
||||||
appInfo.ServiceAccountName = instance.Spec.ChaosServiceAccount
|
|
||||||
|
|
||||||
return appInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// engineRunnerPod to Check if the engineRunner pod already exists, else create
|
// engineRunnerPod to Check if the engineRunner pod already exists, else create
|
||||||
func engineRunnerPod(runnerPod *podEngineRunner) error {
|
func engineRunnerPod(runnerPod *podEngineRunner) error {
|
||||||
if err := runnerPod.r.Client.Get(context.TODO(), types.NamespacedName{Name: runnerPod.engineRunner.Name, Namespace: runnerPod.engineRunner.Namespace}, runnerPod.pod); err != nil && k8serrors.IsNotFound(err) {
|
if err := runnerPod.r.Client.Get(context.TODO(), types.NamespacedName{Name: runnerPod.engineRunner.Name, Namespace: runnerPod.engineRunner.Namespace}, runnerPod.pod); err != nil && k8serrors.IsNotFound(err) {
|
||||||
|
@ -291,30 +275,8 @@ func (r *ChaosEngineReconciler) getChaosEngineInstance(engine *chaosTypes.Engine
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
engine.Instance = instance
|
engine.Instance = instance
|
||||||
return nil
|
engine.AppInfo = instance.Spec.Appinfo
|
||||||
}
|
engine.Selectors = instance.Spec.Selectors
|
||||||
|
|
||||||
// Get application details
|
|
||||||
func getApplicationDetail(engine *chaosTypes.EngineInfo) error {
|
|
||||||
applicationInfo := &chaosTypes.ApplicationInfo{}
|
|
||||||
|
|
||||||
appInfo, err := initializeApplicationInfo(engine.Instance, applicationInfo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.AppInfo = appInfo
|
|
||||||
var appExperiments []string
|
|
||||||
for _, exp := range appInfo.ExperimentList {
|
|
||||||
appExperiments = append(appExperiments, exp.Name)
|
|
||||||
}
|
|
||||||
engine.AppExperiments = appExperiments
|
|
||||||
|
|
||||||
chaosTypes.Log.Info("App Label derived from Chaosengine is ", "appLabels", appInfo.Label)
|
|
||||||
chaosTypes.Log.Info("App NS derived from Chaosengine is ", "appNamespace", appInfo.Namespace)
|
|
||||||
chaosTypes.Log.Info("Exp list derived from chaosengine is ", "appExpirements", appExperiments)
|
|
||||||
chaosTypes.Log.Info("Runner image derived from chaosengine is", "runnerImage", engine.Instance.Spec.Components.Runner.Image)
|
|
||||||
chaosTypes.Log.Info("Annotation check is ", "annotationCheck", engine.Instance.Spec.AnnotationCheck)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,19 +319,6 @@ func setChaosResourceImage(engine *chaosTypes.EngineInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAnnotationCheck() checks for annotation on the application
|
|
||||||
func getAnnotationCheck(engine *chaosTypes.EngineInfo) error {
|
|
||||||
if engine.Instance.Spec.AnnotationCheck == "" {
|
|
||||||
engine.Instance.Spec.AnnotationCheck = chaosTypes.DefaultAnnotationCheck
|
|
||||||
}
|
|
||||||
|
|
||||||
if engine.Instance.Spec.AnnotationCheck != "true" && engine.Instance.Spec.AnnotationCheck != "false" {
|
|
||||||
return fmt.Errorf("annotationCheck '%s', is not supported it should be either true or false", engine.Instance.Spec.AnnotationCheck)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// reconcileForDelete reconciles for deletion/force deletion of Chaos Engine
|
// reconcileForDelete reconciles for deletion/force deletion of Chaos Engine
|
||||||
func (r *ChaosEngineReconciler) reconcileForDelete(engine *chaosTypes.EngineInfo, request reconcile.Request) (reconcile.Result, error) {
|
func (r *ChaosEngineReconciler) reconcileForDelete(engine *chaosTypes.EngineInfo, request reconcile.Request) (reconcile.Result, error) {
|
||||||
patch := client.MergeFrom(engine.Instance.DeepCopy())
|
patch := client.MergeFrom(engine.Instance.DeepCopy())
|
||||||
|
@ -538,8 +487,11 @@ func (r *ChaosEngineReconciler) reconcileForRestartAfterAbort(engine *chaosTypes
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.updateEngineForRestart(engine); err != nil {
|
if requeue, err := r.updateEngineForRestart(engine); err != nil {
|
||||||
return reconcile.Result{}, nil
|
if requeue {
|
||||||
|
return reconcile.Result{Requeue: true}, nil
|
||||||
|
}
|
||||||
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return reconcile.Result{}, nil
|
return reconcile.Result{}, nil
|
||||||
|
@ -574,7 +526,7 @@ func (r *ChaosEngineReconciler) reconcileForRestartAfterComplete(engine *chaosTy
|
||||||
}
|
}
|
||||||
|
|
||||||
// initEngine initialize Chaos Engine, and add a finalizer to it.
|
// initEngine initialize Chaos Engine, and add a finalizer to it.
|
||||||
func (r *ChaosEngineReconciler) initEngine(engine *chaosTypes.EngineInfo) error {
|
func (r *ChaosEngineReconciler) initEngine(engine *chaosTypes.EngineInfo) (bool, error) {
|
||||||
if engine.Instance.Spec.EngineState == "" {
|
if engine.Instance.Spec.EngineState == "" {
|
||||||
engine.Instance.Spec.EngineState = litmuschaosv1alpha1.EngineStateActive
|
engine.Instance.Spec.EngineState = litmuschaosv1alpha1.EngineStateActive
|
||||||
}
|
}
|
||||||
|
@ -587,32 +539,29 @@ func (r *ChaosEngineReconciler) initEngine(engine *chaosTypes.EngineInfo) error
|
||||||
if engine.Instance.ObjectMeta.Finalizers == nil {
|
if engine.Instance.ObjectMeta.Finalizers == nil {
|
||||||
engine.Instance.ObjectMeta.Finalizers = append(engine.Instance.ObjectMeta.Finalizers, finalizer)
|
engine.Instance.ObjectMeta.Finalizers = append(engine.Instance.ObjectMeta.Finalizers, finalizer)
|
||||||
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
||||||
return fmt.Errorf("unable to initialize ChaosEngine, because of Update Error: %v", err)
|
if k8serrors.IsConflict(err) {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("unable to initialize ChaosEngine, because of Update Error: %v", err)
|
||||||
}
|
}
|
||||||
// generate the ChaosEngineInitialized event once finalizer has been added
|
// generate the ChaosEngineInitialized event once finalizer has been added
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "ChaosEngineInitialized", "Identifying app under test & launching %s", engine.Instance.Name+"-runner")
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "ChaosEngineInitialized", "Identifying app under test & launching %s", engine.Instance.Name+"-runner")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconcileForCreationAndRunning reconciles for Chaos execution of Chaos Engine
|
// reconcileForCreationAndRunning reconciles for Chaos execution of Chaos Engine
|
||||||
func (r *ChaosEngineReconciler) reconcileForCreationAndRunning(engine *chaosTypes.EngineInfo, reqLogger logr.Logger) (reconcile.Result, error) {
|
func (r *ChaosEngineReconciler) reconcileForCreationAndRunning(engine *chaosTypes.EngineInfo, reqLogger logr.Logger) (reconcile.Result, error) {
|
||||||
if err := r.validateAnnotatedApplication(engine); err != nil {
|
var runner corev1.Pod
|
||||||
if stopEngineWithAnnotationErrorMessage := r.updateEngineState(engine, litmuschaosv1alpha1.EngineStateStop); stopEngineWithAnnotationErrorMessage != nil {
|
if err := r.Client.Get(context.TODO(), types.NamespacedName{Name: engine.Instance.Name + "-runner", Namespace: engine.Instance.Namespace}, &runner); err != nil {
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos stop) Unable to update chaosengine")
|
if k8serrors.IsNotFound(err) {
|
||||||
return reconcile.Result{}, fmt.Errorf("unable to Update Engine State: %v", err)
|
return r.createRunnerPod(engine, reqLogger)
|
||||||
}
|
}
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the engineRunner pod already exists, else create
|
|
||||||
if err := r.checkEngineRunnerPod(engine, reqLogger); err != nil {
|
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos start) Unable to get chaos resources")
|
|
||||||
return reconcile.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
isCompleted, err := r.checkRunnerContainerCompletedStatus(engine)
|
isCompleted, err := r.checkRunnerContainerCompletedStatus(engine)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if k8serrors.IsNotFound(err) {
|
if k8serrors.IsNotFound(err) {
|
||||||
|
@ -623,15 +572,103 @@ func (r *ChaosEngineReconciler) reconcileForCreationAndRunning(engine *chaosType
|
||||||
}
|
}
|
||||||
|
|
||||||
if isCompleted {
|
if isCompleted {
|
||||||
if err := r.updateEngineForComplete(engine, isCompleted); err != nil {
|
if requeue, err := r.updateEngineForComplete(engine, isCompleted); err != nil {
|
||||||
|
if requeue {
|
||||||
|
return reconcile.Result{Requeue: true}, nil
|
||||||
|
}
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos completed) Unable to update chaos engine")
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos completed) Unable to update chaos engine")
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reqLogger.Info("Skip reconcile: engineRunner Pod already exists", "Pod.Namespace", runner.Namespace, "Pod.Name", runner.Name)
|
||||||
|
|
||||||
return reconcile.Result{}, nil
|
return reconcile.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ChaosEngineReconciler) createRunnerPod(engine *chaosTypes.EngineInfo, reqLogger logr.Logger) (reconcile.Result, error) {
|
||||||
|
if err := r.setExperimentDetails(engine); err != nil {
|
||||||
|
if updateEngineErr := r.updateEngineState(engine, litmuschaosv1alpha1.EngineStateStop); updateEngineErr != nil {
|
||||||
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos stop) Unable to update chaosengine")
|
||||||
|
return reconcile.Result{}, fmt.Errorf("unable to Update Engine State: %v", err)
|
||||||
|
}
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the engineRunner pod already exists, else create
|
||||||
|
if err := r.checkEngineRunnerPod(engine, reqLogger); err != nil {
|
||||||
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(chaos start) Unable to get chaos resources")
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
return reconcile.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ChaosEngineReconciler) setExperimentDetails(engine *chaosTypes.EngineInfo) error {
|
||||||
|
// Get the image for runner pod from chaosengine spec,operator env or default values.
|
||||||
|
setChaosResourceImage(engine)
|
||||||
|
|
||||||
|
if engine.Selectors != nil && engine.Selectors.Workloads == nil && engine.Selectors.Pods == nil {
|
||||||
|
return fmt.Errorf("specify one out of workloads or pods")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (engine.AppInfo.AppKind != "") != (engine.AppInfo.Applabel != "") {
|
||||||
|
return fmt.Errorf("incomplete appinfo, provide appkind and applabel both")
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.Targets = getTargets(engine)
|
||||||
|
|
||||||
|
var appExperiments []string
|
||||||
|
for _, exp := range engine.Instance.Spec.Experiments {
|
||||||
|
appExperiments = append(appExperiments, exp.Name)
|
||||||
|
}
|
||||||
|
engine.AppExperiments = appExperiments
|
||||||
|
|
||||||
|
chaosTypes.Log.Info("Targets derived from Chaosengine is ", "targets", engine.Targets)
|
||||||
|
chaosTypes.Log.Info("Exp list derived from chaosengine is ", "appExpirements", appExperiments)
|
||||||
|
chaosTypes.Log.Info("Runner image derived from chaosengine is", "runnerImage", engine.Instance.Spec.Components.Runner.Image)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTargets(engine *chaosTypes.EngineInfo) string {
|
||||||
|
if engine.Selectors == nil && reflect.DeepEqual(engine.AppInfo, litmuschaosv1alpha1.ApplicationParams{}) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var targets []string
|
||||||
|
|
||||||
|
if engine.Selectors != nil {
|
||||||
|
if engine.Selectors.Workloads != nil {
|
||||||
|
for _, w := range engine.Selectors.Workloads {
|
||||||
|
var filter string
|
||||||
|
if w.Names != "" {
|
||||||
|
filter = w.Names
|
||||||
|
} else {
|
||||||
|
filter = w.Labels
|
||||||
|
}
|
||||||
|
|
||||||
|
target := strings.Join([]string{string(w.Kind), w.Namespace, fmt.Sprintf("[%v]", filter)}, ":")
|
||||||
|
targets = append(targets, target)
|
||||||
|
}
|
||||||
|
return strings.Join(targets, ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, w := range engine.Selectors.Pods {
|
||||||
|
target := strings.Join([]string{"pod", w.Namespace, fmt.Sprintf("[%v]", w.Names)}, ":")
|
||||||
|
targets = append(targets, target)
|
||||||
|
}
|
||||||
|
return strings.Join(targets, ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
if engine.AppInfo.Appns == "" {
|
||||||
|
engine.AppInfo.Appns = engine.Instance.Namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
if engine.AppInfo.AppKind == "" {
|
||||||
|
engine.AppInfo.AppKind = "KIND"
|
||||||
|
}
|
||||||
|
return strings.Join([]string{engine.AppInfo.AppKind, engine.AppInfo.Appns, fmt.Sprintf("[%v]", engine.AppInfo.Applabel)}, ":")
|
||||||
|
}
|
||||||
|
|
||||||
// updateExperimentStatusesForStop updates ChaosEngine.Status.Experiment with Abort Status.
|
// updateExperimentStatusesForStop updates ChaosEngine.Status.Experiment with Abort Status.
|
||||||
func updateExperimentStatusesForStop(engine *chaosTypes.EngineInfo) {
|
func updateExperimentStatusesForStop(engine *chaosTypes.EngineInfo) {
|
||||||
for i := range engine.Instance.Status.Experiments {
|
for i := range engine.Instance.Status.Experiments {
|
||||||
|
@ -643,80 +680,41 @@ func updateExperimentStatusesForStop(engine *chaosTypes.EngineInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startReqLogger(request reconcile.Request) logr.Logger {
|
func startReqLogger(request reconcile.Request) *logr.Logger {
|
||||||
reqLogger := chaosTypes.Log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
|
reqLogger := chaosTypes.Log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
|
||||||
reqLogger.Info("Reconciling ChaosEngine")
|
reqLogger.Info("Reconciling ChaosEngine")
|
||||||
|
|
||||||
return reqLogger
|
return &reqLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ChaosEngineReconciler) validateAnnotatedApplication(engine *chaosTypes.EngineInfo) error {
|
func (r *ChaosEngineReconciler) updateEngineForComplete(engine *chaosTypes.EngineInfo, isCompleted bool) (bool, error) {
|
||||||
// Get the image for runner pod from chaosengine spec,operator env or default values.
|
|
||||||
setChaosResourceImage(engine)
|
|
||||||
|
|
||||||
clientSet, err := clientset.CreateClientSet()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dynamicClient, err := dynamicclientset.CreateClientSet()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// getAnnotationCheck fetch the annotationCheck from engine spec
|
|
||||||
if err = getAnnotationCheck(engine); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the app details from ChaosEngine instance. Check if app is present
|
|
||||||
// Also check, if the app is annotated for chaos & that the labels are unique
|
|
||||||
if err = getApplicationDetail(engine); err != nil {
|
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(appinfo derivation) Unable to get chaosengine")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if engine.Instance.Spec.AnnotationCheck == "true" {
|
|
||||||
if engine.AppInfo.Label == "" || engine.AppInfo.Namespace == "" || engine.AppInfo.Kind == "" {
|
|
||||||
return errors.Errorf("incomplete AppInfo inside chaosengine")
|
|
||||||
}
|
|
||||||
// Determine whether apps with matching labels have chaos annotation set to true
|
|
||||||
engine, err = resource.CheckChaosAnnotation(engine, clientSet, *dynamicClient)
|
|
||||||
if err != nil {
|
|
||||||
// using an event msg that indicates the app couldn't be identified. By this point in execution,
|
|
||||||
// if the engine could not be found or accessed, it would already be caught in r.initEngine & getApplicationDetail
|
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeWarning, "ChaosResourcesOperationFailed", "(app indentification) Unable to filter app by specified info")
|
|
||||||
chaosTypes.Log.Info("Annotation check failed with", "error:", err)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ChaosEngineReconciler) updateEngineForComplete(engine *chaosTypes.EngineInfo, isCompleted bool) error {
|
|
||||||
if engine.Instance.Status.EngineStatus != litmuschaosv1alpha1.EngineStatusCompleted {
|
if engine.Instance.Status.EngineStatus != litmuschaosv1alpha1.EngineStatusCompleted {
|
||||||
engine.Instance.Status.EngineStatus = litmuschaosv1alpha1.EngineStatusCompleted
|
engine.Instance.Status.EngineStatus = litmuschaosv1alpha1.EngineStatusCompleted
|
||||||
engine.Instance.Spec.EngineState = litmuschaosv1alpha1.EngineStateStop
|
engine.Instance.Spec.EngineState = litmuschaosv1alpha1.EngineStateStop
|
||||||
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
||||||
return fmt.Errorf("unable to update ChaosEngine Status, due to update error: %v", err)
|
if k8serrors.IsConflict(err) {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("unable to update ChaosEngine Status, due to update error: %v", err)
|
||||||
}
|
}
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "ChaosEngineCompleted", "ChaosEngine completed, will delete or retain the resources according to jobCleanUpPolicy")
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "ChaosEngineCompleted", "ChaosEngine completed, will delete or retain the resources according to jobCleanUpPolicy")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ChaosEngineReconciler) updateEngineForRestart(engine *chaosTypes.EngineInfo) error {
|
func (r *ChaosEngineReconciler) updateEngineForRestart(engine *chaosTypes.EngineInfo) (bool, error) {
|
||||||
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "RestartInProgress", "ChaosEngine is restarted")
|
r.Recorder.Eventf(engine.Instance, corev1.EventTypeNormal, "RestartInProgress", "ChaosEngine is restarted")
|
||||||
engine.Instance.Status.EngineStatus = litmuschaosv1alpha1.EngineStatusInitialized
|
engine.Instance.Status.EngineStatus = litmuschaosv1alpha1.EngineStatusInitialized
|
||||||
engine.Instance.Status.Experiments = nil
|
engine.Instance.Status.Experiments = nil
|
||||||
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
if err := r.Client.Update(context.TODO(), engine.Instance, &client.UpdateOptions{}); err != nil {
|
||||||
return fmt.Errorf("unable to restart ChaosEngine, due to update error: %v", err)
|
if k8serrors.IsConflict(err) {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("unable to restart ChaosEngine, due to update error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateChaosStatus update the chaos status inside the chaosresult
|
// updateChaosStatus update the chaos status inside the chaosresult
|
||||||
|
@ -829,7 +827,7 @@ func isResultCRDAvailable() (bool, error) {
|
||||||
Resource: "customresourcedefinitions",
|
Resource: "customresourcedefinitions",
|
||||||
}
|
}
|
||||||
|
|
||||||
resultList, err := (*dynamicClient).Resource(gvr).List(context.Background(), v1.ListOptions{})
|
resultList, err := dynamicClient.Resource(gvr).List(context.Background(), v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,61 +34,13 @@ import (
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitializeApplicationInfo(t *testing.T) {
|
|
||||||
tests := map[string]struct {
|
|
||||||
instance *v1alpha1.ChaosEngine
|
|
||||||
isErr bool
|
|
||||||
}{
|
|
||||||
"Test Positive-1": {
|
|
||||||
instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-monitor",
|
|
||||||
Namespace: "test",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "key=value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
isErr: false,
|
|
||||||
},
|
|
||||||
"Test Negative-1": {
|
|
||||||
instance: nil,
|
|
||||||
isErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, mock := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
appInfo := &chaosTypes.ApplicationInfo{
|
|
||||||
Namespace: "namespace",
|
|
||||||
Label: "fake_id=aa",
|
|
||||||
ExperimentList: []v1alpha1.ExperimentList{
|
|
||||||
{
|
|
||||||
Name: "fake_name",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ServiceAccountName: "fake-service-account-name",
|
|
||||||
}
|
|
||||||
_, err := initializeApplicationInfo(mock.instance, appInfo)
|
|
||||||
if mock.isErr && err == nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
|
||||||
}
|
|
||||||
if !mock.isErr && err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
t.Fatalf("Test %q failed: expected error to be nil", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func TestGetChaosRunnerENV(t *testing.T) {
|
func TestGetChaosRunnerENV(t *testing.T) {
|
||||||
fakeEngineName := "Fake Engine"
|
fakeEngineName := "Fake Engine"
|
||||||
fakeNameSpace := "Fake NameSpace"
|
fakeNameSpace := "Fake NameSpace"
|
||||||
fakeServiceAcc := "Fake Service Account"
|
fakeServiceAcc := "Fake Service Account"
|
||||||
|
fakeTargets := "fakeTargets"
|
||||||
fakeAppLabel := "Fake Label"
|
fakeAppLabel := "Fake Label"
|
||||||
fakeAppKind := "Fake Kind"
|
fakeAppKind := "Fake Kind"
|
||||||
fakeAnnotationCheck := "Fake Annotation Check"
|
|
||||||
fakeAnnotationKey := "litmuschaos.io/chaos"
|
|
||||||
fakeAExList := []string{"fake string"}
|
fakeAExList := []string{"fake string"}
|
||||||
fakeAuxilaryAppInfo := "ns1:name=percona,ns2:run=nginx"
|
fakeAuxilaryAppInfo := "ns1:name=percona,ns2:run=nginx"
|
||||||
fakeClientUUID := "12345678-9012-3456-7890-123456789012"
|
fakeClientUUID := "12345678-9012-3456-7890-123456789012"
|
||||||
|
@ -106,7 +58,6 @@ func TestGetChaosRunnerENV(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: fakeServiceAcc,
|
ChaosServiceAccount: fakeServiceAcc,
|
||||||
AnnotationCheck: fakeAnnotationCheck,
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
Appinfo: v1alpha1.ApplicationParams{
|
||||||
Applabel: fakeAppLabel,
|
Applabel: fakeAppLabel,
|
||||||
Appns: fakeNameSpace,
|
Appns: fakeNameSpace,
|
||||||
|
@ -122,16 +73,8 @@ func TestGetChaosRunnerENV(t *testing.T) {
|
||||||
Value: fakeEngineName,
|
Value: fakeEngineName,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "APP_LABEL",
|
Name: "TARGETS",
|
||||||
Value: fakeAppLabel,
|
Value: fakeTargets,
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "APP_KIND",
|
|
||||||
Value: fakeAppKind,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "APP_NAMESPACE",
|
|
||||||
Value: fakeNameSpace,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "EXPERIMENT_LIST",
|
Name: "EXPERIMENT_LIST",
|
||||||
|
@ -153,23 +96,16 @@ func TestGetChaosRunnerENV(t *testing.T) {
|
||||||
Name: "CHAOS_NAMESPACE",
|
Name: "CHAOS_NAMESPACE",
|
||||||
Value: fakeNameSpace,
|
Value: fakeNameSpace,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "ANNOTATION_CHECK",
|
|
||||||
Value: fakeAnnotationCheck,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "ANNOTATION_KEY",
|
|
||||||
Value: fakeAnnotationKey,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, mock := range tests {
|
for name, mock := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
actualResult := getChaosRunnerENV(mock.instance, mock.aExList, fakeClientUUID)
|
engine := &chaosTypes.EngineInfo{Instance: mock.instance, Targets: fakeTargets, AppExperiments: fakeAExList}
|
||||||
println(actualResult)
|
actualResult := getChaosRunnerENV(engine, fakeClientUUID)
|
||||||
if len(actualResult) != 11 {
|
println(len(actualResult))
|
||||||
t.Fatalf("Test %q failed: expected array length to be 11", name)
|
if len(actualResult) != 7 {
|
||||||
|
t.Fatalf("Test %q failed: expected array length to be 7", name)
|
||||||
}
|
}
|
||||||
for index, result := range actualResult {
|
for index, result := range actualResult {
|
||||||
if result.Value != mock.expectedResult[index].Value {
|
if result.Value != mock.expectedResult[index].Value {
|
||||||
|
@ -180,260 +116,6 @@ func TestGetChaosRunnerENV(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetApplicationDetail(t *testing.T) {
|
|
||||||
tests := map[string]struct {
|
|
||||||
engine chaosTypes.EngineInfo
|
|
||||||
isErr bool
|
|
||||||
}{
|
|
||||||
"Test Positive-1": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-monitor",
|
|
||||||
Namespace: "test",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "key=value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
isErr: false,
|
|
||||||
},
|
|
||||||
"Test Negative": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: nil,
|
|
||||||
},
|
|
||||||
isErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, mock := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
err := getApplicationDetail(&mock.engine)
|
|
||||||
if mock.isErr && err == nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
|
||||||
}
|
|
||||||
if !mock.isErr && err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
t.Fatalf("Test %q failed: expected error to be nil", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetAnnotationCheck(t *testing.T) {
|
|
||||||
tests := map[string]struct {
|
|
||||||
engine chaosTypes.EngineInfo
|
|
||||||
isErr bool
|
|
||||||
}{
|
|
||||||
"Test Positive-1": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-runner",
|
|
||||||
Namespace: "test",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "run=nginx",
|
|
||||||
},
|
|
||||||
AnnotationCheck: "true",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
|
||||||
},
|
|
||||||
isErr: false,
|
|
||||||
},
|
|
||||||
"Test Positive-2": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-runner",
|
|
||||||
Namespace: "test",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "run=nginx",
|
|
||||||
},
|
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
|
||||||
},
|
|
||||||
|
|
||||||
isErr: false,
|
|
||||||
},
|
|
||||||
"Test Negative-1": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-runner",
|
|
||||||
Namespace: "test",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
|
||||||
AnnotationCheck: "fakeCheck",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "run=nginx",
|
|
||||||
},
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
|
||||||
},
|
|
||||||
isErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, mock := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
err := getAnnotationCheck(&mock.engine)
|
|
||||||
if mock.isErr && err == nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
|
||||||
}
|
|
||||||
if !mock.isErr && err != nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error to be nil", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateAnnontatedApplication(t *testing.T) {
|
|
||||||
tests := map[string]struct {
|
|
||||||
engine chaosTypes.EngineInfo
|
|
||||||
isErr bool
|
|
||||||
}{
|
|
||||||
"Test Positive-1": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "validate-annotation-p2",
|
|
||||||
Namespace: "default",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
|
||||||
EngineState: "active",
|
|
||||||
AnnotationCheck: "false",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "app=nginx",
|
|
||||||
AppKind: "deployment",
|
|
||||||
},
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
|
||||||
{
|
|
||||||
Name: "exp-1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
|
||||||
},
|
|
||||||
|
|
||||||
isErr: false,
|
|
||||||
},
|
|
||||||
"Test Negetive-1": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "validate-annotation-n1",
|
|
||||||
Namespace: "default",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "app=nginx",
|
|
||||||
AppKind: "deployment",
|
|
||||||
},
|
|
||||||
EngineState: "active",
|
|
||||||
AnnotationCheck: "dummy",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
|
||||||
{
|
|
||||||
Name: "exp-1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
isErr: true,
|
|
||||||
},
|
|
||||||
"Test Negetive-2": {
|
|
||||||
engine: chaosTypes.EngineInfo{
|
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "validate-annotation-n2",
|
|
||||||
Namespace: "default",
|
|
||||||
},
|
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
|
||||||
AnnotationCheck: "true",
|
|
||||||
EngineState: "active",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
|
||||||
Applabel: "app=nginx",
|
|
||||||
AppKind: "deployment",
|
|
||||||
},
|
|
||||||
Components: v1alpha1.ComponentParams{
|
|
||||||
Runner: v1alpha1.RunnerInfo{
|
|
||||||
Image: "fake-runner-image",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
|
||||||
{
|
|
||||||
Name: "exp-1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
|
||||||
},
|
|
||||||
isErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for name, mock := range tests {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
r := CreateFakeClient(t)
|
|
||||||
err := r.Client.Create(context.TODO(), mock.engine.Instance)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Unable to create engine: %v", err)
|
|
||||||
}
|
|
||||||
err = r.validateAnnotatedApplication(&mock.engine)
|
|
||||||
if mock.isErr && err == nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
|
||||||
}
|
|
||||||
if !mock.isErr && err != nil {
|
|
||||||
t.Fatalf("Test %q failed: expected error to be nil", name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdateEngineForComplete(t *testing.T) {
|
func TestUpdateEngineForComplete(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
engine chaosTypes.EngineInfo
|
engine chaosTypes.EngineInfo
|
||||||
|
@ -451,8 +133,7 @@ func TestUpdateEngineForComplete(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -483,8 +164,7 @@ func TestUpdateEngineForComplete(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
{
|
{
|
||||||
Name: "exp-1",
|
Name: "exp-1",
|
||||||
|
@ -510,8 +190,7 @@ func TestUpdateEngineForComplete(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
{
|
{
|
||||||
Name: "exp-1",
|
Name: "exp-1",
|
||||||
|
@ -534,7 +213,7 @@ func TestUpdateEngineForComplete(t *testing.T) {
|
||||||
fmt.Printf("Unable to create engine: %v", err)
|
fmt.Printf("Unable to create engine: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.updateEngineForComplete(&mock.engine, true)
|
_, err = r.updateEngineForComplete(&mock.engine, true)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
}
|
}
|
||||||
|
@ -562,8 +241,7 @@ func TestUpdateEngineForRestart(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -594,8 +272,7 @@ func TestUpdateEngineForRestart(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
{
|
{
|
||||||
Name: "exp-1",
|
Name: "exp-1",
|
||||||
|
@ -618,7 +295,7 @@ func TestUpdateEngineForRestart(t *testing.T) {
|
||||||
fmt.Printf("Unable to create engine: %v", err)
|
fmt.Printf("Unable to create engine: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.updateEngineForRestart(&mock.engine)
|
_, err = r.updateEngineForRestart(&mock.engine)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
}
|
}
|
||||||
|
@ -652,6 +329,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -678,6 +360,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -695,7 +382,6 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -706,6 +392,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -723,7 +414,6 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
AnnotationCheck: "true",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -734,6 +424,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -746,6 +441,13 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
engine: chaosTypes.EngineInfo{
|
engine: chaosTypes.EngineInfo{
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
Instance: &v1alpha1.ChaosEngine{
|
||||||
ObjectMeta: metav1.ObjectMeta{},
|
ObjectMeta: metav1.ObjectMeta{},
|
||||||
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
AppExperiments: []string{"exp-1"},
|
AppExperiments: []string{"exp-1"},
|
||||||
},
|
},
|
||||||
|
@ -760,6 +462,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -776,6 +483,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -797,6 +509,11 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
Image: "",
|
Image: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "pod-delete",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -808,6 +525,15 @@ func TestNewGoRunnerPodForCR(t *testing.T) {
|
||||||
for name, mock := range tests {
|
for name, mock := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
r := CreateFakeClient(t)
|
r := CreateFakeClient(t)
|
||||||
|
exp := v1alpha1.ChaosExperiment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "pod-delete",
|
||||||
|
Namespace: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := r.Client.Create(context.TODO(), &exp); err != nil {
|
||||||
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
|
}
|
||||||
_, err := r.newGoRunnerPodForCR(&mock.engine)
|
_, err := r.newGoRunnerPodForCR(&mock.engine)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
|
@ -836,7 +562,6 @@ func TestInitEngine(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -867,8 +592,7 @@ func TestInitEngine(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: "active",
|
EngineState: "active",
|
||||||
AnnotationCheck: "false",
|
|
||||||
Experiments: []v1alpha1.ExperimentList{
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
{
|
{
|
||||||
Name: "exp-1",
|
Name: "exp-1",
|
||||||
|
@ -886,7 +610,7 @@ func TestInitEngine(t *testing.T) {
|
||||||
for name, mock := range tests {
|
for name, mock := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
r := CreateFakeClient(t)
|
r := CreateFakeClient(t)
|
||||||
err := r.initEngine(&mock.engine)
|
_, err := r.initEngine(&mock.engine)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
}
|
}
|
||||||
|
@ -915,8 +639,7 @@ func TestUpdateEngineState(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -948,8 +671,7 @@ func TestUpdateEngineState(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1005,8 +727,7 @@ func TestCheckRunnerPodCompletedStatus(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1037,8 +758,7 @@ func TestCheckRunnerPodCompletedStatus(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1188,8 +908,7 @@ func TestGetChaosEngineInstance(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1226,8 +945,7 @@ func TestGetChaosEngineInstance(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1292,6 +1010,11 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1313,6 +1036,11 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1330,12 +1058,16 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1353,12 +1085,16 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
AnnotationCheck: "true",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1371,6 +1107,13 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
engine: chaosTypes.EngineInfo{
|
engine: chaosTypes.EngineInfo{
|
||||||
Instance: &v1alpha1.ChaosEngine{
|
Instance: &v1alpha1.ChaosEngine{
|
||||||
ObjectMeta: metav1.ObjectMeta{},
|
ObjectMeta: metav1.ObjectMeta{},
|
||||||
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
AppExperiments: []string{"exp-1"},
|
||||||
|
@ -1386,6 +1129,11 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
|
Experiments: []v1alpha1.ExperimentList{
|
||||||
|
{
|
||||||
|
Name: "exp-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1434,6 +1182,15 @@ func TestCheckEngineRunnerPod(t *testing.T) {
|
||||||
for name, mock := range tests {
|
for name, mock := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
r := CreateFakeClient(t)
|
r := CreateFakeClient(t)
|
||||||
|
exp := v1alpha1.ChaosExperiment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "exp-1",
|
||||||
|
Namespace: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := r.Client.Create(context.TODO(), &exp); err != nil {
|
||||||
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
|
}
|
||||||
reqLogger := chaosTypes.Log.WithValues()
|
reqLogger := chaosTypes.Log.WithValues()
|
||||||
err := r.checkEngineRunnerPod(&mock.engine, reqLogger)
|
err := r.checkEngineRunnerPod(&mock.engine, reqLogger)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
|
@ -1464,8 +1221,7 @@ func TestReconcileForDelete(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1502,8 +1258,7 @@ func TestReconcileForDelete(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1567,8 +1322,7 @@ func TestForceRemoveAllChaosPods(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1605,8 +1359,7 @@ func TestForceRemoveAllChaosPods(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1655,8 +1408,7 @@ func TestGracefullyRemoveDefaultChaosResources(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1693,8 +1445,7 @@ func TestGracefullyRemoveDefaultChaosResources(t *testing.T) {
|
||||||
Applabel: "app=nginx",
|
Applabel: "app=nginx",
|
||||||
AppKind: "deployment",
|
AppKind: "deployment",
|
||||||
},
|
},
|
||||||
EngineState: v1alpha1.EngineStateActive,
|
EngineState: v1alpha1.EngineStateActive,
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1753,9 +1504,10 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
Appinfo: v1alpha1.ApplicationParams{
|
||||||
Applabel: "run=nginx",
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
},
|
},
|
||||||
AnnotationCheck: "false",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1769,6 +1521,12 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
AppInfo: v1alpha1.ApplicationParams{
|
||||||
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
|
},
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
AppExperiments: []string{"exp-1"},
|
||||||
},
|
},
|
||||||
isErr: false,
|
isErr: false,
|
||||||
|
@ -1782,9 +1540,10 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
AnnotationCheck: "fakeCheck",
|
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
Appinfo: v1alpha1.ApplicationParams{
|
||||||
Applabel: "run=nginx",
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
},
|
},
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
|
@ -1794,6 +1553,12 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
AppInfo: v1alpha1.ApplicationParams{
|
||||||
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
|
},
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
AppExperiments: []string{"exp-1"},
|
||||||
},
|
},
|
||||||
isErr: true,
|
isErr: true,
|
||||||
|
@ -1808,9 +1573,10 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
Spec: v1alpha1.ChaosEngineSpec{
|
Spec: v1alpha1.ChaosEngineSpec{
|
||||||
ChaosServiceAccount: "fake-serviceAccount",
|
ChaosServiceAccount: "fake-serviceAccount",
|
||||||
Appinfo: v1alpha1.ApplicationParams{
|
Appinfo: v1alpha1.ApplicationParams{
|
||||||
Applabel: "run=nginx",
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
},
|
},
|
||||||
AnnotationCheck: "true",
|
|
||||||
Components: v1alpha1.ComponentParams{
|
Components: v1alpha1.ComponentParams{
|
||||||
Runner: v1alpha1.RunnerInfo{
|
Runner: v1alpha1.RunnerInfo{
|
||||||
Image: "fake-runner-image",
|
Image: "fake-runner-image",
|
||||||
|
@ -1818,6 +1584,11 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AppInfo: v1alpha1.ApplicationParams{
|
||||||
|
Applabel: "fakeAppLabel",
|
||||||
|
Appns: "fakeAppNs",
|
||||||
|
AppKind: "fakeAppKind",
|
||||||
|
},
|
||||||
|
|
||||||
AppExperiments: []string{"exp-1"},
|
AppExperiments: []string{"exp-1"},
|
||||||
},
|
},
|
||||||
|
@ -1827,6 +1598,15 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
for name, mock := range tests {
|
for name, mock := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
r := CreateFakeClient(t)
|
r := CreateFakeClient(t)
|
||||||
|
exp := v1alpha1.ChaosExperiment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "exp-1",
|
||||||
|
Namespace: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := r.Client.Create(context.TODO(), &exp); err != nil {
|
||||||
|
t.Fatalf("Test %q failed: expected error not to be nil", name)
|
||||||
|
}
|
||||||
reqLogger := chaosTypes.Log.WithValues()
|
reqLogger := chaosTypes.Log.WithValues()
|
||||||
_, err := r.reconcileForCreationAndRunning(&mock.engine, reqLogger)
|
_, err := r.reconcileForCreationAndRunning(&mock.engine, reqLogger)
|
||||||
if mock.isErr && err == nil {
|
if mock.isErr && err == nil {
|
||||||
|
@ -1841,7 +1621,7 @@ func TestReconcileForCreationAndRunning(t *testing.T) {
|
||||||
|
|
||||||
func CreateFakeClient(t *testing.T) *ChaosEngineReconciler {
|
func CreateFakeClient(t *testing.T) *ChaosEngineReconciler {
|
||||||
|
|
||||||
fakeClient := litmusFakeClientset.NewFakeClient()
|
fakeClient := litmusFakeClientset.NewClientBuilder().WithRuntimeObjects().Build()
|
||||||
if fakeClient == nil {
|
if fakeClient == nil {
|
||||||
fmt.Println("litmusClient is not created")
|
fmt.Println("litmusClient is not created")
|
||||||
}
|
}
|
||||||
|
@ -1855,11 +1635,18 @@ func CreateFakeClient(t *testing.T) *ChaosEngineReconciler {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exp := &v1alpha1.ChaosExperiment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: make(map[string]string),
|
||||||
|
Name: "dummyexp",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
chaosResultList := &v1alpha1.ChaosResultList{
|
chaosResultList := &v1alpha1.ChaosResultList{
|
||||||
Items: []v1alpha1.ChaosResult{},
|
Items: []v1alpha1.ChaosResult{},
|
||||||
}
|
}
|
||||||
|
|
||||||
s.AddKnownTypes(v1alpha1.SchemeGroupVersion, engineR, chaosResultList)
|
s.AddKnownTypes(v1alpha1.SchemeGroupVersion, engineR, chaosResultList, exp)
|
||||||
|
|
||||||
recorder := record.NewFakeRecorder(1024)
|
recorder := record.NewFakeRecorder(1024)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,12 +39,8 @@ spec:
|
||||||
#oneOf:
|
#oneOf:
|
||||||
# - pattern: '^delete$'
|
# - pattern: '^delete$'
|
||||||
# - pattern: '^retain$'
|
# - pattern: '^retain$'
|
||||||
annotationCheck:
|
|
||||||
type: string
|
|
||||||
pattern: ^(true|false)$
|
|
||||||
defaultHealthCheck:
|
defaultHealthCheck:
|
||||||
type: string
|
type: boolean
|
||||||
pattern: ^(true|false)$
|
|
||||||
appinfo:
|
appinfo:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -55,6 +51,44 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
appns:
|
appns:
|
||||||
type: string
|
type: string
|
||||||
|
selectors:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
pods:
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
names:
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- names
|
||||||
|
- namespace
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
workloads:
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
pattern: ^(^$|deployment|statefulset|daemonset|deploymentconfig|rollout)$
|
||||||
|
labels:
|
||||||
|
type: string
|
||||||
|
names:
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
type: string
|
||||||
|
oneOf:
|
||||||
|
- required: [ names ]
|
||||||
|
- required: [ labels ]
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- namespace
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
oneOf:
|
||||||
|
- required: [ pods ]
|
||||||
|
- required: [ workloads ]
|
||||||
auxiliaryAppInfo:
|
auxiliaryAppInfo:
|
||||||
type: string
|
type: string
|
||||||
engineState:
|
engineState:
|
||||||
|
@ -67,6 +101,180 @@ spec:
|
||||||
components:
|
components:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
sidecar:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
env:
|
||||||
|
description: ENV contains ENV passed to the sidecar container
|
||||||
|
items:
|
||||||
|
description: EnvVar represents an environment variable
|
||||||
|
present in a Container.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Name of the environment variable. Must
|
||||||
|
be a C_IDENTIFIER.
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
description: 'Variable references $(VAR_NAME) are
|
||||||
|
expanded using the previous defined environment
|
||||||
|
variables in the container and any service environment
|
||||||
|
variables. If a variable cannot be resolved, the
|
||||||
|
reference in the input string will be unchanged.
|
||||||
|
The $(VAR_NAME) syntax can be escaped with a double
|
||||||
|
$$, ie: $$(VAR_NAME). Escaped references will never
|
||||||
|
be expanded, regardless of whether the variable
|
||||||
|
exists or not. Defaults to "".'
|
||||||
|
type: string
|
||||||
|
valueFrom:
|
||||||
|
description: Source for the environment variable's
|
||||||
|
value. Cannot be used if value is not empty.
|
||||||
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Selects a key of a ConfigMap.
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion,
|
||||||
|
kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap
|
||||||
|
or its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
fieldRef:
|
||||||
|
description: 'Selects a field of the pod: supports
|
||||||
|
metadata.name, metadata.namespace, `metadata.labels[''<KEY>'']`,
|
||||||
|
`metadata.annotations[''<KEY>'']`, spec.nodeName,
|
||||||
|
spec.serviceAccountName, status.hostIP, status.podIP,
|
||||||
|
status.podIPs.'
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: Version of the schema the FieldPath
|
||||||
|
is written in terms of, defaults to "v1".
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: Path of the field to select in
|
||||||
|
the specified API version.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- fieldPath
|
||||||
|
type: object
|
||||||
|
resourceFieldRef:
|
||||||
|
description: 'Selects a resource of the container:
|
||||||
|
only resources limits and requests (limits.cpu,
|
||||||
|
limits.memory, limits.ephemeral-storage, requests.cpu,
|
||||||
|
requests.memory and requests.ephemeral-storage)
|
||||||
|
are currently supported.'
|
||||||
|
properties:
|
||||||
|
containerName:
|
||||||
|
description: 'Container name: required for
|
||||||
|
volumes, optional for env vars'
|
||||||
|
type: string
|
||||||
|
divisor:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: Specifies the output format of
|
||||||
|
the exposed resources, defaults to "1"
|
||||||
|
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
resource:
|
||||||
|
description: 'Required: resource to select'
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- resource
|
||||||
|
type: object
|
||||||
|
secretKeyRef:
|
||||||
|
description: Selects a key of a secret in the
|
||||||
|
pod's namespace
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key of the secret to select
|
||||||
|
from. Must be a valid secret key.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion,
|
||||||
|
kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the Secret or
|
||||||
|
its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
envFrom:
|
||||||
|
description: EnvFrom for the sidecar container
|
||||||
|
items:
|
||||||
|
description: EnvFromSource represents the source of a
|
||||||
|
set of ConfigMaps
|
||||||
|
properties:
|
||||||
|
configMapRef:
|
||||||
|
description: The ConfigMap to select from
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind,
|
||||||
|
uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap must
|
||||||
|
be defined
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
prefix:
|
||||||
|
description: An optional identifier to prepend to
|
||||||
|
each key in the ConfigMap. Must be a C_IDENTIFIER.
|
||||||
|
type: string
|
||||||
|
secretRef:
|
||||||
|
description: The Secret to select from
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info:
|
||||||
|
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
TODO: Add other useful fields. apiVersion, kind,
|
||||||
|
uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the Secret must be
|
||||||
|
defined
|
||||||
|
type: boolean
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
imagePullPolicy:
|
||||||
|
type: string
|
||||||
|
secrets:
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
mountPath:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- mountPath
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
runner:
|
runner:
|
||||||
x-kubernetes-preserve-unknown-fields: true
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
type: object
|
type: object
|
||||||
|
@ -127,6 +335,9 @@ spec:
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
- name
|
||||||
|
- type
|
||||||
|
- mode
|
||||||
- runProperties
|
- runProperties
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
|
@ -134,9 +345,13 @@ spec:
|
||||||
type:
|
type:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
pattern: ^(k8sProbe|httpProbe|cmdProbe|promProbe)$
|
pattern: ^(k8sProbe|httpProbe|cmdProbe|promProbe|sloProbe)$
|
||||||
k8sProbe/inputs:
|
k8sProbe/inputs:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- version
|
||||||
|
- resource
|
||||||
|
- operation
|
||||||
properties:
|
properties:
|
||||||
group:
|
group:
|
||||||
type: string
|
type: string
|
||||||
|
@ -146,6 +361,8 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
namespace:
|
namespace:
|
||||||
type: string
|
type: string
|
||||||
|
resourceNames:
|
||||||
|
type: string
|
||||||
fieldSelector:
|
fieldSelector:
|
||||||
type: string
|
type: string
|
||||||
labelSelector:
|
labelSelector:
|
||||||
|
@ -156,12 +373,19 @@ spec:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
cmdProbe/inputs:
|
cmdProbe/inputs:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- command
|
||||||
|
- comparator
|
||||||
properties:
|
properties:
|
||||||
command:
|
command:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
comparator:
|
comparator:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
- criteria
|
||||||
|
- value
|
||||||
properties:
|
properties:
|
||||||
type:
|
type:
|
||||||
type: string
|
type: string
|
||||||
|
@ -174,6 +398,8 @@ spec:
|
||||||
source:
|
source:
|
||||||
description: The external pod where we have to run the
|
description: The external pod where we have to run the
|
||||||
probe commands. It will run the commands inside the experiment pod itself(inline mode) if source contains a nil value
|
probe commands. It will run the commands inside the experiment pod itself(inline mode) if source contains a nil value
|
||||||
|
required:
|
||||||
|
- image
|
||||||
properties:
|
properties:
|
||||||
annotations:
|
annotations:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
@ -349,6 +575,29 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
description: NodeSelector for the source pod
|
description: NodeSelector for the source pod
|
||||||
type: object
|
type: object
|
||||||
|
tolerations:
|
||||||
|
description: Tolerations for the source pod
|
||||||
|
items:
|
||||||
|
description: The pod with this Toleration tolerates any taint matches the <key,value,effect> using the matching operator <operator>.
|
||||||
|
properties:
|
||||||
|
effect:
|
||||||
|
description: Effect to match. Empty means all effects.
|
||||||
|
type: string
|
||||||
|
key:
|
||||||
|
description: Taint key the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists.
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
description: Operators are Exists or Equal. Defaults to Equal.
|
||||||
|
type: string
|
||||||
|
tolerationSeconds:
|
||||||
|
description: Period of time the toleration tolerates the taint.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
value:
|
||||||
|
description: If the operator is Exists, the value should be empty, otherwise just a regular string.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
privileged:
|
privileged:
|
||||||
description: Privileged for the source pod
|
description: Privileged for the source pod
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -1957,6 +2206,9 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
httpProbe/inputs:
|
httpProbe/inputs:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- url
|
||||||
|
- method
|
||||||
properties:
|
properties:
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1969,6 +2221,9 @@ spec:
|
||||||
properties:
|
properties:
|
||||||
get:
|
get:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- criteria
|
||||||
|
- responseCode
|
||||||
properties:
|
properties:
|
||||||
criteria:
|
criteria:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1978,6 +2233,9 @@ spec:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
post:
|
post:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- criteria
|
||||||
|
- responseCode
|
||||||
properties:
|
properties:
|
||||||
contentType:
|
contentType:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1994,6 +2252,9 @@ spec:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
promProbe/inputs:
|
promProbe/inputs:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- endpoint
|
||||||
|
- comparator
|
||||||
properties:
|
properties:
|
||||||
endpoint:
|
endpoint:
|
||||||
type: string
|
type: string
|
||||||
|
@ -2003,6 +2264,9 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
comparator:
|
comparator:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- criteria
|
||||||
|
- value
|
||||||
properties:
|
properties:
|
||||||
criteria:
|
criteria:
|
||||||
type: string
|
type: string
|
||||||
|
@ -2015,18 +2279,112 @@ spec:
|
||||||
- probeTimeout
|
- probeTimeout
|
||||||
- interval
|
- interval
|
||||||
properties:
|
properties:
|
||||||
|
evaluationTimeout:
|
||||||
|
type: string
|
||||||
probeTimeout:
|
probeTimeout:
|
||||||
type: integer
|
type: string
|
||||||
interval:
|
interval:
|
||||||
|
type: string
|
||||||
|
retry:
|
||||||
type: integer
|
type: integer
|
||||||
retry:
|
attempt:
|
||||||
type: integer
|
type: integer
|
||||||
probePollingInterval:
|
probePollingInterval:
|
||||||
type: integer
|
type: string
|
||||||
initialDelaySeconds:
|
initialDelaySeconds:
|
||||||
type: integer
|
type: integer
|
||||||
|
initialDelay:
|
||||||
|
type: string
|
||||||
|
verbosity:
|
||||||
|
type: string
|
||||||
stopOnFailure:
|
stopOnFailure:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
sloProbe/inputs:
|
||||||
|
description: inputs needed for the SLO probe
|
||||||
|
required:
|
||||||
|
- platformEndpoint
|
||||||
|
- sloIdentifier
|
||||||
|
- sloSourceMetadata
|
||||||
|
- comparator
|
||||||
|
properties:
|
||||||
|
comparator:
|
||||||
|
description: Comparator check for the correctness
|
||||||
|
of the probe output
|
||||||
|
required:
|
||||||
|
- criteria
|
||||||
|
- value
|
||||||
|
properties:
|
||||||
|
criteria:
|
||||||
|
description: Criteria for matching data it
|
||||||
|
supports >=, <=, ==, >, <, != for int and
|
||||||
|
float it supports equal, notEqual, contains
|
||||||
|
for string
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: Type of data it can be int, float,
|
||||||
|
string
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
description: Value contains relative value
|
||||||
|
for criteria
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
evaluationWindow:
|
||||||
|
description: EvaluationWindow is the time period
|
||||||
|
for which the metrics will be evaluated
|
||||||
|
properties:
|
||||||
|
evaluationEndTime:
|
||||||
|
description: End time of evaluation
|
||||||
|
type: integer
|
||||||
|
evaluationStartTime:
|
||||||
|
description: Start time of evaluation
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
platformEndpoint:
|
||||||
|
description: PlatformEndpoint for the monitoring
|
||||||
|
service endpoint
|
||||||
|
type: string
|
||||||
|
insecureSkipVerify:
|
||||||
|
description: InsecureSkipVerify flag to skip certificate
|
||||||
|
checks
|
||||||
|
type: boolean
|
||||||
|
sloIdentifier:
|
||||||
|
description: SLOIdentifier for fetching the details
|
||||||
|
of the SLO
|
||||||
|
type: string
|
||||||
|
sloSourceMetadata:
|
||||||
|
description: SLOSourceMetadata consists of required
|
||||||
|
metadata details to fetch metric data
|
||||||
|
required:
|
||||||
|
- apiTokenSecret
|
||||||
|
- scope
|
||||||
|
properties:
|
||||||
|
apiTokenSecret:
|
||||||
|
description: APITokenSecret for authenticating
|
||||||
|
with the platform service
|
||||||
|
type: string
|
||||||
|
scope:
|
||||||
|
description: Scope required for fetching details
|
||||||
|
required:
|
||||||
|
- accountIdentifier
|
||||||
|
- orgIdentifier
|
||||||
|
- projectIdentifier
|
||||||
|
properties:
|
||||||
|
accountIdentifier:
|
||||||
|
description: AccountIdentifier for account
|
||||||
|
ID
|
||||||
|
type: string
|
||||||
|
orgIdentifier:
|
||||||
|
description: OrgIdentifier for organization
|
||||||
|
ID
|
||||||
|
type: string
|
||||||
|
projectIdentifier:
|
||||||
|
description: ProjectIdentifier for project
|
||||||
|
ID
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
mode:
|
mode:
|
||||||
type: string
|
type: string
|
||||||
pattern: ^(SOT|EOT|Edge|Continuous|OnChaos)$
|
pattern: ^(SOT|EOT|Edge|Continuous|OnChaos)$
|
||||||
|
|
|
@ -40,7 +40,7 @@ spec:
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
env:
|
env:
|
||||||
- name: CHAOS_RUNNER_IMAGE
|
- name: CHAOS_RUNNER_IMAGE
|
||||||
value: "litmuschaos/chaos-runner:ci"
|
value: "litmuschaos.docker.scarf.sh/litmuschaos/chaos-runner:ci"
|
||||||
- name: WATCH_NAMESPACE
|
- name: WATCH_NAMESPACE
|
||||||
value: ""
|
value: ""
|
||||||
- name: POD_NAME
|
- name: POD_NAME
|
||||||
|
|
140
go.mod
140
go.mod
|
@ -1,114 +1,108 @@
|
||||||
module github.com/litmuschaos/chaos-operator
|
module github.com/litmuschaos/chaos-operator
|
||||||
|
|
||||||
go 1.17
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.81.0 // indirect
|
github.com/go-logr/logr v1.4.2
|
||||||
github.com/go-logr/logr v0.4.0
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/go-cmp v0.5.6 // indirect
|
|
||||||
github.com/jpillora/go-ogle-analytics v0.0.0-20161213085824-14b04e0594ef
|
github.com/jpillora/go-ogle-analytics v0.0.0-20161213085824-14b04e0594ef
|
||||||
github.com/litmuschaos/elves v0.0.0-20201107015738-552d74669e3c
|
github.com/litmuschaos/elves v0.0.0-20230607095010-c7119636b529
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b // indirect
|
golang.org/x/oauth2 v0.7.0 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect
|
k8s.io/api v0.26.15
|
||||||
golang.org/x/tools v0.1.11 // indirect
|
k8s.io/apimachinery v0.26.15
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
k8s.io/api v0.22.1
|
|
||||||
k8s.io/apimachinery v0.22.1
|
|
||||||
k8s.io/client-go v12.0.0+incompatible
|
k8s.io/client-go v12.0.0+incompatible
|
||||||
sigs.k8s.io/controller-runtime v0.10.0
|
sigs.k8s.io/controller-runtime v0.14.6
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
|
||||||
github.com/google/martian v2.1.0+incompatible
|
github.com/google/martian v2.1.0+incompatible
|
||||||
github.com/onsi/ginkgo v1.16.4
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/gomega v1.15.0
|
github.com/onsi/gomega v1.24.2
|
||||||
github.com/operator-framework/operator-sdk v0.19.0
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/stretchr/testify v1.7.0
|
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
|
||||||
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
|
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
|
|
||||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
|
||||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
|
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
|
||||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||||
github.com/go-logr/zapr v0.4.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
|
github.com/go-logr/zapr v1.2.3 // indirect
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||||
|
github.com/go-openapi/swag v0.19.14 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||||
github.com/google/gofuzz v1.1.0 // indirect
|
github.com/google/gofuzz v1.1.0 // indirect
|
||||||
github.com/google/uuid v1.1.2 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
|
||||||
github.com/hashicorp/golang-lru v0.5.3 // indirect
|
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/mailru/easyjson v0.7.6 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
go.uber.org/zap v1.19.0 // indirect
|
go.uber.org/zap v1.24.0 // indirect
|
||||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
golang.org/x/net v0.19.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
|
golang.org/x/sys v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e // indirect
|
golang.org/x/term v0.15.0 // indirect
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
|
||||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.26.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/apiextensions-apiserver v0.22.1 // indirect
|
k8s.io/apiextensions-apiserver v0.26.1 // indirect
|
||||||
k8s.io/component-base v0.22.2 // indirect
|
k8s.io/component-base v0.26.15 // indirect
|
||||||
k8s.io/klog/v2 v2.9.0 // indirect
|
k8s.io/klog/v2 v2.80.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
|
||||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect
|
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pinned to kubernetes-1.21.2
|
// Pinned to kubernetes-1.26
|
||||||
replace (
|
replace (
|
||||||
k8s.io/api => k8s.io/api v0.21.2
|
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.14.6
|
||||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.21.2
|
github.com/go-logr/logr => github.com/go-logr/logr v1.4.2
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.21.2
|
k8s.io/api => k8s.io/api v0.26.15
|
||||||
k8s.io/apiserver => k8s.io/apiserver v0.21.2
|
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.15
|
||||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.2
|
k8s.io/apimachinery => k8s.io/apimachinery v0.26.15
|
||||||
k8s.io/client-go => k8s.io/client-go v0.21.2
|
k8s.io/client-go => k8s.io/client-go v0.26.15
|
||||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.2
|
k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.15
|
||||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.2
|
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.15
|
||||||
k8s.io/code-generator => k8s.io/code-generator v0.21.2
|
k8s.io/component-base => k8s.io/component-base v0.26.15
|
||||||
k8s.io/component-base => k8s.io/component-base v0.21.2
|
k8s.io/cri-api => k8s.io/cri-api v0.26.15
|
||||||
k8s.io/cri-api => k8s.io/cri-api v0.21.2
|
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.15
|
||||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.2
|
k8s.io/klog/v2 => k8s.io/klog/v2 v2.80.1
|
||||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.2
|
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.15
|
||||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.2
|
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.15
|
||||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.2
|
k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.15
|
||||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.2
|
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.15
|
||||||
k8s.io/kubectl => k8s.io/kubectl v0.21.2
|
k8s.io/kubelet => k8s.io/kubelet v0.26.15
|
||||||
k8s.io/kubelet => k8s.io/kubelet v0.21.2
|
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.15
|
||||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.2
|
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.15
|
||||||
k8s.io/metrics => k8s.io/metrics v0.21.2
|
|
||||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm
|
replace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm
|
||||||
|
|
18
main.go
18
main.go
|
@ -19,9 +19,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/litmuschaos/chaos-operator/pkg/analytics"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -69,12 +72,19 @@ func main() {
|
||||||
|
|
||||||
printVersion()
|
printVersion()
|
||||||
|
|
||||||
namespace, err := k8sutil.GetWatchNamespace()
|
namespace, found := os.LookupEnv("WATCH_NAMESPACE")
|
||||||
if err != nil {
|
if !found {
|
||||||
setupLog.Error(err, "failed to get watch namespace")
|
setupLog.Error(errors.New("WATCH_NAMESPACE env is not set"), "failed to get watch namespace")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger the Analytics if it's enabled
|
||||||
|
if isAnalytics := strings.ToUpper(os.Getenv("ANALYTICS")); isAnalytics != "FALSE" {
|
||||||
|
if err := analytics.TriggerAnalytics(); err != nil {
|
||||||
|
setupLog.Error(err, "failed to trigger analytics")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
MetricsBindAddress: metricsAddr,
|
MetricsBindAddress: metricsAddr,
|
||||||
|
|
|
@ -37,14 +37,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
|
||||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||||
// of clientsets, like in:
|
// of clientsets, like in:
|
||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "k8s.io/client-go/kubernetes"
|
// "k8s.io/client-go/kubernetes"
|
||||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||||
//
|
//
|
||||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||||
// correctly.
|
// correctly.
|
||||||
|
|
|
@ -37,14 +37,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
|
||||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||||
// of clientsets, like in:
|
// of clientsets, like in:
|
||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "k8s.io/client-go/kubernetes"
|
// "k8s.io/client-go/kubernetes"
|
||||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||||
//
|
//
|
||||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||||
// correctly.
|
// correctly.
|
||||||
|
|
|
@ -36,9 +36,9 @@ type FakeChaosEngines struct {
|
||||||
ns string
|
ns string
|
||||||
}
|
}
|
||||||
|
|
||||||
var chaosenginesResource = schema.GroupVersionResource{Group: "litmuschaos", Version: "v1alpha1", Resource: "chaosengines"}
|
var chaosenginesResource = schema.GroupVersionResource{Group: "litmuschaos.io", Version: "v1alpha1", Resource: "chaosengines"}
|
||||||
|
|
||||||
var chaosenginesKind = schema.GroupVersionKind{Group: "litmuschaos", Version: "v1alpha1", Kind: "ChaosEngine"}
|
var chaosenginesKind = schema.GroupVersionKind{Group: "litmuschaos.io", Version: "v1alpha1", Kind: "ChaosEngine"}
|
||||||
|
|
||||||
// Get takes name of the chaosEngine, and returns the corresponding chaosEngine object, and an error if there is any.
|
// Get takes name of the chaosEngine, and returns the corresponding chaosEngine object, and an error if there is any.
|
||||||
func (c *FakeChaosEngines) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosEngine, err error) {
|
func (c *FakeChaosEngines) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosEngine, err error) {
|
||||||
|
|
|
@ -36,9 +36,9 @@ type FakeChaosExperiments struct {
|
||||||
ns string
|
ns string
|
||||||
}
|
}
|
||||||
|
|
||||||
var chaosexperimentsResource = schema.GroupVersionResource{Group: "litmuschaos", Version: "v1alpha1", Resource: "chaosexperiments"}
|
var chaosexperimentsResource = schema.GroupVersionResource{Group: "litmuschaos.io", Version: "v1alpha1", Resource: "chaosexperiments"}
|
||||||
|
|
||||||
var chaosexperimentsKind = schema.GroupVersionKind{Group: "litmuschaos", Version: "v1alpha1", Kind: "ChaosExperiment"}
|
var chaosexperimentsKind = schema.GroupVersionKind{Group: "litmuschaos.io", Version: "v1alpha1", Kind: "ChaosExperiment"}
|
||||||
|
|
||||||
// Get takes name of the chaosExperiment, and returns the corresponding chaosExperiment object, and an error if there is any.
|
// Get takes name of the chaosExperiment, and returns the corresponding chaosExperiment object, and an error if there is any.
|
||||||
func (c *FakeChaosExperiments) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosExperiment, err error) {
|
func (c *FakeChaosExperiments) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosExperiment, err error) {
|
||||||
|
|
|
@ -36,9 +36,9 @@ type FakeChaosResults struct {
|
||||||
ns string
|
ns string
|
||||||
}
|
}
|
||||||
|
|
||||||
var chaosresultsResource = schema.GroupVersionResource{Group: "litmuschaos", Version: "v1alpha1", Resource: "chaosresults"}
|
var chaosresultsResource = schema.GroupVersionResource{Group: "litmuschaos.io", Version: "v1alpha1", Resource: "chaosresults"}
|
||||||
|
|
||||||
var chaosresultsKind = schema.GroupVersionKind{Group: "litmuschaos", Version: "v1alpha1", Kind: "ChaosResult"}
|
var chaosresultsKind = schema.GroupVersionKind{Group: "litmuschaos.io", Version: "v1alpha1", Kind: "ChaosResult"}
|
||||||
|
|
||||||
// Get takes name of the chaosResult, and returns the corresponding chaosResult object, and an error if there is any.
|
// Get takes name of the chaosResult, and returns the corresponding chaosResult object, and an error if there is any.
|
||||||
func (c *FakeChaosResults) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosResult, err error) {
|
func (c *FakeChaosResults) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ChaosResult, err error) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateClientSet returns a Dynamic Kubernetes ClientSet
|
// CreateClientSet returns a Dynamic Kubernetes ClientSet
|
||||||
func CreateClientSet() (*dynamic.Interface, error) {
|
func CreateClientSet() (dynamic.Interface, error) {
|
||||||
restConfig, err := config.GetConfig()
|
restConfig, err := config.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -15,5 +15,5 @@ func CreateClientSet() (*dynamic.Interface, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &clientSet, nil
|
return clientSet, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
gvrro = schema.GroupVersionResource{
|
|
||||||
Group: "argoproj.io",
|
|
||||||
Version: "v1alpha1",
|
|
||||||
Resource: "rollouts",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckRolloutAnnotation will check the annotation of argo rollout
|
|
||||||
func CheckRolloutAnnotation(clientSet dynamic.Interface, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, error) {
|
|
||||||
|
|
||||||
rolloutList, err := getRolloutList(clientSet, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
engine, chaosEnabledRollout, err := checkForChaosEnabledRollout(rolloutList, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if chaosEnabledRollout == 0 {
|
|
||||||
return engine, errors.New("no argo rollout chaos-candidate found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRolloutList returns a list of argo rollout resources that are found in the app namespace with specified label
|
|
||||||
func getRolloutList(clientSet dynamic.Interface, engine *chaosTypes.EngineInfo) (*unstructured.UnstructuredList, error) {
|
|
||||||
|
|
||||||
dynamicClient := clientSet.Resource(gvrro)
|
|
||||||
|
|
||||||
rolloutList, err := dynamicClient.Namespace(engine.AppInfo.Namespace).List(context.Background(), metav1.ListOptions{
|
|
||||||
LabelSelector: engine.Instance.Spec.Appinfo.Applabel})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error while listing argo rollouts with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
if len(rolloutList.Items) == 0 {
|
|
||||||
return nil, fmt.Errorf("no argo rollouts with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
return rolloutList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForChaosEnabledRollout will check and count the total chaos enabled application
|
|
||||||
func checkForChaosEnabledRollout(rolloutList *unstructured.UnstructuredList, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, int, error) {
|
|
||||||
|
|
||||||
chaosEnabledRollout := 0
|
|
||||||
for _, rollout := range rolloutList.Items {
|
|
||||||
annotationValue := rollout.GetAnnotations()[ChaosAnnotationKey]
|
|
||||||
if IsChaosEnabled(annotationValue) {
|
|
||||||
chaosTypes.Log.Info("chaos candidate of", "kind:", engine.AppInfo.Kind, "appName: ", rollout.GetName(), "appUUID: ", rollout.GetUID())
|
|
||||||
chaosEnabledRollout++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return engine, chaosEnabledRollout, nil
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 LitmusChaos Authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
appsV1 "k8s.io/api/apps/v1"
|
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckDaemonSetAnnotation will check the annotation of DaemonSet
|
|
||||||
func CheckDaemonSetAnnotation(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, error) {
|
|
||||||
targetAppList, err := getDaemonSetLists(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
engine, chaosEnabledDaemonSet, err := checkForChaosEnabledDaemonSet(targetAppList, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
if chaosEnabledDaemonSet == 0 {
|
|
||||||
return engine, errors.New("no chaos-candidate found")
|
|
||||||
}
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDaemonSetLists will list the daemonSets which having the chaos label
|
|
||||||
func getDaemonSetLists(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*appsV1.DaemonSetList, error) {
|
|
||||||
targetAppList, err := clientset.AppsV1().DaemonSets(engine.AppInfo.Namespace).List(context.Background(), metaV1.ListOptions{
|
|
||||||
LabelSelector: engine.Instance.Spec.Appinfo.Applabel,
|
|
||||||
FieldSelector: ""})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error while listing daemonSets with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
if len(targetAppList.Items) == 0 {
|
|
||||||
return nil, fmt.Errorf("no daemonSets apps with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
return targetAppList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForChaosEnabledDaemonSet will check and count the total chaos enabled application
|
|
||||||
func checkForChaosEnabledDaemonSet(targetAppList *appsV1.DaemonSetList, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, int, error) {
|
|
||||||
chaosEnabledDaemonSet := 0
|
|
||||||
for _, daemonSet := range targetAppList.Items {
|
|
||||||
annotationValue := daemonSet.ObjectMeta.GetAnnotations()[ChaosAnnotationKey]
|
|
||||||
if IsChaosEnabled(annotationValue) {
|
|
||||||
chaosTypes.Log.Info("chaos candidate of", "kind:", engine.AppInfo.Kind, "appName: ", daemonSet.ObjectMeta.Name, "appUUID: ", daemonSet.ObjectMeta.UID)
|
|
||||||
chaosEnabledDaemonSet++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return engine, chaosEnabledDaemonSet, nil
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 LitmusChaos Authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/apps/v1"
|
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckDeploymentAnnotation will check the annotation of deployment
|
|
||||||
func CheckDeploymentAnnotation(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, error) {
|
|
||||||
targetAppList, err := getDeploymentLists(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
engine, chaosEnabledDeployment, err := checkForChaosEnabledDeployment(targetAppList, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
if chaosEnabledDeployment == 0 {
|
|
||||||
return engine, errors.New("no chaos-candidate found")
|
|
||||||
}
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDeploymentLists will list the deployments which having the chaos label
|
|
||||||
func getDeploymentLists(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*v1.DeploymentList, error) {
|
|
||||||
targetAppList, err := clientset.AppsV1().Deployments(engine.AppInfo.Namespace).List(context.Background(), metaV1.ListOptions{
|
|
||||||
LabelSelector: engine.Instance.Spec.Appinfo.Applabel,
|
|
||||||
FieldSelector: ""})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error while listing deployments with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
if len(targetAppList.Items) == 0 {
|
|
||||||
return nil, fmt.Errorf("no deployments apps with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
return targetAppList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForChaosEnabledDeployment will check and count the total chaos enabled application
|
|
||||||
func checkForChaosEnabledDeployment(targetAppList *v1.DeploymentList, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, int, error) {
|
|
||||||
chaosEnabledDeployment := 0
|
|
||||||
for _, deployment := range targetAppList.Items {
|
|
||||||
annotationValue := deployment.ObjectMeta.GetAnnotations()[ChaosAnnotationKey]
|
|
||||||
if IsChaosEnabled(annotationValue) {
|
|
||||||
chaosTypes.Log.Info("chaos candidate of", "kind:", engine.AppInfo.Kind, "appName: ", deployment.ObjectMeta.Name, "appUUID: ", deployment.ObjectMeta.UID)
|
|
||||||
chaosEnabledDeployment++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return engine, chaosEnabledDeployment, nil
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
gvrdc = schema.GroupVersionResource{
|
|
||||||
Group: "apps.openshift.io",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "deploymentconfigs",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckDeploymentConfigAnnotation will check the annotation of deployment
|
|
||||||
func CheckDeploymentConfigAnnotation(clientSet dynamic.Interface, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, error) {
|
|
||||||
deploymentConfigList, err := getDeploymentConfigList(clientSet, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
|
|
||||||
engine, chaosEnabledDeploymentConfig, err := checkForChaosEnabledDeploymentConfig(deploymentConfigList, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if chaosEnabledDeploymentConfig == 0 {
|
|
||||||
return engine, errors.New("no deploymentconfigs chaos-candidate found")
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDeploymentConfigList(clientSet dynamic.Interface, engine *chaosTypes.EngineInfo) (*unstructured.UnstructuredList, error) {
|
|
||||||
dynamicClient := clientSet.Resource(gvrdc)
|
|
||||||
|
|
||||||
deploymentConfigList, err := dynamicClient.Namespace(engine.AppInfo.Namespace).List(context.Background(), metav1.ListOptions{
|
|
||||||
LabelSelector: engine.Instance.Spec.Appinfo.Applabel})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error while listing deploymentconfigs with matching labels: %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(deploymentConfigList.Items) == 0 {
|
|
||||||
return nil, fmt.Errorf("no deploymentconfigs with matching labels: %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
return deploymentConfigList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForChaosEnabledDeploymentConfig will check and count the total chaos enabled application
|
|
||||||
func checkForChaosEnabledDeploymentConfig(deploymentConfigList *unstructured.UnstructuredList, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, int, error) {
|
|
||||||
chaosEnabledDeploymentConfig := 0
|
|
||||||
if deploymentConfigList == nil {
|
|
||||||
return engine, chaosEnabledDeploymentConfig, fmt.Errorf("deploymentconfigs is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, deploymentConfig := range deploymentConfigList.Items {
|
|
||||||
annotationValue := deploymentConfig.GetAnnotations()[ChaosAnnotationKey]
|
|
||||||
if IsChaosEnabled(annotationValue) {
|
|
||||||
chaosTypes.Log.Info("chaos candidate of", "kind:", engine.AppInfo.Kind, "appName: ", deploymentConfig.GetName(), "appUUID: ", deploymentConfig.GetUID())
|
|
||||||
chaosEnabledDeploymentConfig++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine, chaosEnabledDeploymentConfig, nil
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 LitmusChaos Authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Annotations on app to enable chaos on it
|
|
||||||
const (
|
|
||||||
ChaosAnnotationValue = "true"
|
|
||||||
DefaultChaosAnnotationKey = "litmuschaos.io/chaos"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ChaosAnnotationKey is global variable used as the Key for annotation check.
|
|
||||||
ChaosAnnotationKey = GetAnnotationKey()
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetAnnotationKey returns the annotation to be used while validating applications.
|
|
||||||
func GetAnnotationKey() string {
|
|
||||||
|
|
||||||
annotationKey := os.Getenv("CUSTOM_ANNOTATION")
|
|
||||||
if len(annotationKey) != 0 {
|
|
||||||
return annotationKey
|
|
||||||
}
|
|
||||||
return DefaultChaosAnnotationKey
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckChaosAnnotation will check for the annotation of required resources
|
|
||||||
func CheckChaosAnnotation(engine *chaosTypes.EngineInfo, clientset kubernetes.Interface, dynamicClientSet dynamic.Interface) (*chaosTypes.EngineInfo, error) {
|
|
||||||
|
|
||||||
switch strings.ToLower(engine.AppInfo.Kind) {
|
|
||||||
case "deployment", "deployments":
|
|
||||||
engine, err := CheckDeploymentAnnotation(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, fmt.Errorf("resource type 'deployment', err: %+v", err)
|
|
||||||
}
|
|
||||||
case "statefulset", "statefulsets":
|
|
||||||
engine, err := CheckStatefulSetAnnotation(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, fmt.Errorf("resource type 'statefulset', err: %+v", err)
|
|
||||||
}
|
|
||||||
case "daemonset", "daemonsets":
|
|
||||||
engine, err := CheckDaemonSetAnnotation(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, fmt.Errorf("resource type 'daemonset', err: %+v", err)
|
|
||||||
}
|
|
||||||
case "deploymentconfig", "deploymentconfigs":
|
|
||||||
engine, err := CheckDeploymentConfigAnnotation(dynamicClientSet, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, fmt.Errorf("resource type 'deploymentconfig', err: %+v", err)
|
|
||||||
}
|
|
||||||
case "rollout", "rollouts":
|
|
||||||
engine, err := CheckRolloutAnnotation(dynamicClientSet, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, fmt.Errorf("resource type 'rollout', err: %+v", err)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return engine, fmt.Errorf("resource type '%s' not supported for induce chaos", engine.AppInfo.Kind)
|
|
||||||
}
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsChaosEnabled check for the given annotation value
|
|
||||||
func IsChaosEnabled(annotationValue string) bool {
|
|
||||||
return annotationValue == ChaosAnnotationValue
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 LitmusChaos Authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
appsV1 "k8s.io/api/apps/v1"
|
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
|
|
||||||
chaosTypes "github.com/litmuschaos/chaos-operator/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckStatefulSetAnnotation will check the annotation of StatefulSet
|
|
||||||
func CheckStatefulSetAnnotation(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, error) {
|
|
||||||
targetAppList, err := getStatefulSetLists(clientset, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
engine, chaosEnabledStatefulSet, err := checkForChaosEnabledStatefulSet(targetAppList, engine)
|
|
||||||
if err != nil {
|
|
||||||
return engine, err
|
|
||||||
}
|
|
||||||
if chaosEnabledStatefulSet == 0 {
|
|
||||||
return engine, errors.New("no chaos-candidate found")
|
|
||||||
}
|
|
||||||
return engine, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStatefulSetLists will list the statefulset which having the chaos label
|
|
||||||
func getStatefulSetLists(clientset kubernetes.Interface, engine *chaosTypes.EngineInfo) (*appsV1.StatefulSetList, error) {
|
|
||||||
targetAppList, err := clientset.AppsV1().StatefulSets(engine.AppInfo.Namespace).List(context.Background(), metaV1.ListOptions{
|
|
||||||
LabelSelector: engine.Instance.Spec.Appinfo.Applabel,
|
|
||||||
FieldSelector: ""})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error while listing statefulsets with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
if len(targetAppList.Items) == 0 {
|
|
||||||
return nil, fmt.Errorf("no statefulset apps with matching labels %s", engine.Instance.Spec.Appinfo.Applabel)
|
|
||||||
}
|
|
||||||
return targetAppList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkForChaosEnabledStatefulSet will check and count the total chaos enabled application
|
|
||||||
func checkForChaosEnabledStatefulSet(targetAppList *appsV1.StatefulSetList, engine *chaosTypes.EngineInfo) (*chaosTypes.EngineInfo, int, error) {
|
|
||||||
chaosEnabledStatefulSet := 0
|
|
||||||
for _, statefulSet := range targetAppList.Items {
|
|
||||||
annotationValue := statefulSet.ObjectMeta.GetAnnotations()[ChaosAnnotationKey]
|
|
||||||
if IsChaosEnabled(annotationValue) {
|
|
||||||
chaosTypes.Log.Info("chaos candidate of", "kind:", engine.AppInfo.Kind, "appName: ", statefulSet.ObjectMeta.Name, "appUUID: ", statefulSet.ObjectMeta.UID)
|
|
||||||
chaosEnabledStatefulSet++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return engine, chaosEnabledStatefulSet, nil
|
|
||||||
}
|
|
|
@ -38,14 +38,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// AppLabelKey contains the application label key
|
|
||||||
AppLabelKey string
|
|
||||||
|
|
||||||
// DefaultAnnotationCheck contains the default value (true) of the annotationCheck
|
|
||||||
DefaultAnnotationCheck = "false"
|
|
||||||
|
|
||||||
// AppLabelValue contains the application label value
|
|
||||||
AppLabelValue string
|
|
||||||
|
|
||||||
// Log with default name ie: controller_chaosengine
|
// Log with default name ie: controller_chaosengine
|
||||||
Log = log.Log.WithName("controller_chaosengine")
|
Log = log.Log.WithName("controller_chaosengine")
|
||||||
|
@ -57,21 +49,12 @@ var (
|
||||||
ResultCRDName = "chaosresults.litmuschaos.io"
|
ResultCRDName = "chaosresults.litmuschaos.io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApplicationInfo contains the chaos details for target application
|
// EngineInfo Related information
|
||||||
type ApplicationInfo struct {
|
|
||||||
Namespace string
|
|
||||||
Label string
|
|
||||||
ExperimentList []litmuschaosv1alpha1.ExperimentList
|
|
||||||
ServiceAccountName string
|
|
||||||
Kind string
|
|
||||||
}
|
|
||||||
|
|
||||||
//EngineInfo Related information
|
|
||||||
type EngineInfo struct {
|
type EngineInfo struct {
|
||||||
Instance *litmuschaosv1alpha1.ChaosEngine
|
Instance *litmuschaosv1alpha1.ChaosEngine
|
||||||
AppInfo *ApplicationInfo
|
AppInfo litmuschaosv1alpha1.ApplicationParams
|
||||||
ConfigMaps []litmuschaosv1alpha1.ConfigMap
|
Selectors *litmuschaosv1alpha1.Selector
|
||||||
Secrets []litmuschaosv1alpha1.Secret
|
Targets string
|
||||||
VolumeOpts utils.VolumeOpts
|
VolumeOpts utils.VolumeOpts
|
||||||
AppExperiments []string
|
AppExperiments []string
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
//VolumeOpts is a strcuture for all volume related operations
|
// VolumeOpts is a strcuture for all volume related operations
|
||||||
type VolumeOpts struct {
|
type VolumeOpts struct {
|
||||||
VolumeMounts []corev1.VolumeMount
|
VolumeMounts []corev1.VolumeMount
|
||||||
VolumeBuilders []*volume.Builder
|
VolumeBuilders []*volume.Builder
|
||||||
|
|
|
@ -22,6 +22,9 @@ import (
|
||||||
|
|
||||||
// RemoveString removes a particular string from a slice of strings
|
// RemoveString removes a particular string from a slice of strings
|
||||||
func RemoveString(slice []string, s string) (result []string) {
|
func RemoveString(slice []string, s string) (result []string) {
|
||||||
|
if len(slice) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
for _, item := range slice {
|
for _, item := range slice {
|
||||||
if item == s {
|
if item == s {
|
||||||
continue
|
continue
|
||||||
|
@ -33,7 +36,7 @@ func RemoveString(slice []string, s string) (result []string) {
|
||||||
|
|
||||||
// SetEnv sets the env inside envDetails struct
|
// SetEnv sets the env inside envDetails struct
|
||||||
func (envDetails *ENVDetails) SetEnv(key, value string) *ENVDetails {
|
func (envDetails *ENVDetails) SetEnv(key, value string) *ENVDetails {
|
||||||
if value != "" {
|
if key != "" && value != "" {
|
||||||
envDetails.ENV = append(envDetails.ENV, corev1.EnvVar{
|
envDetails.ENV = append(envDetails.ENV, corev1.EnvVar{
|
||||||
Name: key,
|
Name: key,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 LitmusChaos Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
fuzzheaders "github.com/AdaLogics/go-fuzz-headers"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FuzzSetEnv(f *testing.F) {
|
||||||
|
kv := map[string]string{
|
||||||
|
"KEY1": "VALUE1",
|
||||||
|
"KEY2": "VALUE2",
|
||||||
|
}
|
||||||
|
for k, v := range kv {
|
||||||
|
f.Add(k, v)
|
||||||
|
}
|
||||||
|
f.Fuzz(func(t *testing.T, key, value string) {
|
||||||
|
ed := ENVDetails{
|
||||||
|
ENV: make([]v1.EnvVar, 0),
|
||||||
|
}
|
||||||
|
edUpdated := ed.SetEnv(key, value)
|
||||||
|
if edUpdated == nil {
|
||||||
|
t.Error("nil object not expected")
|
||||||
|
}
|
||||||
|
if key == "" && edUpdated != nil {
|
||||||
|
assert.Equal(t, 0, len(edUpdated.ENV))
|
||||||
|
}
|
||||||
|
if value == "" && edUpdated != nil {
|
||||||
|
assert.Equal(t, 0, len(edUpdated.ENV))
|
||||||
|
}
|
||||||
|
if key != "" && value != "" && edUpdated != nil {
|
||||||
|
assert.Equal(t, 1, len(edUpdated.ENV))
|
||||||
|
}
|
||||||
|
if key != "" && value != "" && edUpdated != nil && len(edUpdated.ENV) == 1 {
|
||||||
|
env := edUpdated.ENV[0]
|
||||||
|
assert.Equal(t, key, env.Name)
|
||||||
|
assert.Equal(t, value, env.Value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzRemoveString(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, extra string, data []byte) {
|
||||||
|
consumer := fuzzheaders.NewConsumer(data)
|
||||||
|
testInput := &struct {
|
||||||
|
Data map[string]int
|
||||||
|
}{}
|
||||||
|
err := consumer.GenerateStruct(testInput)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
max := len(testInput.Data) - 1
|
||||||
|
if max < 0 {
|
||||||
|
max = 0
|
||||||
|
}
|
||||||
|
randomNumber := func(min, max int) int {
|
||||||
|
if max == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rand.Intn(max-min) + min
|
||||||
|
}(0, max)
|
||||||
|
index := 0
|
||||||
|
full := make([]string, 0)
|
||||||
|
exclude := ""
|
||||||
|
result := make([]string, 0)
|
||||||
|
for k := range testInput.Data {
|
||||||
|
if k == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !func() bool {
|
||||||
|
for _, r := range k {
|
||||||
|
if !unicode.IsLetter(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
full = append(full, k)
|
||||||
|
if index == randomNumber {
|
||||||
|
exclude = k
|
||||||
|
}
|
||||||
|
if index != randomNumber {
|
||||||
|
result = append(result, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exclude != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
got := RemoveString(full, exclude)
|
||||||
|
if got == nil {
|
||||||
|
got = make([]string, 0)
|
||||||
|
}
|
||||||
|
assert.Equal(t, result, got)
|
||||||
|
})
|
||||||
|
}
|
|
@ -6,11 +6,6 @@ import (
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// hostpathTypeFile represents the hostpath type
|
|
||||||
hostpathTypeFile = corev1.HostPathFile
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateVolumeBuilders build Volume needed in execution of experiments
|
// CreateVolumeBuilders build Volume needed in execution of experiments
|
||||||
func CreateVolumeBuilders(configMaps []v1alpha1.ConfigMap, secrets []v1alpha1.Secret) []*volume.Builder {
|
func CreateVolumeBuilders(configMaps []v1alpha1.ConfigMap, secrets []v1alpha1.Secret) []*volume.Builder {
|
||||||
volumeBuilderList := []*volume.Builder{}
|
volumeBuilderList := []*volume.Builder{}
|
||||||
|
|
|
@ -119,7 +119,7 @@ var _ = BeforeSuite(func() {
|
||||||
klog.Infoln("Chaos-Operator is in running state")
|
klog.Infoln("Chaos-Operator is in running state")
|
||||||
})
|
})
|
||||||
|
|
||||||
//BDD Tests to check secondary resources
|
// BDD Tests to check secondary resources
|
||||||
var _ = Describe("BDD on chaos-operator", func() {
|
var _ = Describe("BDD on chaos-operator", func() {
|
||||||
|
|
||||||
// BDD TEST CASE 1
|
// BDD TEST CASE 1
|
||||||
|
@ -437,25 +437,6 @@ var _ = Describe("BDD on chaos-operator", func() {
|
||||||
})
|
})
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Should change EngineStatus ", func() {
|
|
||||||
|
|
||||||
err := retry.
|
|
||||||
Times(uint(180 / 2)).
|
|
||||||
Wait(time.Duration(2) * time.Second).
|
|
||||||
Try(func(attempt uint) error {
|
|
||||||
//Fetching engineStatus
|
|
||||||
engine, err := clientSet.ChaosEngines("litmus").Get(context.Background(), "engine-nginx-1", metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if engine.Status.EngineStatus != v1alpha1.EngineStatusCompleted {
|
|
||||||
return fmt.Errorf("engine is not in completed state")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("Validate via Chaos-Operator Logs", func() {
|
Context("Validate via Chaos-Operator Logs", func() {
|
||||||
|
@ -505,7 +486,7 @@ var _ = Describe("BDD on chaos-operator", func() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
//Deleting all unused resources
|
// Deleting all unused resources
|
||||||
var _ = AfterSuite(func() {
|
var _ = AfterSuite(func() {
|
||||||
|
|
||||||
//Deleting Pod Delete sa
|
//Deleting Pod Delete sa
|
||||||
|
|
Loading…
Reference in New Issue