Compare commits

...

62 Commits

Author SHA1 Message Date
Namkyu Park 173b5ff688
feat: implement otel telemetry sdk for distributed tracing (#221)
* feat: implement otel sdk

Signed-off-by: namkyu1999 <lak9348@konkuk.ac.kr>

* fix: update endpoint

Signed-off-by: namkyu1999 <lak9348@konkuk.ac.kr>

* fix: fix context logic

Signed-off-by: namkyu1999 <lak9348@konkuk.ac.kr>

* fix: make otel optional

Signed-off-by: namkyu1999 <lak9348@konkuk.ac.kr>

* (chore): Fix the release pipeline (#224)

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

* fix: add logs

Signed-off-by: namkyu1999 <lak9348@gmail.com>

* chore

Signed-off-by: namkyu1999 <lak9348@gmail.com>

* feat: go version from 1.20 to 1.22

Signed-off-by: namkyu1999 <lak9348@gmail.com>

---------

Signed-off-by: namkyu1999 <lak9348@konkuk.ac.kr>
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
Signed-off-by: namkyu1999 <lak9348@gmail.com>
Co-authored-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2025-04-02 11:50:02 +05:30
Shubham Chaudhary b0bca2fa6b
(chore): Fix the release pipeline (#224)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2024-10-15 23:44:14 +05:30
Vedant Shrotria 7c8ef36850
Merge pull request #222 from dusdjhyeon/ubi-migration
UBI migration of Images - chaos-runner
2024-08-06 13:00:13 +05:30
dusdjhyeon 7272457ded
feat: migration base image
Signed-off-by: dusdjhyeon <dusdj0813@gmail.com>
2024-07-16 10:48:40 +09:00
Shubham Chaudhary 6437228ec2
fix(logs): fix the rank warning in logs (#220)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2024-06-01 12:20:37 +05:30
Vedant Shrotria a53618dad5
Merge pull request #219 from Jonsy13/add-gitleaks
Added `gitleaks` as PR Check
2024-05-20 10:27:41 +05:30
Vedant Shrotria 3c7fe9516a
Merge branch 'master' into add-gitleaks 2024-05-17 17:37:19 +05:30
Jonsy13 f72590cbef
Added gitleaks
Signed-off-by: Jonsy13 <vedant.shrotria@harness.io>
2024-05-17 17:34:01 +05:30
Udit Gaurav 13f8c59591
Merge pull request #218 from uditgaurav/remove_bch
Remove BCH banner from readme
2024-04-26 14:31:41 +05:30
Udit Gaurav 1a58f1b8a5 Remove BCH banner from readme
Signed-off-by: Udit Gaurav <udit.gaurav@harness.io>
2024-04-26 14:25:22 +05:30
Udit Gaurav e2dfb54db0
Merge pull request #217 from uditgaurav/fix_pipeline_issues
Fixes pipeline issues and vulnerabilities in the image
2024-04-26 14:23:01 +05:30
Udit Gaurav 516de72ae7 Update security-scan.yml 2024-04-25 21:04:42 +05:30
Udit Gaurav 4004c0bce0 Fixes pipeline issues and vulnerabilities in the image 2024-04-25 21:04:05 +05:30
Arkajyoti Mukherjee 2f3f2c41b5
chore: [CHAOS-4699]: added fuzz test for FuzzBuildContainerSpec (#215)
Signed-off-by: Arkajyoti Mukherjee <arkajyoti.mukherjee@harness.io>
2024-04-01 20:16:18 +05:30
Sayan Mondal a8eaaa6912
test: Adding fuzz test for getSetSidecarSecrets in builders.go (#214) 2024-03-14 12:05:40 +05:30
Sayan Mondal 3d2913efd0
test: Adding fuzz test for getEnvFromMap in builders.go (#213) 2024-03-14 11:24:57 +05:30
Saranya Jena f7b569a5f4
Merge pull request #211 from litmuschaos/CHAOS-4611
chore: [CHAOS-4611]: writing initial fuzz testing for chaos runner
2024-03-11 11:50:27 +05:30
Arkajyoti Mukherjee fa7f5ed86e
chore: [CHAOS-4611]: writing initial fuzz testing for chaos runner
Signed-off-by: Arkajyoti Mukherjee <arkajyoti.mukherjee@harness.io>
2024-03-08 11:15:36 +05:30
Nageshbansal c5e46ee2c7
Adds support tolerations in source cmd Probe (#210)
Signed-off-by: nagesh bansal <nageshbansal59@gmail.com>
2024-03-01 14:51:20 +05:30
Nageshbansal 6750e9f25e
Adds verbosity property (#209)
Signed-off-by: nagesh bansal <nageshbansal59@gmail.com>
2024-01-11 17:32:50 +05:30
Shubham Chaudhary adee28bdd6
fix the go deps (#208)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-12-15 14:15:07 +05:30
Shubham Chaudhary 23f11723a8
fix the chaoshub fault url (#205)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-09-29 16:26:26 +05:30
Udit Gaurav a06a78a02f
Merge pull request #204 from Adarshkumar14/logrus-fix
Upgrading logrus version to v1.9.3 to resolve the vulnerability
2023-07-18 17:30:08 +05:30
Adarsh kumar 35bff87d87 upgrading logrus version
Signed-off-by: Adarsh kumar <adarsh.kumar@harness.io>
2023-07-18 17:18:56 +05:30
Udit Gaurav 6a91bd6f22
Merge pull request #203 from Adarshkumar14/master
Upgrading go version to 1.20
2023-07-18 17:05:38 +05:30
Adarsh kumar f3e98d147f updating go version
Signed-off-by: Adarsh kumar <adarsh.kumar@harness.io>
2023-07-13 14:14:00 +05:30
Adarsh kumar 755acc1c9a Merge branch 'master' of https://github.com/Adarshkumar14/chaos-runner 2023-07-03 14:52:10 +05:30
Adarsh kumar f441876f7a Upgrading go version
Signed-off-by: Adarsh kumar <adarsh.kumar@harness.io>
2023-07-03 14:52:06 +05:30
Shubham Chaudhary e2040a77a8
fixing the docker buildx progess argument (#202)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-06-20 11:54:01 +05:30
Vedant Shrotria 583f5316a4
Merge pull request #200 from Jonsy13/group-optional-runner
Upgrading chaos-operator version (making group optional in k8s probe)
2023-06-05 19:00:42 +05:30
Jonsy13 d18f671758
Added changes for operator upgrade
Signed-off-by: Jonsy13 <vedant.shrotria@harness.io>
2023-06-05 13:12:24 +05:30
Vedant Shrotria e97bbebf52
Merge pull request #199 from Adarshkumar14/master
upgrading go version to 1.19 to fix vulnerabilities
2023-05-26 15:32:04 +05:30
Adarsh kumar 58cf26a08b upgrading go version
Signed-off-by: Adarsh kumar <adarsh.kumar@harness.io>
2023-05-26 15:22:09 +05:30
Shubham Chaudhary bb185d5c91
chore(fields): Updating optional fields to pointer type (#197)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-04-25 12:10:46 +05:30
Shubham Chaudhary 01d959c862
run workflow on dispatch event and use token from secrets (#196)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-04-20 13:22:25 +05:30
Shubham Chaudhary 7ecca3c448
chore(unit): Adding units to the duration fields (#195)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-04-18 13:07:50 +05:30
Amit Kumar Das c05b15a1b8
Updated go mod for slo probes (#194)
* Updated go mod for slo probes

Signed-off-by: Amit Kumar Das <amit.das@harness.io>

* go mod tidy

Signed-off-by: Amit Kumar Das <amit.das@harness.io>

---------

Signed-off-by: Amit Kumar Das <amit.das@harness.io>
2023-04-08 22:54:04 +05:30
Shubham Chaudhary 1238882011
Updating the probe schema (#193)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-03-09 21:26:03 +05:30
Shubham Chaudhary 5cbdaa576e
update(crd): updating the chaosengine crd (#192)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-03-08 13:21:02 +05:30
Shubham Chaudhary 09a62c04cb
chore(sidecar): adding sidecar to the experiment pod (#190)
* chore(sidecar): adding sidecar to the experiment  pod

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

* updating go mod

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

* chore(sidecar): adding env and envFrom fields

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2023-01-10 12:19:36 +05:30
Shubham Chaudhary 8357b15524
chore(engine): Adding chaosengine labels to experiment pod (#189)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-12-26 13:57:33 +05:30
Shubham Chaudhary 60295079df
feat(statuschecktimeout): Fixing case when only one of the timeout or delay is defined (#188)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-11-29 20:01:06 +05:30
Shubham Chaudhary b48382b39a
Adding selectors inside the chaosengine (#187)
* feat(selectors): Adding selectors inside the chaosengine (#181)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-11-21 22:16:56 +05:30
Soumya Ghosh Dastidar b3593a3c8c
feat: update chaos operator (#184)
Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>

Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
2022-11-14 12:14:39 +05:30
Udit Gaurav 092097295c
Chore(healthCheck): Update default healthCheck tunable in engine (#183)
Signed-off-by: uditgaurav <udit@chaosnative.com>
2022-10-06 14:28:48 +05:30
Udit Gaurav 360649a7cb
Core(docs): Pull new cmdProbe inherit field and Removal of responseTimeout field into chaos-runner (#180)
* Pull cmdProbe inherit changes into runner

Signed-off-by: uditgaurav <udit@chaosnative.com>
2022-09-29 16:03:54 +05:30
Shubham Chaudhary 9996579456
update(sdk): updating operator sdk version (#179)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-09-28 09:59:20 +05:30
Shubham Chaudhary 421160c0a7
chore(env): Adding service acccount as an env (#178)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-09-05 12:10:09 +05:30
Udit Gaurav d0e8dfb20d
Merge pull request #177 from uditgaurav/fix_test_e2e_pipeline
Fix K3s cluster creation in the pipeline by providing version
2022-08-16 18:41:04 +05:30
uditgaurav a539b63e37 Fix K3s cluster creation in the pipeline by providing version
Signed-off-by: uditgaurav <udit@chaosnative.com>
2022-08-16 18:31:59 +05:30
Shubham Chaudhary b2962a7069
chore(cmdProbe): Updating go.mod for cmd probe changes (#176)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-08-04 19:46:06 +05:30
Shubham Chaudhary 44a8ecac17
updating the go.mod for the source cmdProbe (#175)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-07-14 19:54:19 +05:30
Shubham Chaudhary 3afc7b9456
Updating litmus-clientset and k8s version to 1.21.2 (#174)
Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
2022-07-14 18:48:37 +05:30
Udit Gaurav fb1776f9ec
Merge pull request #171 from uditgaurav/update_build_flag
Chore(build): Fix the go build by providing -buildvcs=false flag
2022-04-16 22:42:36 +05:30
uditgaurav a1d0e0e07a Chore(build): Fix the go build by providing -buildvcs=false flag
Signed-off-by: uditgaurav <udit@chaosnative.com>
2022-04-16 14:18:03 +05:30
Udit Gaurav d7c558baa7
Chore(snyk): Fix snyk security scan on chaos-runner (#170)
Signed-off-by: uditgaurav <udit@chaosnative.com>
2022-03-15 08:12:54 +05:30
Udit Gaurav c06566bc86
Chore(vulnerability): Update Go mod pkgs (#169)
Signed-off-by: udit <udit@chaosnative.com>
2022-03-03 18:30:49 +05:30
Udit Gaurav a764c000b8
Merge pull request #168 from uditgaurav/go_version_for_release
Update go version to 1.17 for release build
2021-12-15 17:50:10 +05:30
udit 5469b60df4 Update go version to 1.17 for release build
Signed-off-by: udit <udit@chaosnative.com>
2021-12-15 17:48:23 +05:30
Udit Gaurav 521d6244be
Merge pull request #167 from uditgaurav/update_go.sum
Chore(update): Update go.sum and go version to 1.17 for chaos-runner
2021-12-15 17:09:46 +05:30
udit f3c0cd68f1 Chore(update): Update go.sum for chaos-runner
Signed-off-by: udit <udit@chaosnative.com>
2021-12-15 15:33:56 +05:30
Shubham Chaudhary 177e29c6e0
chore(retry): adding retries for the kubeapi request (#165)
Signed-off-by: shubham chaudhary <shubham@chaosnative.com>
2021-11-10 10:27:41 +05:30
41 changed files with 1169 additions and 1526 deletions

View File

@ -10,7 +10,7 @@ jobs:
# Install golang # Install golang
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: 1.16 go-version: 1.20.0
# Checkout to the latest commit # Checkout to the latest commit
# On specific directory/path # On specific directory/path
@ -26,17 +26,18 @@ jobs:
- name: unused-package check - name: unused-package check
run: make unused-package-check run: make unused-package-check
security: gitleaks-scan:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@v3
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/golang@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with: with:
args: --severity-threshold=high 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
trivy: trivy:
needs: pre-checks needs: pre-checks
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -83,7 +84,7 @@ jobs:
# Install golang # Install golang
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: 1.16 go-version: 1.22.0
# Checkout to the latest commit # Checkout to the latest commit
# On specific directory/path # On specific directory/path
@ -95,7 +96,7 @@ jobs:
env: env:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml KUBECONFIG: /etc/rancher/k3s/k3s.yaml
run: | run: |
curl -sfL https://get.k3s.io | sh -s - --docker --write-kubeconfig-mode 664 curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.21.11+k3s1 sh -s - --docker --write-kubeconfig-mode 664
kubectl wait node --all --for condition=ready --timeout=90s kubectl wait node --all --for condition=ready --timeout=90s
mkdir -p $HOME/.kube mkdir -p $HOME/.kube
cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config

View File

@ -13,7 +13,7 @@ jobs:
# Install golang # Install golang
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: 1.16 go-version: 1.22.0
# Checkout to the latest commit # Checkout to the latest commit
# On specific directory/path # On specific directory/path
@ -31,7 +31,6 @@ jobs:
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,44 +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-runner run: make push-chaos-runner
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.16
- name: Build chaos-runner image
run: make build-amd64
#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 | 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
env:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
run: |
make deps
- name: Running Go BDD Test
env:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
run: |
make test

View File

@ -11,25 +11,15 @@ jobs:
# Install golang # Install golang
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: 1.16 go-version: 1.22.0
# 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,45 +63,3 @@ jobs:
DNAME: ${{ secrets.DNAME }} DNAME: ${{ secrets.DNAME }}
DPASS: ${{ secrets.DPASS }} DPASS: ${{ secrets.DPASS }}
run: make push-chaos-runner run: make push-chaos-runner
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.16
#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 | 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-runner
DOCKER_TAG: ci
run: |
make build-amd64
- name: Running Go BDD Test
run: |
make test

24
.github/workflows/security-scan.yml vendored Normal file
View File

@ -0,0 +1,24 @@
---
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-runner:${{ github.sha }} . --build-arg TARGETARCH=amd64
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'docker.io/litmuschaos/chaos-runner:${{ github.sha }}'
format: 'table'
exit-code: '1'
ignore-unfixed: true
vuln-type: 'os,library'
severity: 'CRITICAL,HIGH'

View File

@ -52,14 +52,14 @@ build-chaos-runner:
@echo "-------------------------" @echo "-------------------------"
@echo "--> Build chaos-runner image" @echo "--> Build chaos-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-runner .PHONY: push-chaos-runner
push-chaos-runner: push-chaos-runner:
@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:

View File

@ -7,7 +7,6 @@
[![Twitter Follow](https://img.shields.io/twitter/follow/litmuschaos?style=social)](https://twitter.com/LitmusChaos) [![Twitter Follow](https://img.shields.io/twitter/follow/litmuschaos?style=social)](https://twitter.com/LitmusChaos)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5291/badge)](https://bestpractices.coreinfrastructure.org/projects/5291) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5291/badge)](https://bestpractices.coreinfrastructure.org/projects/5291)
[![Go Report Card](https://goreportcard.com/badge/github.com/litmuschaos/chaos-runner)](https://goreportcard.com/report/github.com/litmuschaos/chaos-runner) [![Go Report Card](https://goreportcard.com/badge/github.com/litmuschaos/chaos-runner)](https://goreportcard.com/report/github.com/litmuschaos/chaos-runner)
[![BCH compliance](https://bettercodehub.com/edge/badge/litmuschaos/chaos-runner?branch=master)](https://bettercodehub.com/)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-runner.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-runner?ref=badge_shield) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-runner.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Flitmuschaos%2Fchaos-runner?ref=badge_shield)
[![YouTube Channel](https://img.shields.io/badge/YouTube-Subscribe-red)](https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw) [![YouTube Channel](https://img.shields.io/badge/YouTube-Subscribe-red)](https://www.youtube.com/channel/UCa57PMqmz_j0wnteRa9nCaw)
<br><br> <br><br>

View File

@ -1,10 +1,16 @@
package main package main
import ( import (
"context"
"errors"
"os"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/litmuschaos/chaos-runner/pkg/telemetry"
"github.com/litmuschaos/chaos-runner/pkg/utils" "github.com/litmuschaos/chaos-runner/pkg/utils"
"github.com/litmuschaos/chaos-runner/pkg/utils/analytics" "github.com/litmuschaos/chaos-runner/pkg/utils/analytics"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opentelemetry.io/otel"
) )
func init() { func init() {
@ -17,9 +23,26 @@ func init() {
} }
func main() { func main() {
ctx := context.Background()
// Set up Observability.
if otelExporterEndpoint := os.Getenv(telemetry.OTELExporterOTLPEndpoint); otelExporterEndpoint != "" {
shutdown, err := telemetry.InitOTelSDK(ctx, otelExporterEndpoint)
if err != nil {
log.Errorf("Failed to initialize OTel SDK: %v", err)
return
}
defer func() {
err = errors.Join(err, shutdown(ctx))
}()
ctx = telemetry.GetTraceParentContext()
}
engineDetails := utils.EngineDetails{} engineDetails := utils.EngineDetails{}
clients := utils.ClientSets{} clients := utils.ClientSets{}
ctx, span := otel.Tracer(telemetry.TracerName).Start(ctx, "ExecuteChaosRunner")
defer span.End()
// Getting kubeConfig and Generate ClientSets // Getting kubeConfig and Generate ClientSets
if err := clients.GenerateClientSetFromKubeConfig(); err != nil { if err := clients.GenerateClientSetFromKubeConfig(); err != nil {
log.Errorf("unable to create ClientSets, error: %v", err) log.Errorf("unable to create ClientSets, error: %v", err)
@ -35,9 +58,7 @@ func main() {
log.InfoWithValues("Experiments details are as follows", logrus.Fields{ log.InfoWithValues("Experiments details are as follows", logrus.Fields{
"Experiments List": engineDetails.Experiments, "Experiments List": engineDetails.Experiments,
"Engine Name": engineDetails.Name, "Engine Name": engineDetails.Name,
"appLabels": engineDetails.AppLabel, "Targets": engineDetails.Targets,
"appNs": engineDetails.AppNs,
"appKind": engineDetails.AppKind,
"Service Account Name": engineDetails.SvcAccount, "Service Account Name": engineDetails.SvcAccount,
"Engine Namespace": engineDetails.EngineNamespace, "Engine Namespace": engineDetails.EngineNamespace,
}) })
@ -68,12 +89,19 @@ func main() {
continue continue
} }
// derive the envs from the chaos experiment and override their values from chaosengine if any // derive the envs from the chaos experiment and override their values from chaosengine if any
if err := experiment.SetENV(engineDetails, clients); err != nil { if err := experiment.SetENV(ctx, engineDetails, clients); err != nil {
log.Errorf("unable to patch ENV, error: %v", err) log.Errorf("unable to patch ENV, error: %v", err)
experiment.ExperimentSkipped(utils.ExperimentEnvParseErrorReason, engineDetails, clients) experiment.ExperimentSkipped(utils.ExperimentEnvParseErrorReason, engineDetails, clients)
engineDetails.ExperimentSkippedPatchEngine(&experiment, clients) engineDetails.ExperimentSkippedPatchEngine(&experiment, clients)
continue continue
} }
// derive the sidecar details from chaosengine
if err := experiment.SetSideCarDetails(engineDetails.Name, clients); err != nil {
log.Errorf("unable to get sidecar details, error: %v", err)
experiment.ExperimentSkipped(utils.ExperimentSideCarPatchErrorReason, engineDetails, clients)
engineDetails.ExperimentSkippedPatchEngine(&experiment, clients)
continue
}
log.Infof("Preparing to run Chaos Experiment: %v", experiment.Name) log.Infof("Preparing to run Chaos Experiment: %v", experiment.Name)
@ -87,7 +115,7 @@ func main() {
experiment.ExperimentDependencyCheck(engineDetails, clients) experiment.ExperimentDependencyCheck(engineDetails, clients)
// Creation of PodTemplateSpec, and Final Job // Creation of PodTemplateSpec, and Final Job
if err := utils.BuildingAndLaunchJob(&experiment, clients); err != nil { if err := utils.BuildingAndLaunchJob(ctx, &experiment, clients); err != nil {
log.Errorf("unable to construct chaos experiment job, error: %v", err) log.Errorf("unable to construct chaos experiment job, error: %v", err)
experiment.ExperimentSkipped(utils.ExperimentDependencyCheckReason, engineDetails, clients) experiment.ExperimentSkipped(utils.ExperimentDependencyCheckReason, engineDetails, clients)
engineDetails.ExperimentSkippedPatchEngine(&experiment, clients) engineDetails.ExperimentSkippedPatchEngine(&experiment, clients)

View File

@ -14,17 +14,18 @@ RUN export GOOS=$(echo ${TARGETPLATFORM} | cut -d / -f1) && \
RUN go env RUN go env
RUN CGO_ENABLED=0 go build -o /output/chaos-runner -v ./bin RUN CGO_ENABLED=0 go build -buildvcs=false -o /output/chaos-runner -v ./bin
# Packaging stage # Packaging stage
# Image source: https://github.com/litmuschaos/test-tools/blob/master/custom/hardend-alpine/control-plane/Dockerfile FROM registry.access.redhat.com/ubi9/ubi-minimal:9.4
# The base image is non-root (have litmus user) with default litmus directory.
FROM litmuschaos/infra-alpine
LABEL maintainer="LitmusChaos" LABEL maintainer="LitmusChaos"
ENV RUNNER=/usr/local/bin/chaos-runner ENV RUNNER=/usr/local/bin/chaos-runner
COPY --from=builder /output/chaos-runner ${RUNNER} COPY --from=builder /output/chaos-runner ${RUNNER}
RUN chown 65534:0 ${RUNNER} && chmod 755 ${RUNNER}
USER 65534
ENTRYPOINT ["/usr/local/bin/chaos-runner"] ENTRYPOINT ["/usr/local/bin/chaos-runner"]

115
go.mod
View File

@ -1,46 +1,95 @@
module github.com/litmuschaos/chaos-runner module github.com/litmuschaos/chaos-runner
go 1.16 go 1.22
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
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/chaos-operator v0.0.0-20210906063757-231a74b4452d github.com/litmuschaos/chaos-operator v0.0.0-20240601063404-e96a7ee7f1f7
github.com/litmuschaos/elves v0.0.0-20210325101625-5620f93aed51 github.com/litmuschaos/elves v0.0.0-20230607095010-c7119636b529
github.com/litmuschaos/litmus-go v0.0.0-20210914084212-c40973c39565 github.com/litmuschaos/litmus-go v0.0.0-20230605073551-d73728198577
github.com/onsi/ginkgo v1.12.0 github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.9.0 github.com/onsi/gomega v1.15.0
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus v1.9.3
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf // indirect github.com/stretchr/testify v1.9.0
golang.org/x/sys v0.0.0-20210921065528-437939a70204 // indirect go.opentelemetry.io/otel v1.27.0
k8s.io/api v0.22.2 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0
k8s.io/apimachinery v0.22.2 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0
go.opentelemetry.io/otel/sdk v1.27.0
k8s.io/api v0.26.0
k8s.io/apimachinery v0.26.0
k8s.io/client-go v12.0.0+incompatible k8s.io/client-go v12.0.0+incompatible
) )
// Pinned to kubernetes-1.16.2 require (
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/palantir/stacktrace v0.0.0-20161112013806-78658fd2d177 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.opentelemetry.io/otel/metric v1.27.0 // indirect
go.opentelemetry.io/otel/trace v1.27.0 // indirect
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
sigs.k8s.io/controller-runtime v0.10.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
// Pinned to kubernetes-1.21.2
replace ( replace (
k8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a k8s.io/api => k8s.io/api v0.21.2
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65 k8s.io/apimachinery => k8s.io/apimachinery v0.21.2
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8 k8s.io/cli-runtime => k8s.io/cli-runtime v0.21.2
k8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d k8s.io/client-go => k8s.io/client-go v0.21.2
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5 k8s.io/cloud-provider => k8s.io/cloud-provider v0.21.2
k8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48 k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.21.2
k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458 k8s.io/component-base => k8s.io/component-base v0.21.2
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42 k8s.io/cri-api => k8s.io/cri-api v0.21.2
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.21.2
k8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9 k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.21.2
k8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.21.2
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd k8s.io/kube-proxy => k8s.io/kube-proxy v0.21.2
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4 k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.21.2
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df k8s.io/kubectl => k8s.io/kubectl v0.21.2
k8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229 k8s.io/kubelet => k8s.io/kubelet v0.21.2
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.21.2
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51 k8s.io/metrics => k8s.io/metrics v0.21.2
k8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.21.2
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b
k8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9
) )
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
replace golang.org/x/net => golang.org/x/net v0.17.0

1373
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -4,24 +4,24 @@ import (
logrus "github.com/sirupsen/logrus" logrus "github.com/sirupsen/logrus"
) )
//Fatalf Logs first and then calls `logger.Exit(1)` // Fatalf Logs first and then calls `logger.Exit(1)`
// logging level is set to Panic. // logging level is set to Panic.
func Fatalf(msg string, err error) { func Fatalf(msg string, err error) {
logrus.WithFields(logrus.Fields{}).Fatalf(msg, err) logrus.WithFields(logrus.Fields{}).Fatalf(msg, err)
} }
//Fatal Logs first and then calls `logger.Exit(1)` // Fatal Logs first and then calls `logger.Exit(1)`
// logging level is set to Panic. // logging level is set to Panic.
func Fatal(msg string) { func Fatal(msg string) {
logrus.WithFields(logrus.Fields{}).Fatal(msg) logrus.WithFields(logrus.Fields{}).Fatal(msg)
} }
//Infof log the General operational entries about what's going on inside the application // Infof log the General operational entries about what's going on inside the application
func Infof(msg string, val ...interface{}) { func Infof(msg string, val ...interface{}) {
logrus.WithFields(logrus.Fields{}).Infof(msg, val...) logrus.WithFields(logrus.Fields{}).Infof(msg, val...)
} }
//Info log the General operational entries about what's going on inside the application // Info log the General operational entries about what's going on inside the application
func Info(msg string) { func Info(msg string) {
logrus.WithFields(logrus.Fields{}).Infof(msg) logrus.WithFields(logrus.Fields{}).Infof(msg)
} }
@ -38,23 +38,23 @@ func ErrorWithValues(msg string, val map[string]interface{}) {
logrus.WithFields(val).Error(msg) logrus.WithFields(val).Error(msg)
} }
//Warn log the Non-critical entries that deserve eyes. // Warn log the Non-critical entries that deserve eyes.
func Warn(msg string) { func Warn(msg string) {
logrus.WithFields(logrus.Fields{}).Warn(msg) logrus.WithFields(logrus.Fields{}).Warn(msg)
} }
//Warnf log the Non-critical entries that deserve eyes. // Warnf log the Non-critical entries that deserve eyes.
func Warnf(msg string, val ...interface{}) { func Warnf(msg string, val ...interface{}) {
logrus.WithFields(logrus.Fields{}).Warnf(msg, val...) logrus.WithFields(logrus.Fields{}).Warnf(msg, val...)
} }
//Errorf used for errors that should definitely be noted. // Errorf used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service. // Commonly used for hooks to send errors to an error tracking service.
func Errorf(msg string, err ...interface{}) { func Errorf(msg string, err ...interface{}) {
logrus.WithFields(logrus.Fields{}).Errorf(msg, err...) logrus.WithFields(logrus.Fields{}).Errorf(msg, err...)
} }
//Error used for errors that should definitely be noted. // Error used for errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service // Commonly used for hooks to send errors to an error tracking service
func Error(msg string) { func Error(msg string) {
logrus.WithFields(logrus.Fields{}).Error(msg) logrus.WithFields(logrus.Fields{}).Error(msg)

89
pkg/telemetry/otel.go Normal file
View File

@ -0,0 +1,89 @@
package telemetry
import (
"context"
"errors"
log "github.com/sirupsen/logrus"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
)
// TODO: change endpoint to be configurable
const OTELExporterOTLPEndpoint = "OTEL_EXPORTER_OTLP_ENDPOINT"
const OTELServiceName = "chaos_runner"
func InitOTelSDK(ctx context.Context, endpoint string) (shutdown func(context.Context) error, err error) {
var shutdownFuncs []func(context.Context) error
shutdown = func(ctx context.Context) error {
var err error
for _, fn := range shutdownFuncs {
err = errors.Join(err, fn(ctx))
}
shutdownFuncs = nil
return err
}
handleErr := func(inErr error) {
err = errors.Join(inErr, shutdown(ctx))
}
tracerProvider, err := newTracerProvider(ctx, endpoint)
if err != nil {
handleErr(err)
return
}
prop := newPropagator()
otel.SetTextMapPropagator(prop)
shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown)
otel.SetTracerProvider(tracerProvider)
log.Info("OTel SDK initialized")
// TODO: need to add metrics & logging provider
return
}
func newPropagator() propagation.TextMapPropagator {
return propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
)
}
func newTracerProvider(ctx context.Context, endpoint string) (*trace.TracerProvider, error) {
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String(OTELServiceName),
),
)
traceExporter, err := otlptrace.New(
ctx,
otlptracegrpc.NewClient(
// TODO: add secure option
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithEndpoint(endpoint),
),
)
if err != nil {
return nil, err
}
batchSpanProcessor := sdktrace.NewBatchSpanProcessor(traceExporter)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(batchSpanProcessor),
)
return tracerProvider, nil
}

52
pkg/telemetry/tracing.go Normal file
View File

@ -0,0 +1,52 @@
package telemetry
import (
"context"
"encoding/json"
"os"
"github.com/litmuschaos/chaos-runner/pkg/log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)
const (
TracerName = "litmuschaos.io/chaos-runner"
TraceParent = "TRACE_PARENT"
)
func GetTraceParentContext() context.Context {
traceParent := os.Getenv(TraceParent)
pro := otel.GetTextMapPropagator()
carrier := make(map[string]string)
if err := json.Unmarshal([]byte(traceParent), &carrier); err != nil {
log.Fatal(err.Error())
}
return pro.Extract(context.Background(), propagation.MapCarrier(carrier))
}
// GetMarshalledSpanFromContext Extract spanContext from the context and return it as json encoded string
func GetMarshalledSpanFromContext(ctx context.Context) string {
carrier := make(map[string]string)
pro := otel.GetTextMapPropagator()
pro.Inject(ctx, propagation.MapCarrier(carrier))
if len(carrier) == 0 {
log.Error("spanContext not present in the context, unable to marshall")
return ""
}
marshalled, err := json.Marshal(carrier)
if err != nil {
log.Error(err.Error())
return ""
}
if len(marshalled) >= 1024 {
log.Error("marshalled span context is too large, unable to marshall")
return ""
}
return string(marshalled)
}

View File

@ -1,16 +1,20 @@
package utils package utils
import ( import (
"context"
"reflect" "reflect"
"github.com/pkg/errors" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
batchv1 "k8s.io/api/batch/v1" "github.com/litmuschaos/chaos-runner/pkg/telemetry"
corev1 "k8s.io/api/core/v1"
"github.com/litmuschaos/elves/kubernetes/container" "github.com/litmuschaos/elves/kubernetes/container"
"github.com/litmuschaos/elves/kubernetes/job" "github.com/litmuschaos/elves/kubernetes/job"
"github.com/litmuschaos/elves/kubernetes/jobspec" "github.com/litmuschaos/elves/kubernetes/jobspec"
"github.com/litmuschaos/elves/kubernetes/podtemplatespec" "github.com/litmuschaos/elves/kubernetes/podtemplatespec"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// PodTemplateSpec is struct for creating the *core1.PodTemplateSpec // PodTemplateSpec is struct for creating the *core1.PodTemplateSpec
@ -29,15 +33,11 @@ func buildContainerSpec(experiment *ExperimentDetails, envVars []corev1.EnvVar)
WithEnvsNew(envVars) WithEnvsNew(envVars)
if !reflect.DeepEqual(experiment.SecurityContext.ContainerSecurityContext, corev1.SecurityContext{}) { if !reflect.DeepEqual(experiment.SecurityContext.ContainerSecurityContext, corev1.SecurityContext{}) {
containerSpec.WithSecurityContext(experiment.SecurityContext.ContainerSecurityContext) containerSpec.WithSecurityContext(experiment.SecurityContext.ContainerSecurityContext)
} }
if !reflect.DeepEqual(experiment.ResourceRequirements, corev1.ResourceRequirements{}) { if !reflect.DeepEqual(experiment.ResourceRequirements, corev1.ResourceRequirements{}) {
containerSpec.WithResourceRequirements(experiment.ResourceRequirements) containerSpec.WithResourceRequirements(experiment.ResourceRequirements)
} }
if experiment.VolumeOpts.VolumeMounts != nil { if experiment.VolumeOpts.VolumeMounts != nil {
@ -54,6 +54,45 @@ func buildContainerSpec(experiment *ExperimentDetails, envVars []corev1.EnvVar)
} }
// buildSideCarSpec builds a Container with following properties
func buildSideCarSpec(experiment *ExperimentDetails) ([]*container.Builder, error) {
var sidecarContainers []*container.Builder
for _, sidecar := range experiment.SideCars {
var volumeOpts VolumeOpts
if len(sidecar.Secrets) != 0 {
volumeOpts.NewVolumeMounts().BuildVolumeMountsForSecrets(sidecar.Secrets)
}
containerSpec := container.NewBuilder().
WithName(experiment.JobName + "-sidecar-" + RandomString(6)).
WithImage(sidecar.Image).
WithImagePullPolicy(sidecar.ImagePullPolicy).
WithEnvsNew(sidecar.ENV)
if !reflect.DeepEqual(experiment.ResourceRequirements, corev1.ResourceRequirements{}) {
containerSpec.WithResourceRequirements(experiment.ResourceRequirements)
}
if volumeOpts.VolumeMounts != nil {
containerSpec.WithVolumeMountsNew(volumeOpts.VolumeMounts)
}
if len(sidecar.EnvFrom) != 0 {
containerSpec.WithEnvsFrom(sidecar.EnvFrom)
}
if _, err := containerSpec.Build(); err != nil {
return nil, err
}
sidecarContainers = append(sidecarContainers, containerSpec)
}
return sidecarContainers, err
}
func getEnvFromMap(m map[string]corev1.EnvVar) []corev1.EnvVar { func getEnvFromMap(m map[string]corev1.EnvVar) []corev1.EnvVar {
var envVars []corev1.EnvVar var envVars []corev1.EnvVar
for _, v := range m { for _, v := range m {
@ -75,7 +114,10 @@ func getEnvFromMap(m map[string]corev1.EnvVar) []corev1.EnvVar {
} }
// BuildingAndLaunchJob builds Job, and then launch it. // BuildingAndLaunchJob builds Job, and then launch it.
func BuildingAndLaunchJob(experiment *ExperimentDetails, clients ClientSets) error { func BuildingAndLaunchJob(ctx context.Context, experiment *ExperimentDetails, clients ClientSets) error {
ctx, span := otel.Tracer(telemetry.TracerName).Start(ctx, "BuildingAndLaunchJob")
defer span.End()
experiment.VolumeOpts.VolumeOperations(experiment) experiment.VolumeOpts.VolumeOperations(experiment)
envVars := getEnvFromMap(experiment.envMap) envVars := getEnvFromMap(experiment.envMap)
@ -84,8 +126,19 @@ func BuildingAndLaunchJob(experiment *ExperimentDetails, clients ClientSets) err
if err != nil { if err != nil {
return errors.Errorf("unable to build Container for Chaos Experiment, error: %v", err) return errors.Errorf("unable to build Container for Chaos Experiment, error: %v", err)
} }
containers := []*container.Builder{containerForPod}
if len(experiment.SideCars) != 0 {
sidecars, err := buildSideCarSpec(experiment)
if err != nil {
return errors.Errorf("unable to build sidecar Container for Chaos Experiment, error: %v", err)
}
containers = append(containers, sidecars...)
}
// Will build a PodSpecTemplate // Will build a PodSpecTemplate
pod, err := buildPodTemplateSpec(experiment, containerForPod) pod, err := buildPodTemplateSpec(experiment, containers...)
if err != nil { if err != nil {
return errors.Errorf("unable to build PodTemplateSpec for Chaos Experiment, error: %v", err) return errors.Errorf("unable to build PodTemplateSpec for Chaos Experiment, error: %v", err)
@ -109,12 +162,12 @@ func BuildingAndLaunchJob(experiment *ExperimentDetails, clients ClientSets) err
// launchJob spawn a kubernetes Job using the job Object received. // launchJob spawn a kubernetes Job using the job Object received.
func (expDetails *ExperimentDetails) launchJob(job *batchv1.Job, clients ClientSets) error { func (expDetails *ExperimentDetails) launchJob(job *batchv1.Job, clients ClientSets) error {
_, err := clients.KubeClient.BatchV1().Jobs(expDetails.Namespace).Create(job) _, err := clients.KubeClient.BatchV1().Jobs(expDetails.Namespace).Create(context.Background(), job, v1.CreateOptions{})
return err return err
} }
// BuildPodTemplateSpec return a PodTempplateSpec // BuildPodTemplateSpec return a PodTemplateSpec
func buildPodTemplateSpec(experiment *ExperimentDetails, containerForPod *container.Builder) (*podtemplatespec.Builder, error) { func buildPodTemplateSpec(experiment *ExperimentDetails, containers ...*container.Builder) (*podtemplatespec.Builder, error) {
podtemplate := podtemplatespec.NewBuilder(). podtemplate := podtemplatespec.NewBuilder().
WithName(experiment.JobName). WithName(experiment.JobName).
WithNamespace(experiment.Namespace). WithNamespace(experiment.Namespace).
@ -123,7 +176,7 @@ func buildPodTemplateSpec(experiment *ExperimentDetails, containerForPod *contai
WithRestartPolicy(corev1.RestartPolicyNever). WithRestartPolicy(corev1.RestartPolicyNever).
WithVolumeBuilders(experiment.VolumeOpts.VolumeBuilders). WithVolumeBuilders(experiment.VolumeOpts.VolumeBuilders).
WithAnnotations(experiment.Annotations). WithAnnotations(experiment.Annotations).
WithContainerBuildersNew(containerForPod) WithContainerBuildersNew(containers...)
if experiment.TerminationGracePeriodSeconds != 0 { if experiment.TerminationGracePeriodSeconds != 0 {
podtemplate.WithTerminationGracePeriodSeconds(experiment.TerminationGracePeriodSeconds) podtemplate.WithTerminationGracePeriodSeconds(experiment.TerminationGracePeriodSeconds)
@ -135,6 +188,15 @@ func buildPodTemplateSpec(experiment *ExperimentDetails, containerForPod *contai
} }
if len(experiment.SideCars) != 0 {
secrets := setSidecarSecrets(experiment)
if len(secrets) != 0 {
var volumeOpts VolumeOpts
volumeOpts.NewVolumeBuilder().BuildVolumeBuilderForSecrets(secrets)
podtemplate.WithVolumeBuilders(volumeOpts.VolumeBuilders)
}
}
if experiment.HostPID { if experiment.HostPID {
podtemplate.WithHostPID(experiment.HostPID) podtemplate.WithHostPID(experiment.HostPID)
} }
@ -157,6 +219,20 @@ func buildPodTemplateSpec(experiment *ExperimentDetails, containerForPod *contai
return podtemplate, nil return podtemplate, nil
} }
func setSidecarSecrets(experiment *ExperimentDetails) []v1alpha1.Secret {
var secrets []v1alpha1.Secret
secretMap := make(map[string]bool)
for _, sidecar := range experiment.SideCars {
for _, secret := range sidecar.Secrets {
if _, ok := secretMap[secret.Name]; !ok {
secretMap[secret.Name] = true
secrets = append(secrets, secret)
}
}
}
return secrets
}
// BuildJobSpec returns a JobSpec // BuildJobSpec returns a JobSpec
func buildJobSpec(pod *podtemplatespec.Builder) (*jobspec.Builder, error) { func buildJobSpec(pod *podtemplatespec.Builder) (*jobspec.Builder, error) {
jobSpecObj := jobspec.NewBuilder(). jobSpecObj := jobspec.NewBuilder().

View File

@ -0,0 +1,81 @@
package utils
import (
fuzz "github.com/AdaLogics/go-fuzz-headers"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"testing"
)
func FuzzBuildContainerSpec(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzConsumer := fuzz.NewConsumer(data)
targetStruct := &struct {
ExpDetails *ExperimentDetails
EnvVars []corev1.EnvVar
}{}
err := fuzzConsumer.GenerateStruct(targetStruct)
if err != nil {
return
}
containerSpec, err := buildContainerSpec(targetStruct.ExpDetails, targetStruct.EnvVars)
if err != nil {
return
}
container, err := containerSpec.Build()
if err != nil {
return
}
require.Equal(t, targetStruct.ExpDetails.JobName, container.Name)
require.Equal(t, targetStruct.ExpDetails.ExpImage, container.Image)
require.Equal(t, targetStruct.ExpDetails.ExpCommand, container.Command)
require.Equal(t, targetStruct.ExpDetails.ExpArgs, container.Args)
require.Equal(t, targetStruct.ExpDetails.ExpImagePullPolicy, container.ImagePullPolicy)
require.Equal(t, targetStruct.EnvVars, container.Env)
})
}
func FuzzGetEnvFromMap(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzConsumer := fuzz.NewConsumer(data)
targetStruct := &struct {
m map[string]corev1.EnvVar
}{}
err := fuzzConsumer.GenerateStruct(targetStruct)
if err != nil {
return
}
envs := getEnvFromMap(targetStruct.m)
var envCount = len(envs)
require.Equal(t, envCount, len(targetStruct.m)+1)
})
}
func FuzzSetSidecarSecrets(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzConsumer := fuzz.NewConsumer(data)
targetStruct := &struct {
experiment *ExperimentDetails
}{}
err := fuzzConsumer.GenerateStruct(targetStruct)
if err != nil {
return
}
if targetStruct.experiment != nil {
secrets := setSidecarSecrets(targetStruct.experiment)
require.GreaterOrEqual(t, len(secrets), 1)
for _, sidecar := range targetStruct.experiment.SideCars {
for _, secret := range sidecar.Secrets {
for _, s := range secrets {
require.Equal(t, s.Name, secret.Name)
}
}
}
}
})
}

View File

@ -7,10 +7,10 @@ import (
) )
// RandomString will generate a random string of length 6 // RandomString will generate a random string of length 6
func RandomString() string { func RandomString(length int) string {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
chars := []rune("abcdefghijklmnopqrstuvwxyz" + "0123456789") chars := []rune("abcdefghijklmnopqrstuvwxyz" + "0123456789")
length := 6
var b strings.Builder var b strings.Builder
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
b.WriteRune(chars[rand.Intn(len(chars))]) b.WriteRune(chars[rand.Intn(len(chars))])

View File

@ -0,0 +1,38 @@
package utils
import (
"strings"
"testing"
)
func FuzzRandomString(f *testing.F) {
f.Add(6)
f.Fuzz(func(t *testing.T, n int) {
randomString := RandomString(n)
// Perform checks on the generated string
// Check if the length matches the expected length
if n >= 0 && len(randomString) != n {
t.Errorf("Generated string length doesn't match expected length")
}
// Check if the string contains only valid characters
if !isValidString(randomString) {
t.Errorf("Generated string contains invalid characters")
}
})
}
func isValidString(s string) bool {
// Define the set of valid characters
validChars := "abcdefghijklmnopqrstuvwxyz0123456789"
// Iterate over each character in the string
for _, char := range s {
// Check if the character is not in the set of valid characters
if !strings.ContainsRune(validChars, char) {
return false
}
}
return true
}

View File

@ -1,13 +1,14 @@
package utils package utils
import ( import (
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "context"
"github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
//PatchConfigMaps patches configmaps in experimentDetails struct. // PatchConfigMaps patches configmaps in experimentDetails struct.
func (expDetails *ExperimentDetails) PatchConfigMaps(clients ClientSets, engineDetails EngineDetails) error { func (expDetails *ExperimentDetails) PatchConfigMaps(clients ClientSets, engineDetails EngineDetails) error {
if err := expDetails.SetConfigMaps(clients, engineDetails); err != nil { if err := expDetails.SetConfigMaps(clients, engineDetails); err != nil {
return err return err
@ -24,7 +25,7 @@ func (expDetails *ExperimentDetails) PatchConfigMaps(clients ClientSets, engineD
// ValidatePresenceOfConfigMapResourceInCluster validates the configMap, before checking or creating them. // ValidatePresenceOfConfigMapResourceInCluster validates the configMap, before checking or creating them.
func (clientSets ClientSets) ValidatePresenceOfConfigMapResourceInCluster(configMapName, namespace string) error { func (clientSets ClientSets) ValidatePresenceOfConfigMapResourceInCluster(configMapName, namespace string) error {
_, err := clientSets.KubeClient.CoreV1().ConfigMaps(namespace).Get(configMapName, metav1.GetOptions{}) _, err := clientSets.KubeClient.CoreV1().ConfigMaps(namespace).Get(context.Background(), configMapName, metav1.GetOptions{})
return err return err
} }
@ -62,7 +63,7 @@ func (expDetails *ExperimentDetails) ValidateConfigMaps(clients ClientSets) erro
} }
func (expDetails *ExperimentDetails) getConfigMapsFromChaosExperiment(clients ClientSets) ([]v1alpha1.ConfigMap, error) { func (expDetails *ExperimentDetails) getConfigMapsFromChaosExperiment(clients ClientSets) ([]v1alpha1.ConfigMap, error) {
chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err) return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err)
} }

View File

@ -1,13 +1,14 @@
package utils package utils
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
) )
func TestPatchConfigMaps(t *testing.T) { func TestPatchConfigMaps(t *testing.T) {
@ -118,15 +119,15 @@ func TestPatchConfigMaps(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.KubeClient.CoreV1().ConfigMaps(experiment.Namespace).Create(&mock.configmap) _, err := client.KubeClient.CoreV1().ConfigMaps(experiment.Namespace).Create(context.Background(), &mock.configmap, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("configmap not created for %v test, err: %v", name, err) t.Fatalf("configmap not created for %v test, err: %v", name, err)
} }
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -231,7 +232,7 @@ func TestValidateConfigMaps(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.KubeClient.CoreV1().ConfigMaps(fakeNamespace).Create(&mock.configmap) _, err := client.KubeClient.CoreV1().ConfigMaps(fakeNamespace).Create(context.Background(), &mock.configmap, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("configmap not created for %v test, err: %v", name, err) t.Fatalf("configmap not created for %v test, err: %v", name, err)
} }
@ -279,7 +280,7 @@ func TestValidatePresenceOfConfigMapResourceInCluster(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if !mock.isErr { if !mock.isErr {
_, err := client.KubeClient.CoreV1().ConfigMaps(experiment.Namespace).Create(&mock.configmap) _, err := client.KubeClient.CoreV1().ConfigMaps(experiment.Namespace).Create(context.Background(), &mock.configmap, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("configmap not created for %v test, err: %v", name, err) t.Fatalf("configmap not created for %v test, err: %v", name, err)
} }
@ -383,13 +384,13 @@ func TestSetConfigMaps(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if !mock.isErr { if !mock.isErr {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
} }
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -447,7 +448,7 @@ func TestGetConfigMapsFromChaosExperiment(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if !mock.isErr { if !mock.isErr {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }

View File

@ -1,6 +1,8 @@
package utils package utils
import ( import (
"context"
"fmt"
"reflect" "reflect"
"strconv" "strconv"
@ -8,7 +10,12 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
)
const (
SideCarEnabled = "sidecar/enabled"
SideCarPrefix = "SIDECAR"
) )
// SetInstanceAttributeValuesFromChaosEngine set the value from the chaosengine // SetInstanceAttributeValuesFromChaosEngine set the value from the chaosengine
@ -19,13 +26,14 @@ func (expDetails *ExperimentDetails) SetInstanceAttributeValuesFromChaosEngine(e
} }
// fetch all the values from chaosengine and set into expDetails struct // fetch all the values from chaosengine and set into expDetails struct
expDetails.SetExpAnnotationFromEngine(chaosEngine). expDetails.SetExpAnnotationFromEngine(chaosEngine).
SetEngineLabels(chaosEngine).
SetExpNodeSelectorFromEngine(chaosEngine). SetExpNodeSelectorFromEngine(chaosEngine).
SetResourceRequirementsFromEngine(chaosEngine). SetResourceRequirementsFromEngine(chaosEngine).
SetImagePullSecretsFromEngine(chaosEngine). SetImagePullSecretsFromEngine(chaosEngine).
SetTolerationsFromEngine(chaosEngine). SetTolerationsFromEngine(chaosEngine).
SetExpImageFromEngine(chaosEngine). SetExpImageFromEngine(chaosEngine).
SetTerminationGracePeriodSecondsFromEngine(chaosEngine). SetTerminationGracePeriodSecondsFromEngine(chaosEngine).
SetDefaultAppHealthCheck(chaosEngine) SetDefaultHealthCheck(chaosEngine)
return nil return nil
} }
@ -107,16 +115,16 @@ func (expDetails *ExperimentDetails) SetTolerationsFromEngine(engine *litmuschao
return expDetails return expDetails
} }
// SetDefaultAppHealthCheck sets th default health checks provided inside the chaosEngine // SetDefaultHealthCheck sets th default health checks provided inside the chaosEngine
func (expDetails *ExperimentDetails) SetDefaultAppHealthCheck(engine *litmuschaosv1alpha1.ChaosEngine) *ExperimentDetails { func (expDetails *ExperimentDetails) SetDefaultHealthCheck(engine *litmuschaosv1alpha1.ChaosEngine) *ExperimentDetails {
expDetails.DefaultAppHealthCheck = engine.Spec.DefaultAppHealthCheck expDetails.DefaultHealthCheck = strconv.FormatBool(engine.Spec.DefaultHealthCheck)
return expDetails return expDetails
} }
// SetOverrideEnvFromChaosEngine override the default envs with envs passed inside the chaosengine // SetOverrideEnvFromChaosEngine override the default envs with envs passed inside the chaosengine
func (expDetails *ExperimentDetails) SetOverrideEnvFromChaosEngine(engineName string, clients ClientSets) error { func (expDetails *ExperimentDetails) SetOverrideEnvFromChaosEngine(engineName string, clients ClientSets) error {
engineSpec, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(expDetails.Namespace).Get(engineName, metav1.GetOptions{}) engineSpec, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(expDetails.Namespace).Get(context.Background(), engineName, metav1.GetOptions{})
if err != nil { if err != nil {
return errors.Errorf("unable to get ChaosEngine Resource in namespace: %v", expDetails.Namespace) return errors.Errorf("unable to get ChaosEngine Resource in namespace: %v", expDetails.Namespace)
} }
@ -133,11 +141,7 @@ func (expDetails *ExperimentDetails) SetOverrideEnvFromChaosEngine(engineName st
} }
} }
delay, timeout := 2, 180 delay, timeout := getStatusCheckDelayAndTimeout(exp)
if sc := exp.Spec.Components.StatusCheckTimeouts; !reflect.DeepEqual(sc, litmuschaosv1alpha1.StatusCheckTimeout{}) {
delay = sc.Delay
timeout = sc.Timeout
}
expDetails.envMap["STATUS_CHECK_DELAY"] = v1.EnvVar{ expDetails.envMap["STATUS_CHECK_DELAY"] = v1.EnvVar{
Name: "STATUS_CHECK_DELAY", Name: "STATUS_CHECK_DELAY",
@ -159,3 +163,97 @@ func (expDetails *ExperimentDetails) SetOverrideEnvFromChaosEngine(engineName st
return nil return nil
} }
func (expDetails *ExperimentDetails) SetSideCarDetails(engineName string, clients ClientSets) error {
engineSpec, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(expDetails.Namespace).Get(context.Background(), engineName, metav1.GetOptions{})
if err != nil {
return errors.Errorf("unable to get ChaosEngine Resource in namespace: %v", expDetails.Namespace)
}
if engineSpec.Annotations == nil {
return nil
}
if sidecarEnabled, ok := engineSpec.Annotations[SideCarEnabled]; !ok || (sidecarEnabled == "false") {
return nil
}
if len(engineSpec.Spec.Components.Sidecar) == 0 {
return fmt.Errorf("sidecar image is not set inside chaosengine")
}
expDetails.SideCars = expDetails.getSidecarDetails(engineSpec)
return nil
}
func (expDetails *ExperimentDetails) getSidecarDetails(engineSpec *litmuschaosv1alpha1.ChaosEngine) []SideCar {
var sidecars []SideCar
for _, v := range engineSpec.Spec.Components.Sidecar {
sidecar := SideCar{
Image: v.Image,
ImagePullPolicy: v.ImagePullPolicy,
Secrets: v.Secrets,
ENV: append(v.ENV, getDefaultEnvs(expDetails.JobName)...),
EnvFrom: v.EnvFrom,
}
if sidecar.ImagePullPolicy == "" {
sidecar.ImagePullPolicy = v1.PullIfNotPresent
}
sidecars = append(sidecars, sidecar)
}
return sidecars
}
func getDefaultEnvs(cName string) []v1.EnvVar {
return []v1.EnvVar{
{
Name: "POD_NAME",
ValueFrom: getEnvSource("v1", "metadata.name"),
},
{
Name: "POD_NAMESPACE",
ValueFrom: getEnvSource("v1", "metadata.namespace"),
},
{
Name: "MAIN_CONTAINER",
Value: cName,
},
}
}
// getEnvSource return the env source for the given apiVersion & fieldPath
func getEnvSource(apiVersion string, fieldPath string) *v1.EnvVarSource {
downwardENV := v1.EnvVarSource{
FieldRef: &v1.ObjectFieldSelector{
APIVersion: apiVersion,
FieldPath: fieldPath,
},
}
return &downwardENV
}
// SetEngineLabels sets the engine labels
func (expDetails *ExperimentDetails) SetEngineLabels(engine *litmuschaosv1alpha1.ChaosEngine) *ExperimentDetails {
for k, v := range engine.Labels {
expDetails.ExpLabels[k] = v
}
return expDetails
}
func getStatusCheckDelayAndTimeout(exp litmuschaosv1alpha1.ExperimentList) (int, int) {
delay, timeout := 2, 180
if sc := exp.Spec.Components.StatusCheckTimeouts; !reflect.DeepEqual(sc, litmuschaosv1alpha1.StatusCheckTimeout{}) {
if sc.Timeout != 0 {
timeout = sc.Timeout
}
if sc.Delay != 0 {
delay = sc.Delay
}
}
return delay, timeout
}

View File

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
@ -8,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
) )
@ -54,7 +55,7 @@ func TestSetExpImageFromEngine(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created, err: %v", err) t.Fatalf("engine not created, err: %v", err)
} }
@ -412,7 +413,7 @@ func TestInstanceAttributeValuesFromChaosEngine(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created, err: %v", err) t.Fatalf("engine not created, err: %v", err)
} }

View File

@ -1,28 +1,25 @@
package utils package utils
import ( import (
"context"
"os" "os"
"strconv" "strconv"
"strings" "strings"
v1 "k8s.io/api/core/v1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/litmuschaos/chaos-runner/pkg/telemetry"
v1 "k8s.io/api/core/v1"
) )
// SetEngineDetails adds the ENV's to EngineDetails // SetEngineDetails adds the ENV's to EngineDetails
func (engineDetails *EngineDetails) SetEngineDetails() *EngineDetails { func (engineDetails *EngineDetails) SetEngineDetails() *EngineDetails {
engineDetails.Experiments = strings.Split(os.Getenv("EXPERIMENT_LIST"), ",") engineDetails.Experiments = strings.Split(os.Getenv("EXPERIMENT_LIST"), ",")
engineDetails.Name = os.Getenv("CHAOSENGINE") engineDetails.Name = os.Getenv("CHAOSENGINE")
engineDetails.AppLabel = os.Getenv("APP_LABEL")
engineDetails.AppNs = os.Getenv("APP_NAMESPACE")
engineDetails.EngineNamespace = os.Getenv("CHAOS_NAMESPACE") engineDetails.EngineNamespace = os.Getenv("CHAOS_NAMESPACE")
engineDetails.AppKind = os.Getenv("APP_KIND")
engineDetails.SvcAccount = os.Getenv("CHAOS_SVC_ACC") engineDetails.SvcAccount = os.Getenv("CHAOS_SVC_ACC")
engineDetails.ClientUUID = os.Getenv("CLIENT_UUID") engineDetails.ClientUUID = os.Getenv("CLIENT_UUID")
engineDetails.AuxiliaryAppInfo = os.Getenv("AUXILIARY_APPINFO") engineDetails.AuxiliaryAppInfo = os.Getenv("AUXILIARY_APPINFO")
engineDetails.AnnotationKey = os.Getenv("ANNOTATION_KEY") engineDetails.Targets = os.Getenv("TARGETS")
engineDetails.AnnotationCheck = os.Getenv("ANNOTATION_CHECK")
return engineDetails return engineDetails
} }
@ -36,22 +33,22 @@ func (engineDetails *EngineDetails) SetEngineUID(clients ClientSets) error {
return nil return nil
} }
//SetENV sets ENV values in experimentDetails struct. // SetENV sets ENV values in experimentDetails struct.
func (expDetails *ExperimentDetails) SetENV(engineDetails EngineDetails, clients ClientSets) error { func (expDetails *ExperimentDetails) SetENV(ctx context.Context, engineDetails EngineDetails, clients ClientSets) error {
// Setting envs from engine fields other than env // Setting envs from engine fields other than env
expDetails.setEnv("CHAOSENGINE", engineDetails.Name). expDetails.setEnv("CHAOSENGINE", engineDetails.Name).
setEnv("APP_LABEL", engineDetails.AppLabel). setEnv("TARGETS", engineDetails.Targets).
setEnv("CHAOS_NAMESPACE", engineDetails.EngineNamespace). setEnv("CHAOS_NAMESPACE", engineDetails.EngineNamespace).
setEnv("APP_NAMESPACE", engineDetails.AppNs).
setEnv("APP_KIND", engineDetails.AppKind).
setEnv("AUXILIARY_APPINFO", engineDetails.AuxiliaryAppInfo). setEnv("AUXILIARY_APPINFO", engineDetails.AuxiliaryAppInfo).
setEnv("CHAOS_UID", engineDetails.UID). setEnv("CHAOS_UID", engineDetails.UID).
setEnv("EXPERIMENT_NAME", expDetails.Name). setEnv("EXPERIMENT_NAME", expDetails.Name).
setEnv("ANNOTATION_KEY", engineDetails.AnnotationKey).
setEnv("ANNOTATION_CHECK", engineDetails.AnnotationCheck).
setEnv("LIB_IMAGE_PULL_POLICY", string(expDetails.ExpImagePullPolicy)). setEnv("LIB_IMAGE_PULL_POLICY", string(expDetails.ExpImagePullPolicy)).
setEnv("TERMINATION_GRACE_PERIOD_SECONDS", strconv.Itoa(int(expDetails.TerminationGracePeriodSeconds))). setEnv("TERMINATION_GRACE_PERIOD_SECONDS", strconv.Itoa(int(expDetails.TerminationGracePeriodSeconds))).
setEnv("DEFAULT_APP_HEALTH_CHECK", expDetails.DefaultAppHealthCheck) setEnv("DEFAULT_HEALTH_CHECK", expDetails.DefaultHealthCheck).
setEnv("CHAOS_SERVICE_ACCOUNT", expDetails.SvcAccount).
setEnv("OTEL_EXPORTER_OTLP_ENDPOINT", os.Getenv(telemetry.OTELExporterOTLPEndpoint)).
setEnv("TRACE_PARENT", telemetry.GetMarshalledSpanFromContext(ctx))
// Get the Default ENV's from ChaosExperiment // Get the Default ENV's from ChaosExperiment
log.Info("Getting the ENV Variables") log.Info("Getting the ENV Variables")

View File

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"context"
"time" "time"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
@ -10,7 +11,7 @@ import (
clientTypes "k8s.io/apimachinery/pkg/types" clientTypes "k8s.io/apimachinery/pkg/types"
) )
//CreateEvents create the events in the desired resource // CreateEvents create the events in the desired resource
func (engineDetails EngineDetails) CreateEvents(eventAttributes *EventAttributes, clients ClientSets) error { func (engineDetails EngineDetails) CreateEvents(eventAttributes *EventAttributes, clients ClientSets) error {
events := &apiv1.Event{ events := &apiv1.Event{
@ -36,16 +37,16 @@ func (engineDetails EngineDetails) CreateEvents(eventAttributes *EventAttributes
}, },
} }
_, err := clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Create(events) _, err := clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Create(context.Background(), events, metav1.CreateOptions{})
return err return err
} }
//GenerateEvents update the events and increase the count by 1, if already present // GenerateEvents update the events and increase the count by 1, if already present
// else it will create a new event // else it will create a new event
func (engineDetails EngineDetails) GenerateEvents(eventAttributes *EventAttributes, clients ClientSets) error { func (engineDetails EngineDetails) GenerateEvents(eventAttributes *EventAttributes, clients ClientSets) error {
event, err := clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Get(eventAttributes.Name, metav1.GetOptions{}) event, err := clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Get(context.Background(), eventAttributes.Name, metav1.GetOptions{})
if err != nil { if err != nil {
if k8serrors.IsNotFound(err) { if k8serrors.IsNotFound(err) {
if err := engineDetails.CreateEvents(eventAttributes, clients); err != nil { if err := engineDetails.CreateEvents(eventAttributes, clients); err != nil {
@ -58,7 +59,7 @@ func (engineDetails EngineDetails) GenerateEvents(eventAttributes *EventAttribut
event.LastTimestamp = metav1.Time{Time: time.Now()} event.LastTimestamp = metav1.Time{Time: time.Now()}
event.Count = event.Count + 1 event.Count = event.Count + 1
event.Message = eventAttributes.Message event.Message = eventAttributes.Message
_, err = clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Update(event) _, err = clients.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).Update(context.Background(), event, metav1.UpdateOptions{})
return err return err
} }
return nil return nil

View File

@ -1,10 +1,13 @@
package utils package utils
import ( import (
"context"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientTypes "k8s.io/apimachinery/pkg/types" clientTypes "k8s.io/apimachinery/pkg/types"
@ -29,7 +32,7 @@ func TestCreateEvents(t *testing.T) {
t.Fatalf("TestCreateEvents failed unable to get event, err: %v", err) t.Fatalf("TestCreateEvents failed unable to get event, err: %v", err)
} }
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{}) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil || len(events.Items) == 0 { if err != nil || len(events.Items) == 0 {
t.Fatalf("TestCreateEvents failed to get events, err: %v", err) t.Fatalf("TestCreateEvents failed to get events, err: %v", err)
} }
@ -87,7 +90,7 @@ func TestGenerateEvents(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if mock.isErr { if mock.isErr {
_, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(&mock.events) _, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(context.Background(), &mock.events, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create event for %v test, err: %v", name, err) t.Fatalf("fail to create event for %v test, err: %v", name, err)
} }
@ -96,7 +99,7 @@ func TestGenerateEvents(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("%v fail to generate events, err: %v", name, err) t.Fatalf("%v fail to generate events, err: %v", name, err)
} }
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{}) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil || len(events.Items) == 0 { if err != nil || len(events.Items) == 0 {
t.Fatalf("%v fail to get events, err: %v", name, err) t.Fatalf("%v fail to get events, err: %v", name, err)
} }
@ -162,14 +165,14 @@ func TestExperimentSkipped(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if mock.isErr { if mock.isErr {
_, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(&mock.events) _, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(context.Background(), &mock.events, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create event for %v test, err: %v", name, err) t.Fatalf("fail to create event for %v test, err: %v", name, err)
} }
} }
experiment.ExperimentSkipped(eventAtr.Reason, engineDetails, client) experiment.ExperimentSkipped(eventAtr.Reason, engineDetails, client)
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{}) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil || len(events.Items) == 0 { if err != nil || len(events.Items) == 0 {
t.Fatalf("%v fail to get events, err: %v", name, err) t.Fatalf("%v fail to get events, err: %v", name, err)
} }
@ -188,12 +191,6 @@ func TestExperimentDependencyCheck(t *testing.T) {
UID: "", UID: "",
} }
eventAtr := EventAttributes{
Reason: "fake-reason",
Message: "fake-message",
Type: "fake-type",
Name: "fake-name",
}
experiment := ExperimentDetails{ experiment := ExperimentDetails{
Name: "Fake-Exp-Name", Name: "Fake-Exp-Name",
Namespace: "Fake NameSpace", Namespace: "Fake NameSpace",
@ -202,35 +199,12 @@ func TestExperimentDependencyCheck(t *testing.T) {
} }
tests := map[string]struct { tests := map[string]struct {
events v1.Event isErr bool
isErr bool
}{ }{
"Test Positive-1": { "Test Positive-1": {
isErr: false, isErr: false,
}, },
"Test Positive-2": { "Test Positive-2": {
events: v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: eventAtr.Name,
Namespace: engineDetails.EngineNamespace,
},
Source: v1.EventSource{
Component: engineDetails.Name + "-runner",
},
Message: eventAtr.Message,
Reason: eventAtr.Reason,
Type: eventAtr.Type,
Count: 1,
FirstTimestamp: metav1.Time{Time: time.Now()},
LastTimestamp: metav1.Time{Time: time.Now()},
InvolvedObject: v1.ObjectReference{
APIVersion: "litmuschaos.io/v1alpha1",
Kind: "ChaosEngine",
Name: engineDetails.Name,
Namespace: engineDetails.EngineNamespace,
UID: clientTypes.UID(engineDetails.UID),
},
},
isErr: true, isErr: true,
}, },
} }
@ -238,22 +212,21 @@ func TestExperimentDependencyCheck(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) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if mock.isErr { if !mock.isErr {
_, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(&mock.events) experiment.ExperimentDependencyCheck(engineDetails, client)
if err != nil {
t.Fatalf("fail to create event for %v test, err: %v", name, err)
}
} }
experiment.ExperimentDependencyCheck(engineDetails, client)
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{}) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil || len(events.Items) == 0 { if err != nil {
t.Fatalf("%v fail to get events, err: %v", name, err) t.Fatalf("%v fail to get events, err: %v", name, err)
} }
if mock.isErr && !strings.Contains(events.Items[1].Message, "Experiment resources validated for Chaos Experiment") { if mock.isErr {
t.Fatalf("%v failed to get the validate event message", name) require.Equal(t, 0, len(events.Items))
return
} }
require.Equal(t, 1, len(events.Items))
require.Contains(t, events.Items[0].Message, "Experiment resources validated for Chaos Experiment")
}) })
} }
} }
@ -264,13 +237,6 @@ func TestExperimentJobCreate(t *testing.T) {
EngineNamespace: "Fake NameSpace", EngineNamespace: "Fake NameSpace",
UID: "", UID: "",
} }
eventAtr := EventAttributes{
Reason: "fake-reason",
Message: "fake-message",
Type: "fake-type",
Name: "fake-name",
}
experiment := ExperimentDetails{ experiment := ExperimentDetails{
Name: "Fake-Exp-Name", Name: "Fake-Exp-Name",
Namespace: "Fake NameSpace", Namespace: "Fake NameSpace",
@ -279,35 +245,12 @@ func TestExperimentJobCreate(t *testing.T) {
} }
tests := map[string]struct { tests := map[string]struct {
events v1.Event isErr bool
isErr bool
}{ }{
"Test Positive-1": { "Test Positive-1": {
isErr: false, isErr: false,
}, },
"Test Positive-2": { "Test Positive-2": {
events: v1.Event{
ObjectMeta: metav1.ObjectMeta{
Name: eventAtr.Name,
Namespace: engineDetails.EngineNamespace,
},
Source: v1.EventSource{
Component: engineDetails.Name + "-runner",
},
Message: eventAtr.Message,
Reason: eventAtr.Reason,
Type: eventAtr.Type,
Count: 1,
FirstTimestamp: metav1.Time{Time: time.Now()},
LastTimestamp: metav1.Time{Time: time.Now()},
InvolvedObject: v1.ObjectReference{
APIVersion: "litmuschaos.io/v1alpha1",
Kind: "ChaosEngine",
Name: engineDetails.Name,
Namespace: engineDetails.EngineNamespace,
UID: clientTypes.UID(engineDetails.UID),
},
},
isErr: true, isErr: true,
}, },
} }
@ -315,40 +258,29 @@ func TestExperimentJobCreate(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) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if mock.isErr { if !mock.isErr {
_, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(&mock.events) experiment.ExperimentJobCreate(engineDetails, client)
if err != nil {
t.Fatalf("fail to create event for %v test, err: %v", name, err)
}
} }
experiment.ExperimentJobCreate(engineDetails, client) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{})
if err != nil || len(events.Items) == 0 {
t.Fatalf("%v fail to get events, err: %v", name, err) t.Fatalf("%v fail to get events, err: %v", name, err)
} }
if mock.isErr {
if mock.isErr && !strings.Contains(events.Items[1].Message, "Experiment Job "+experiment.JobName+" for Chaos Experiment") { require.Equal(t, 0, len(events.Items))
t.Fatalf("%v failed to get the validate event message", name) return
} }
require.Equal(t, 1, len(events.Items))
require.Contains(t, events.Items[0].Message, "Experiment Job "+experiment.JobName+" for Chaos Experiment: "+experiment.Name)
}) })
} }
} }
func TestExperimentJobCleanUp(t *testing.T) { func TestExperimentJobCleanUp(t *testing.T) {
fakeJobCleanupPolicy := "delete"
engineDetails := EngineDetails{ engineDetails := EngineDetails{
Name: "Fake Engine", Name: "Fake Engine",
EngineNamespace: "Fake NameSpace", EngineNamespace: "Fake NameSpace",
UID: "", UID: "",
} }
eventAtr := EventAttributes{
Reason: "fake-reason",
Message: "fake-message",
Type: "fake-type",
Name: "fake-name",
}
experiment := ExperimentDetails{ experiment := ExperimentDetails{
Name: "Fake-Exp-Name", Name: "Fake-Exp-Name",
Namespace: "Fake NameSpace", Namespace: "Fake NameSpace",
@ -357,57 +289,30 @@ func TestExperimentJobCleanUp(t *testing.T) {
} }
tests := map[string]struct { tests := map[string]struct {
events v1.Event jobCleanupPolicy string
isErr bool
}{ }{
"Test Positive-1": { "Test Positive-1": {
isErr: false, jobCleanupPolicy: "delete",
}, },
"Test Positive-2": { "Test Positive-2": {
events: v1.Event{ jobCleanupPolicy: "retain",
ObjectMeta: metav1.ObjectMeta{
Name: eventAtr.Name,
Namespace: engineDetails.EngineNamespace,
},
Source: v1.EventSource{
Component: engineDetails.Name + "-runner",
},
Message: eventAtr.Message,
Reason: eventAtr.Reason,
Type: eventAtr.Type,
Count: 1,
FirstTimestamp: metav1.Time{Time: time.Now()},
LastTimestamp: metav1.Time{Time: time.Now()},
InvolvedObject: v1.ObjectReference{
APIVersion: "litmuschaos.io/v1alpha1",
Kind: "ChaosEngine",
Name: engineDetails.Name,
Namespace: engineDetails.EngineNamespace,
UID: clientTypes.UID(engineDetails.UID),
},
},
isErr: true,
}, },
} }
for name, mock := range tests { for name, mock := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if mock.isErr { experiment.ExperimentJobCleanUp(mock.jobCleanupPolicy, engineDetails, client)
_, err := client.KubeClient.CoreV1().Events(mock.events.Namespace).Create(&mock.events) events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
t.Fatalf("fail to create event for %v test, err: %v", name, err)
}
}
experiment.ExperimentJobCleanUp(fakeJobCleanupPolicy, engineDetails, client)
events, err := client.KubeClient.CoreV1().Events(engineDetails.EngineNamespace).List(metav1.ListOptions{})
if err != nil || len(events.Items) == 0 { if err != nil || len(events.Items) == 0 {
t.Fatalf("%v fail to get events, err: %v", name, err) t.Fatalf("%v fail to get events, err: %v", name, err)
} }
if mock.jobCleanupPolicy == "retain" {
if mock.isErr && !strings.Contains(events.Items[1].Message, "Experiment Job: "+experiment.JobName+" will be deleted") { require.Contains(t, events.Items[0].Message, "Experiment Job "+experiment.JobName+" will be retained")
t.Fatalf("%v failed to get the validate event message", name) return
}
if mock.jobCleanupPolicy == "delete" {
require.Contains(t, events.Items[0].Message, "Experiment Job: "+experiment.JobName+" will be deleted")
} }
}) })
} }

View File

@ -1,7 +1,8 @@
package utils package utils
import ( import (
litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "context"
litmuschaosv1alpha1 "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/pkg/errors" "github.com/pkg/errors"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -27,13 +28,13 @@ func (engineDetails *EngineDetails) NewExperimentDetails(i int) ExperimentDetail
experimentDetails.SvcAccount = engineDetails.SvcAccount experimentDetails.SvcAccount = engineDetails.SvcAccount
experimentDetails.Namespace = engineDetails.EngineNamespace experimentDetails.Namespace = engineDetails.EngineNamespace
// Setting the JobName in Experiment related struct // Setting the JobName in Experiment related struct
experimentDetails.JobName = experimentDetails.Name + "-" + RandomString() experimentDetails.JobName = experimentDetails.Name + "-" + RandomString(6)
return experimentDetails return experimentDetails
} }
// SetDefaultEnvFromChaosExperiment sets the Env's in Experiment Structure // SetDefaultEnvFromChaosExperiment sets the Env's in Experiment Structure
func (expDetails *ExperimentDetails) SetDefaultEnvFromChaosExperiment(clients ClientSets) error { func (expDetails *ExperimentDetails) SetDefaultEnvFromChaosExperiment(clients ClientSets) error {
experimentEnv, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) experimentEnv, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return errors.Errorf("unable to get the %v ChaosExperiment in %v namespace, error: %v", expDetails.Name, expDetails.Namespace, err) return errors.Errorf("unable to get the %v ChaosExperiment in %v namespace, error: %v", expDetails.Name, expDetails.Namespace, err)
} }
@ -61,7 +62,7 @@ func (expDetails *ExperimentDetails) SetValueFromChaosResources(engineDetails *E
// HandleChaosExperimentExistence will check the experiment in the app namespace // HandleChaosExperimentExistence will check the experiment in the app namespace
func (expDetails *ExperimentDetails) HandleChaosExperimentExistence(engineDetails EngineDetails, clients ClientSets) error { func (expDetails *ExperimentDetails) HandleChaosExperimentExistence(engineDetails EngineDetails, clients ClientSets) error {
_, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) _, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
if err := engineDetails.ExperimentNotFoundPatchEngine(expDetails, clients); err != nil { if err := engineDetails.ExperimentNotFoundPatchEngine(expDetails, clients); err != nil {
return errors.Errorf("unable to patch Chaos Engine Name: %v, namespace: %v, error: %v", engineDetails.Name, engineDetails.EngineNamespace, err) return errors.Errorf("unable to patch Chaos Engine Name: %v, namespace: %v, error: %v", engineDetails.Name, engineDetails.EngineNamespace, err)
@ -72,10 +73,10 @@ func (expDetails *ExperimentDetails) HandleChaosExperimentExistence(engineDetail
return nil return nil
} }
//SetDefaultAttributeValuesFromChaosExperiment sets value in experimentDetails struct from chaosExperiment // SetDefaultAttributeValuesFromChaosExperiment sets value in experimentDetails struct from chaosExperiment
func (expDetails *ExperimentDetails) SetDefaultAttributeValuesFromChaosExperiment(clients ClientSets, engine *EngineDetails) error { func (expDetails *ExperimentDetails) SetDefaultAttributeValuesFromChaosExperiment(clients ClientSets, engine *EngineDetails) error {
experimentSpec, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) experimentSpec, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return errors.Errorf("unable to get %v ChaosExperiment instance in namespace: %v", expDetails.Name, expDetails.Namespace) return errors.Errorf("unable to get %v ChaosExperiment instance in namespace: %v", expDetails.Name, expDetails.Namespace)
} }

View File

@ -1,10 +1,11 @@
package utils package utils
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -142,7 +143,7 @@ func TestSetDefaultEnvFromChaosExperiment(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
@ -257,7 +258,7 @@ func TestSetDefaultAttributeValuesFromChaosExperiment(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
@ -388,13 +389,13 @@ func TestSetValueFromChaosResources(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
if !mock.isErr { if !mock.isErr {
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -457,11 +458,11 @@ func TestSetLabels(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -510,11 +511,11 @@ func TestSetImage(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -564,11 +565,11 @@ func TestSetImagePullPolicy(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -619,11 +620,11 @@ func TestSetArgs(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -674,11 +675,11 @@ func TestSetCommand(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -731,11 +732,11 @@ func TestSetSecurityContext(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -784,11 +785,11 @@ func TestHostPID(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(mock.chaosexperiment.Name, metav1.GetOptions{}) experimentSpec, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Get(context.Background(), mock.chaosexperiment.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err) t.Fatalf("fail to get the chaosexperiment for %v test, err: %v", name, err)
} }
@ -869,12 +870,12 @@ func TestHandleChaosExperimentExistence(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if !mock.isErr { if !mock.isErr {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
} else { } else {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -888,7 +889,7 @@ func TestHandleChaosExperimentExistence(t *testing.T) {
} }
if mock.isErr { if mock.isErr {
chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Get(engineDetails.Name, metav1.GetOptions{}) chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Get(context.Background(), engineDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("%v test failed engine not found, err: %v", name, err) t.Fatalf("%v test failed engine not found, err: %v", name, err)
} }

View File

@ -1,10 +1,11 @@
package utils package utils
import ( import (
"context"
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
) )
@ -14,7 +15,7 @@ import (
//socket file mounts etc., and are often have fixed paths, i.e., similar to securityContext/hostPID //socket file mounts etc., and are often have fixed paths, i.e., similar to securityContext/hostPID
//and other such mandatory attributes //and other such mandatory attributes
//PatchHostFileVolumes patches hostFileVolume in experimentDetails struct. // PatchHostFileVolumes patches hostFileVolume in experimentDetails struct.
func (expDetails *ExperimentDetails) PatchHostFileVolumes(clients ClientSets, engineDetails EngineDetails) error { func (expDetails *ExperimentDetails) PatchHostFileVolumes(clients ClientSets, engineDetails EngineDetails) error {
err := expDetails.SetHostFileVolumes(clients, engineDetails) err := expDetails.SetHostFileVolumes(clients, engineDetails)
if err != nil { if err != nil {
@ -57,7 +58,7 @@ func (expDetails *ExperimentDetails) ValidateHostFileVolumes() error {
// getHostFileVolumesFromExperiment obtains the hostFileVolume details from experiment CR spec // getHostFileVolumesFromExperiment obtains the hostFileVolume details from experiment CR spec
func getHostFileVolumesFromExperiment(clients ClientSets, expDetails *ExperimentDetails) ([]v1alpha1.HostFile, error) { func getHostFileVolumesFromExperiment(clients ClientSets, expDetails *ExperimentDetails) ([]v1alpha1.HostFile, error) {
chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err) return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err)
} }

View File

@ -1,12 +1,13 @@
package utils package utils
import ( import (
"context"
"testing" "testing"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
) )
func TestPatchHostFileVolumes(t *testing.T) { func TestPatchHostFileVolumes(t *testing.T) {
@ -77,7 +78,7 @@ func TestPatchHostFileVolumes(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", err, name) t.Fatalf("experiment not created for %v test, err: %v", err, name)
} }

View File

@ -1,9 +1,11 @@
package utils package utils
import ( import (
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "context"
"github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// ExperimentStatus is wrapper for v1alpha1.ExperimentStatuses // ExperimentStatus is wrapper for v1alpha1.ExperimentStatuses
@ -24,7 +26,7 @@ func InitialPatchEngine(engineDetails EngineDetails, clients ClientSets, experim
expStatus.InitialExperimentStatus(v.Name, engineDetails.Name) expStatus.InitialExperimentStatus(v.Name, engineDetails.Name)
expEngine.Status.Experiments = append(expEngine.Status.Experiments, v1alpha1.ExperimentStatuses(expStatus)) expEngine.Status.Experiments = append(expEngine.Status.Experiments, v1alpha1.ExperimentStatuses(expStatus))
} }
_, updateErr := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Update(expEngine) _, updateErr := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Update(context.Background(), expEngine, metav1.UpdateOptions{})
if updateErr != nil { if updateErr != nil {
return errors.Errorf("unable to update ChaosEngine in namespace: %v, error: %v", engineDetails.EngineNamespace, updateErr) return errors.Errorf("unable to update ChaosEngine in namespace: %v, error: %v", engineDetails.EngineNamespace, updateErr)
} }

View File

@ -1,10 +1,11 @@
package utils package utils
import ( import (
"context"
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
) )
@ -26,7 +27,7 @@ func (expDetails *ExperimentDetails) PatchSecrets(clients ClientSets, engineDeta
// ValidatePresenceOfSecretResourceInCluster validates the secret in Chaos Namespace // ValidatePresenceOfSecretResourceInCluster validates the secret in Chaos Namespace
func (clientSets ClientSets) ValidatePresenceOfSecretResourceInCluster(secretName, namespace string) error { func (clientSets ClientSets) ValidatePresenceOfSecretResourceInCluster(secretName, namespace string) error {
_, err := clientSets.KubeClient.CoreV1().Secrets(namespace).Get(secretName, metav1.GetOptions{}) _, err := clientSets.KubeClient.CoreV1().Secrets(namespace).Get(context.Background(), secretName, metav1.GetOptions{})
return err return err
} }
@ -62,7 +63,7 @@ func (expDetails *ExperimentDetails) ValidateSecrets(clients ClientSets) error {
} }
func (expDetails *ExperimentDetails) getSecretsFromChaosExperiment(clients ClientSets) ([]v1alpha1.Secret, error) { func (expDetails *ExperimentDetails) getSecretsFromChaosExperiment(clients ClientSets) ([]v1alpha1.Secret, error) {
chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(expDetails.Name, metav1.GetOptions{}) chaosExperimentObj, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(expDetails.Namespace).Get(context.Background(), expDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err) return nil, errors.Errorf("unable to get ChaosExperiment Resource, error: %v", err)
} }

View File

@ -1,13 +1,14 @@
package utils package utils
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
) )
func TestPatchSecrets(t *testing.T) { func TestPatchSecrets(t *testing.T) {
@ -118,15 +119,15 @@ func TestPatchSecrets(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.KubeClient.CoreV1().Secrets(experiment.Namespace).Create(&mock.secret) _, err := client.KubeClient.CoreV1().Secrets(experiment.Namespace).Create(context.Background(), &mock.secret, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("secret not created for %v test, err: %v", name, err) t.Fatalf("secret not created for %v test, err: %v", name, err)
} }
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -238,13 +239,13 @@ func TestSetSecrets(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
if !mock.isErr { if !mock.isErr {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }
} }
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -347,7 +348,7 @@ func TestValidateSecrets(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.KubeClient.CoreV1().Secrets(fakeNamespace).Create(&mock.secret) _, err := client.KubeClient.CoreV1().Secrets(fakeNamespace).Create(context.Background(), &mock.secret, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("secret not created for %v test, err: %v", name, err) t.Fatalf("secret not created for %v test, err: %v", name, err)
} }
@ -415,7 +416,7 @@ func TestGetSecretsFromChaosExperiment(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(mock.chaosexperiment) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosExperiments(mock.chaosexperiment.Namespace).Create(context.Background(), mock.chaosexperiment, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("experiment not created for %v test, err: %v", name, err) t.Fatalf("experiment not created for %v test, err: %v", name, err)
} }

View File

@ -1,7 +1,7 @@
package utils package utils
import ( import (
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )

View File

@ -0,0 +1,2 @@
go test fuzz v1
[]byte("0")

View File

@ -0,0 +1,2 @@
go test fuzz v1
[]byte("0")

View File

@ -3,7 +3,7 @@ package utils
import ( import (
"flag" "flag"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
clientV1alpha1 "github.com/litmuschaos/chaos-operator/pkg/client/clientset/versioned" clientV1alpha1 "github.com/litmuschaos/chaos-operator/pkg/client/clientset/versioned"
volume "github.com/litmuschaos/elves/kubernetes/volume/v1alpha1" volume "github.com/litmuschaos/elves/kubernetes/volume/v1alpha1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -19,16 +19,12 @@ import (
type EngineDetails struct { type EngineDetails struct {
Name string Name string
Experiments []string Experiments []string
AppLabel string Targets string
AppNs string
SvcAccount string SvcAccount string
AppKind string
ClientUUID string ClientUUID string
AuxiliaryAppInfo string AuxiliaryAppInfo string
UID string UID string
EngineNamespace string EngineNamespace string
AnnotationKey string
AnnotationCheck string
} }
// ExperimentDetails is for collecting all the experiment-related details // ExperimentDetails is for collecting all the experiment-related details
@ -59,10 +55,19 @@ type ExperimentDetails struct {
ImagePullSecrets []v1.LocalObjectReference ImagePullSecrets []v1.LocalObjectReference
StatusCheckTimeout int StatusCheckTimeout int
TerminationGracePeriodSeconds int64 TerminationGracePeriodSeconds int64
DefaultAppHealthCheck string DefaultHealthCheck string
SideCars []SideCar
} }
//VolumeOpts is a strcuture for all volume related operations type SideCar struct {
ENV []v1.EnvVar
Image string
ImagePullPolicy v1.PullPolicy
Secrets []v1alpha1.Secret
EnvFrom []v1.EnvFromSource
}
// VolumeOpts is a strcuture for all volume related operations
type VolumeOpts struct { type VolumeOpts struct {
VolumeMounts []v1.VolumeMount VolumeMounts []v1.VolumeMount
VolumeBuilders []*volume.Builder VolumeBuilders []*volume.Builder
@ -106,6 +111,8 @@ const (
ExperimentChaosContainerWatchErrorReason string = "ChaosContainerWatchNotPermitted" ExperimentChaosContainerWatchErrorReason string = "ChaosContainerWatchNotPermitted"
// ChaosResourceNotFoundReason contains the reason for the chaos-resources-not-found event // ChaosResourceNotFoundReason contains the reason for the chaos-resources-not-found event
ChaosResourceNotFoundReason string = "ChaosResourceNotFound" ChaosResourceNotFoundReason string = "ChaosResourceNotFound"
// ExperimentSideCarPatchErrorReason contains the reason for the side-car-patch-error event
ExperimentSideCarPatchErrorReason string = "SideCarPatchError"
) )
// GenerateClientSetFromKubeConfig will generation both ClientSets (k8s, and Litmus) // GenerateClientSetFromKubeConfig will generation both ClientSets (k8s, and Litmus)

View File

@ -1,7 +1,7 @@
package utils package utils
import ( import (
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
volume "github.com/litmuschaos/elves/kubernetes/volume/v1alpha1" volume "github.com/litmuschaos/elves/kubernetes/volume/v1alpha1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )

View File

@ -1,6 +1,8 @@
package utils package utils
import ( import (
"context"
"strings"
"time" "time"
"github.com/litmuschaos/litmus-go/pkg/utils/retry" "github.com/litmuschaos/litmus-go/pkg/utils/retry"
@ -19,7 +21,7 @@ func GetChaosPod(expDetails *ExperimentDetails, clients ClientSets) (*corev1.Pod
Times(uint(expDetails.StatusCheckTimeout / delay)). Times(uint(expDetails.StatusCheckTimeout / delay)).
Wait(time.Duration(delay) * time.Second). Wait(time.Duration(delay) * time.Second).
Try(func(attempt uint) error { Try(func(attempt uint) error {
chaosPodList, err = clients.KubeClient.CoreV1().Pods(expDetails.Namespace).List(metav1.ListOptions{LabelSelector: "job-name=" + expDetails.JobName}) chaosPodList, err = clients.KubeClient.CoreV1().Pods(expDetails.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "job-name=" + expDetails.JobName})
if err != nil || len(chaosPodList.Items) == 0 { if err != nil || len(chaosPodList.Items) == 0 {
return errors.Errorf("unable to get the chaos pod, error: %v", err) return errors.Errorf("unable to get the chaos pod, error: %v", err)
} else if len(chaosPodList.Items) > 1 { } else if len(chaosPodList.Items) > 1 {
@ -48,20 +50,21 @@ func GetChaosContainerStatus(experimentDetails *ExperimentDetails, clients Clien
if err != nil { if err != nil {
return false, errors.Errorf("unable to get the chaos pod, error: %v", err) return false, errors.Errorf("unable to get the chaos pod, error: %v", err)
} }
if pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded { if pod.Status.Phase == corev1.PodSucceeded {
return true, nil
}
if pod.Status.Phase == corev1.PodRunning {
for _, container := range pod.Status.ContainerStatuses { for _, container := range pod.Status.ContainerStatuses {
//NOTE: The name of container inside chaos-pod is same as the chaos job name //NOTE: The name of container inside chaos-pod is same as the chaos job name
// we only have one container inside chaos pod to inject the chaos // we only have one container inside chaos pod to inject the chaos
// looking the chaos container is completed or not // looking the chaos container is completed or not
if container.Name == experimentDetails.JobName && container.State.Terminated != nil { if strings.Contains(container.Name, experimentDetails.JobName) && container.State.Terminated == nil {
if container.State.Terminated.Reason == "Completed" { return false, nil
isCompleted = !container.Ready
}
} }
} }
return true, nil
} else if pod.Status.Phase == corev1.PodPending { } else if pod.Status.Phase == corev1.PodPending {
delay := 2 delay := 2
err := retry. err := retry.
@ -100,6 +103,10 @@ func (engineDetails EngineDetails) WatchChaosContainerForCompletion(experiment *
return err return err
} }
if isChaosCompleted {
return nil
}
var expStatus ExperimentStatus var expStatus ExperimentStatus
chaosPod, err := GetChaosPod(experiment, clients) chaosPod, err := GetChaosPod(experiment, clients)
if err != nil { if err != nil {

View File

@ -1,9 +1,10 @@
package utils package utils
import ( import (
"context"
"testing" "testing"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -125,12 +126,12 @@ func TestGetChaosPod(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.KubeClient.CoreV1().Pods(experiment.Namespace).Create(&mock.chaospod) _, err := client.KubeClient.CoreV1().Pods(experiment.Namespace).Create(context.Background(), &mock.chaospod, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err) t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err)
} }
if mock.isSecondTest { if mock.isSecondTest {
_, err = client.KubeClient.CoreV1().Pods(experiment.Namespace).Create(&mock.chaospod2) _, err = client.KubeClient.CoreV1().Pods(experiment.Namespace).Create(context.Background(), &mock.chaospod2, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create chaos pod 2 for %v test, err: %v", name, err) t.Fatalf("fail to create chaos pod 2 for %v test, err: %v", name, err)
} }
@ -248,7 +249,7 @@ func TestGetChaosContainerStatus(t *testing.T) {
} else { } else {
ns = "wrong-ns" ns = "wrong-ns"
} }
_, err := client.KubeClient.CoreV1().Pods(ns).Create(&mock.chaospod) _, err := client.KubeClient.CoreV1().Pods(ns).Create(context.Background(), &mock.chaospod, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err) t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err)
} }
@ -390,12 +391,12 @@ func TestWatchChaosContainerForCompletion(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(fakeNamespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(fakeNamespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
_, err = client.KubeClient.CoreV1().Pods(fakeNamespace).Create(&mock.chaospod) _, err = client.KubeClient.CoreV1().Pods(fakeNamespace).Create(context.Background(), &mock.chaospod, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err) t.Fatalf("fail to create chaos pod for %v test, err: %v", name, err)
} }

View File

@ -1,15 +1,20 @@
package utils package utils
import ( import (
"context"
"fmt" "fmt"
"time"
"github.com/pkg/errors" "github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/litmuschaos/litmus-go/pkg/utils/retry"
) )
var err error
// checkStatusListForExp loops over all the status patched in chaosEngine, to get the one, which has to be updated // checkStatusListForExp loops over all the status patched in chaosEngine, to get the one, which has to be updated
// Can go with updated the last status(status[n-1]) // Can go with updated the last status(status[n-1])
// But would'nt work for the parallel execution // But would'nt work for the parallel execution
@ -24,12 +29,20 @@ func checkStatusListForExp(status []v1alpha1.ExperimentStatuses, ExperimentName
// GetChaosEngine returns chaosEngine Object // GetChaosEngine returns chaosEngine Object
func (engineDetails EngineDetails) GetChaosEngine(clients ClientSets) (*v1alpha1.ChaosEngine, error) { func (engineDetails EngineDetails) GetChaosEngine(clients ClientSets) (*v1alpha1.ChaosEngine, error) {
expEngine, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Get(engineDetails.Name, metav1.GetOptions{}) var engine *v1alpha1.ChaosEngine
if err != nil { if err := retry.
Times(uint(180)).
return nil, errors.Errorf("unable to get ChaosEngine name: %v, in namespace: %v, error: %v", engineDetails.Name, engineDetails.EngineNamespace, err) Wait(time.Duration(2)).
Try(func(attempt uint) error {
engine, err = clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Get(context.Background(), engineDetails.Name, metav1.GetOptions{})
if err != nil {
return errors.Errorf("unable to get ChaosEngine name: %v, in namespace: %v, error: %v", engineDetails.Name, engineDetails.EngineNamespace, err)
}
return nil
}); err != nil {
return nil, err
} }
return expEngine, nil return engine, nil
} }
// PatchChaosEngineStatus updates ChaosEngine with Experiment Status // PatchChaosEngineStatus updates ChaosEngine with Experiment Status
@ -44,7 +57,7 @@ func (expStatus *ExperimentStatus) PatchChaosEngineStatus(engineDetails EngineDe
return errors.Errorf("unable to find the status for Experiment: %v in ChaosEngine: %v", expStatus.Name, expEngine.Name) return errors.Errorf("unable to find the status for Experiment: %v in ChaosEngine: %v", expStatus.Name, expEngine.Name)
} }
expEngine.Status.Experiments[experimentIndex] = v1alpha1.ExperimentStatuses(*expStatus) expEngine.Status.Experiments[experimentIndex] = v1alpha1.ExperimentStatuses(*expStatus)
if _, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Update(expEngine); err != nil { if _, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engineDetails.EngineNamespace).Update(context.Background(), expEngine, metav1.UpdateOptions{}); err != nil {
return err return err
} }
return nil return nil
@ -64,7 +77,7 @@ func GetResultName(engineName, experimentName, instanceID string) string {
func (expDetails *ExperimentDetails) GetChaosResult(engineDetails EngineDetails, clients ClientSets) (*v1alpha1.ChaosResult, error) { func (expDetails *ExperimentDetails) GetChaosResult(engineDetails EngineDetails, clients ClientSets) (*v1alpha1.ChaosResult, error) {
resultName := GetResultName(engineDetails.Name, expDetails.Name, expDetails.InstanceID) resultName := GetResultName(engineDetails.Name, expDetails.Name, expDetails.InstanceID)
expResult, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosResults(engineDetails.EngineNamespace).Get(resultName, metav1.GetOptions{}) expResult, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosResults(engineDetails.EngineNamespace).Get(context.Background(), resultName, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, errors.Errorf("unable to get ChaosResult name: %v in namespace: %v, error: %v", resultName, engineDetails.EngineNamespace, err) return nil, errors.Errorf("unable to get ChaosResult name: %v in namespace: %v, error: %v", resultName, engineDetails.EngineNamespace, err)
} }
@ -105,7 +118,7 @@ func (engineDetails EngineDetails) DeleteJobAccordingToJobCleanUpPolicy(experime
case v1alpha1.CleanUpPolicyDelete: case v1alpha1.CleanUpPolicyDelete:
log.Infof("deleting the job as jobCleanPolicy is set to %s", expEngine.Spec.JobCleanUpPolicy) log.Infof("deleting the job as jobCleanPolicy is set to %s", expEngine.Spec.JobCleanUpPolicy)
deletePolicy := metav1.DeletePropagationForeground deletePolicy := metav1.DeletePropagationForeground
if deleteJobErr := clients.KubeClient.BatchV1().Jobs(experiment.Namespace).Delete(experiment.JobName, &metav1.DeleteOptions{ if deleteJobErr := clients.KubeClient.BatchV1().Jobs(experiment.Namespace).Delete(context.Background(), experiment.JobName, metav1.DeleteOptions{
PropagationPolicy: &deletePolicy, PropagationPolicy: &deletePolicy,
}); deleteJobErr != nil { }); deleteJobErr != nil {
return "", errors.Errorf("unable to delete ChaosExperiment Job name: %v, in namespace: %v, error: %v", experiment.JobName, experiment.Namespace, deleteJobErr) return "", errors.Errorf("unable to delete ChaosExperiment Job name: %v, in namespace: %v, error: %v", experiment.JobName, experiment.Namespace, deleteJobErr)

View File

@ -1,6 +1,7 @@
package utils package utils
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
@ -10,7 +11,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
litmusFakeClientset "github.com/litmuschaos/chaos-operator/pkg/client/clientset/versioned/fake" litmusFakeClientset "github.com/litmuschaos/chaos-operator/pkg/client/clientset/versioned/fake"
) )
@ -18,7 +19,6 @@ func TestPatchChaosEngineStatus(t *testing.T) {
fakeServiceAcc := "Fake Service Account" fakeServiceAcc := "Fake Service Account"
fakeAppLabel := "Fake Label" fakeAppLabel := "Fake Label"
fakeAppKind := "Fake Kind" fakeAppKind := "Fake Kind"
fakeAnnotationCheck := "Fake Annotation Check"
expStatus := ExperimentStatus{ expStatus := ExperimentStatus{
Name: "Fake exp Name", Name: "Fake exp Name",
Status: v1alpha1.ExperimentStatusRunning, Status: v1alpha1.ExperimentStatusRunning,
@ -40,10 +40,9 @@ func TestPatchChaosEngineStatus(t *testing.T) {
}, },
Spec: v1alpha1.ChaosEngineSpec{ Spec: v1alpha1.ChaosEngineSpec{
ChaosServiceAccount: fakeServiceAcc, ChaosServiceAccount: fakeServiceAcc,
AnnotationCheck: fakeAnnotationCheck,
Appinfo: v1alpha1.ApplicationParams{ Appinfo: v1alpha1.ApplicationParams{
Applabel: fakeAppLabel,
Appns: engineDetails.EngineNamespace, Appns: engineDetails.EngineNamespace,
Applabel: fakeAppLabel,
AppKind: fakeAppKind, AppKind: fakeAppKind,
}, },
}, },
@ -66,10 +65,9 @@ func TestPatchChaosEngineStatus(t *testing.T) {
}, },
Spec: v1alpha1.ChaosEngineSpec{ Spec: v1alpha1.ChaosEngineSpec{
ChaosServiceAccount: fakeServiceAcc, ChaosServiceAccount: fakeServiceAcc,
AnnotationCheck: fakeAnnotationCheck,
Appinfo: v1alpha1.ApplicationParams{ Appinfo: v1alpha1.ApplicationParams{
Applabel: fakeAppLabel,
Appns: engineDetails.EngineNamespace, Appns: engineDetails.EngineNamespace,
Applabel: fakeAppLabel,
AppKind: fakeAppKind, AppKind: fakeAppKind,
}, },
}, },
@ -85,7 +83,7 @@ func TestPatchChaosEngineStatus(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
@ -98,7 +96,7 @@ func TestPatchChaosEngineStatus(t *testing.T) {
t.Fatalf("Test %q failed: expected error not to be nil", name) t.Fatalf("Test %q failed: expected error not to be nil", name)
} }
chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Get(engineDetails.Name, metav1.GetOptions{}) chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Get(context.Background(), engineDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get chaos engine after status patch, err: %v", err) t.Fatalf("fail to get chaos engine after status patch, err: %v", err)
} }
@ -122,7 +120,6 @@ func TestUpdateEngineWithResult(t *testing.T) {
fakeServiceAcc := "Fake Service Account" fakeServiceAcc := "Fake Service Account"
fakeAppLabel := "Fake Label" fakeAppLabel := "Fake Label"
fakeAppKind := "Fake Kind" fakeAppKind := "Fake Kind"
fakeAnnotationCheck := "Fake Annotation Check"
expStatus := ExperimentStatus{ expStatus := ExperimentStatus{
Name: "Fake-Exp-Name", Name: "Fake-Exp-Name",
Status: v1alpha1.ExperimentStatusRunning, Status: v1alpha1.ExperimentStatusRunning,
@ -152,10 +149,9 @@ func TestUpdateEngineWithResult(t *testing.T) {
}, },
Spec: v1alpha1.ChaosEngineSpec{ Spec: v1alpha1.ChaosEngineSpec{
ChaosServiceAccount: fakeServiceAcc, ChaosServiceAccount: fakeServiceAcc,
AnnotationCheck: fakeAnnotationCheck,
Appinfo: v1alpha1.ApplicationParams{ Appinfo: v1alpha1.ApplicationParams{
Applabel: fakeAppLabel,
Appns: engineDetails.EngineNamespace, Appns: engineDetails.EngineNamespace,
Applabel: fakeAppLabel,
AppKind: fakeAppKind, AppKind: fakeAppKind,
}, },
JobCleanUpPolicy: "retain", JobCleanUpPolicy: "retain",
@ -205,10 +201,9 @@ func TestUpdateEngineWithResult(t *testing.T) {
}, },
Spec: v1alpha1.ChaosEngineSpec{ Spec: v1alpha1.ChaosEngineSpec{
ChaosServiceAccount: fakeServiceAcc, ChaosServiceAccount: fakeServiceAcc,
AnnotationCheck: fakeAnnotationCheck,
Appinfo: v1alpha1.ApplicationParams{ Appinfo: v1alpha1.ApplicationParams{
Applabel: fakeAppLabel,
Appns: engineDetails.EngineNamespace, Appns: engineDetails.EngineNamespace,
Applabel: fakeAppLabel,
AppKind: fakeAppKind, AppKind: fakeAppKind,
}, },
JobCleanUpPolicy: "retain", JobCleanUpPolicy: "retain",
@ -250,15 +245,15 @@ func TestUpdateEngineWithResult(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
_, err = client.KubeClient.CoreV1().Pods(engineDetails.EngineNamespace).Create(&mock.chaospod) _, err = client.KubeClient.CoreV1().Pods(engineDetails.EngineNamespace).Create(context.Background(), &mock.chaospod, metav1.CreateOptions{})
if err != nil { if err != nil {
fmt.Printf("fail to create chaos pod for %v test, err: %v", name, err) fmt.Printf("fail to create chaos pod for %v test, err: %v", name, err)
} }
_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosResults(mock.chaosresult.Namespace).Create(mock.chaosresult) _, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosResults(mock.chaosresult.Namespace).Create(context.Background(), mock.chaosresult, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("chaosresult not created for %v test, err: %v", name, err) t.Fatalf("chaosresult not created for %v test, err: %v", name, err)
} }
@ -269,7 +264,7 @@ func TestUpdateEngineWithResult(t *testing.T) {
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)
} }
chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Get(engineDetails.Name, metav1.GetOptions{}) chaosEngine, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Get(context.Background(), engineDetails.Name, metav1.GetOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to get chaosengine after status patch for %v test, err: %v", name, err) t.Fatalf("fail to get chaosengine after status patch for %v test, err: %v", name, err)
} }
@ -386,11 +381,11 @@ func TestDeleteJobAccordingToJobCleanUpPolicy(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t) client := CreateFakeClient(t)
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(mock.chaosengine) _, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(mock.chaosengine.Namespace).Create(context.Background(), mock.chaosengine, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("engine not created for %v test, err: %v", name, err) t.Fatalf("engine not created for %v test, err: %v", name, err)
} }
_, err = client.KubeClient.BatchV1().Jobs(engineDetails.EngineNamespace).Create(&mock.expjob) _, err = client.KubeClient.BatchV1().Jobs(engineDetails.EngineNamespace).Create(context.Background(), &mock.expjob, metav1.CreateOptions{})
if err != nil { if err != nil {
t.Fatalf("fail to create exp job pod for %v test, err: %v", name, err) t.Fatalf("fail to create exp job pod for %v test, err: %v", name, err)
} }
@ -399,7 +394,7 @@ func TestDeleteJobAccordingToJobCleanUpPolicy(t *testing.T) {
t.Fatalf("fail to create exp job for %v test, err: %v", name, err) t.Fatalf("fail to create exp job for %v test, err: %v", name, err)
} }
jobList, err := client.KubeClient.BatchV1().Jobs(engineDetails.EngineNamespace).List(metav1.ListOptions{LabelSelector: "job-name=" + experiment.JobName}) jobList, err := client.KubeClient.BatchV1().Jobs(engineDetails.EngineNamespace).List(context.Background(), metav1.ListOptions{LabelSelector: "job-name=" + experiment.JobName})
if !mock.isErr && err != nil && len(jobList.Items) != 0 { if !mock.isErr && err != nil && len(jobList.Items) != 0 {
t.Fatalf("[%v] test failed experiment job is not deleted when the job cleanup policy is %v , err: %v", name, err, cleanupPolicy) t.Fatalf("[%v] test failed experiment job is not deleted when the job cleanup policy is %v , err: %v", name, err, cleanupPolicy)
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
*/ */
import ( import (
"context"
"flag" "flag"
"fmt" "fmt"
"os" "os"
@ -25,7 +26,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/litmuschaos/chaos-operator/pkg/apis/litmuschaos/v1alpha1" "github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
"github.com/litmuschaos/chaos-runner/pkg/log" "github.com/litmuschaos/chaos-runner/pkg/log"
"github.com/litmuschaos/chaos-runner/pkg/utils" "github.com/litmuschaos/chaos-runner/pkg/utils"
"github.com/litmuschaos/chaos-runner/pkg/utils/k8s" "github.com/litmuschaos/chaos-runner/pkg/utils/k8s"
@ -37,7 +38,8 @@ import (
appv1 "k8s.io/api/apps/v1" appv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )
@ -95,7 +97,7 @@ var _ = BeforeSuite(func() {
Times(uint(180 / 2)). Times(uint(180 / 2)).
Wait(time.Duration(2) * time.Second). Wait(time.Duration(2) * time.Second).
Try(func(attempt uint) error { Try(func(attempt uint) error {
podSpec, err := clients.KubeClient.CoreV1().Pods("litmus").List(metav1.ListOptions{LabelSelector: "name=chaos-operator"}) podSpec, err := clients.KubeClient.CoreV1().Pods("litmus").List(context.Background(), metav1.ListOptions{LabelSelector: "name=chaos-operator"})
if err != nil || len(podSpec.Items) == 0 { if err != nil || len(podSpec.Items) == 0 {
return errors.Errorf("Unable to list chaos-operator, err: %v", err) return errors.Errorf("Unable to list chaos-operator, err: %v", err)
} }
@ -111,7 +113,7 @@ var _ = BeforeSuite(func() {
log.Info("Chaos-Operator is in running state") log.Info("Chaos-Operator is in running state")
By("Installing Pod Delete Experiment") By("Installing Pod Delete Experiment")
err = exec.Command("kubectl", "apply", "-f", "https://hub.litmuschaos.io/api/chaos/master?file=charts/generic/pod-delete/experiment.yaml", "-n", "litmus").Run() err = exec.Command("kubectl", "apply", "-f", "https://hub.litmuschaos.io/api/chaos/master?file=faults/kubernetes/pod-delete/fault.yaml", "-n", "litmus").Run()
Expect(err).To(BeNil(), "unable to create Pod-Delete Experiment") Expect(err).To(BeNil(), "unable to create Pod-Delete Experiment")
log.Info("pod-delete ChaosExperiment created") log.Info("pod-delete ChaosExperiment created")
@ -120,7 +122,7 @@ var _ = BeforeSuite(func() {
log.Info("pod-delete-sa created") log.Info("pod-delete-sa created")
}) })
//BDD Tests to check secondary resources // BDD Tests to check secondary resources
var _ = Describe("BDD on chaos-runner", func() { var _ = Describe("BDD on chaos-runner", func() {
// BDD TEST CASE 1 // BDD TEST CASE 1
@ -169,7 +171,7 @@ var _ = Describe("BDD on chaos-runner", func() {
}, },
} }
By("Creating nginx deployment") By("Creating nginx deployment")
_, err := clients.KubeClient.AppsV1().Deployments("litmus").Create(deployment) _, err := clients.KubeClient.AppsV1().Deployments("litmus").Create(context.Background(), deployment, metav1.CreateOptions{})
Expect(err).To( Expect(err).To(
BeNil(), BeNil(),
"while creating nginx deployment in namespace litmus", "while creating nginx deployment in namespace litmus",
@ -204,16 +206,14 @@ var _ = Describe("BDD on chaos-runner", func() {
Experiments: []v1alpha1.ExperimentList{ Experiments: []v1alpha1.ExperimentList{
{ {
Name: "pod-delete", Name: "pod-delete",
Spec: v1alpha1.ExperimentAttributes{ Spec: v1alpha1.ExperimentAttributes{},
Rank: uint32(1),
},
}, },
}, },
}, },
} }
By("Creating ChaosEngine Resource") By("Creating ChaosEngine Resource")
_, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines("litmus").Create(chaosEngine) _, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines("litmus").Create(context.Background(), chaosEngine, metav1.CreateOptions{})
Expect(err).To( Expect(err).To(
BeNil(), BeNil(),
"while building ChaosEngine engine-nginx in namespace litmus", "while building ChaosEngine engine-nginx in namespace litmus",
@ -224,7 +224,7 @@ var _ = Describe("BDD on chaos-runner", func() {
Times(uint(180 / 2)). Times(uint(180 / 2)).
Wait(time.Duration(2) * time.Second). Wait(time.Duration(2) * time.Second).
Try(func(attempt uint) error { Try(func(attempt uint) error {
pod, err := clients.KubeClient.CoreV1().Pods("litmus").Get("engine-nginx-runner", metav1.GetOptions{}) pod, err := clients.KubeClient.CoreV1().Pods("litmus").Get(context.Background(), "engine-nginx-runner", metav1.GetOptions{})
if err != nil { if err != nil {
return errors.Errorf("unable to get chaos-runner pod, err: %v", err) return errors.Errorf("unable to get chaos-runner pod, err: %v", err)
} }
@ -249,7 +249,7 @@ var _ = Describe("BDD on chaos-runner", func() {
Wait(time.Duration(2) * time.Second). Wait(time.Duration(2) * time.Second).
Try(func(attempt uint) error { Try(func(attempt uint) error {
var jobName string var jobName string
jobs, err := clients.KubeClient.BatchV1().Jobs("litmus").List(metav1.ListOptions{}) jobs, err := clients.KubeClient.BatchV1().Jobs("litmus").List(context.Background(), metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
@ -279,7 +279,7 @@ var _ = Describe("BDD on chaos-runner", func() {
}) })
//Deleting all unused resources // Deleting all unused resources
var _ = AfterSuite(func() { var _ = AfterSuite(func() {
By("Deleting chaosengine CRD") By("Deleting chaosengine CRD")