Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Update to REST functionality #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Monkey-Ops is prepared to running into a docker image. Monkey-Ops also includes
Monkey-Ops has two different modes of execution: background or rest.

* **Background**: With the Background mode, the service is running nonstop until you stop the container.
* **Rest**: With the Rest mode, you consume an api rest that allows you login in Openshift, choose a project, and execute the chaos for a certain time.
* **Rest**: With the Rest mode, you consume an api rest that allows you login in Openshift, choose a project, and execute the chaos for a certain time. In addition, it will allow you to specify pod names that you want to attack, as well as the option to scale or not your deployments.

The service accept parameters as flags or environment variables. These are the input flags required:

Expand All @@ -29,6 +29,7 @@ The service accept parameters as flags or environment variables. These are the i
--MODE string Execution mode: background or rest (by default "background")
--PROJECT_NAME string Project to get crazy
--TOKEN string Bearer token with edit grants to access to the Openshift project
--NAMES string Name of the pods you want to attack

### Usage with Docker

Expand Down Expand Up @@ -127,3 +128,6 @@ Monkey-Ops Api Rest expose two endpoints:
> "totalTime": Total Time of monkey-ops execution in seconds
> }

### Using in Jenkins

This code has also been extended to easily integrate in Jenkins. After creating a docker image from the Dockefile here (and modifying your yml to represent your images and project name), you can reference the added jenkinsfile to see how it can be intgrated.
52 changes: 46 additions & 6 deletions go/chaos.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

//Get all the pods running from a project
func GetPods(token string, project string, url string) []string {
func GetPods(token string, project string, url string, names string) []string {

urlGetPods := url + "/api/v1/namespaces/" + project + "/pods"

Expand Down Expand Up @@ -53,21 +53,60 @@ func GetPods(token string, project string, url string) []string {
podsCustom := map[string]interface{}{}
json.Unmarshal(pods, &podsCustom)

if podsCustom != nil && len(podsCustom)> 0 {
//Create Names Variables
targetNames := strings.Split(names, ", ")

//Case to run against all pods
if podsCustom != nil && len(podsCustom)> 0 && string(targetNames[0]) == "names" {
items := podsCustom["items"].([]interface{})

for _, item := range items {
itemObject := item.(map[string]interface{})
metadataMap := itemObject["metadata"].(map[string]interface{})
statusMap := itemObject["status"].(map[string]interface{})
status := statusMap["phase"].(string)

if status == "Running" {
podsName = append(podsName, metadataMap["name"].(string))
log.Println("Adding pod")
podsName = append(podsName, metadataMap["name"].(string))
log.Println(podsName)
}

return podsName
}
}

//Run Ordered Chaos against Specific Pods
if podsCustom != nil && len(podsCustom)> 0 {
items := podsCustom["items"].([]interface{})

for _, item := range items {
itemObject := item.(map[string]interface{})
metadataMap := itemObject["metadata"].(map[string]interface{})
statusMap := itemObject["status"].(map[string]interface{})
status := statusMap["phase"].(string)
appName := metadataMap["name"]

// If there was no passed, run "ordered" Chaos against listed pods
// No in-built Golang function to compare arrays, have to iterate over
// Iterate over []strings (ie targetNames), because it is not legal argument in strings.Contains
for _, name := range targetNames {
log.Println(name)
log.Println(appName)
if strings.Contains(metadataMap["name"].(string), name) {
if status == "Running" {
log.Println("Adding ", appName)
podsName = append(podsName, metadataMap["name"].(string))
log.Println(podsName)
} else {
log.Println("Pod already stopping")
}
} else {
log.Println("Skipping pod ", appName)
}
}
}
}
log.Println("Pod List: ", podsName)
return podsName
}

Expand Down Expand Up @@ -219,11 +258,12 @@ func ExecuteChaos(chaosInput *ChaosInput, mode string) {
for doChaos := (mode == "background" || (time.Since(start).Seconds() < chaosInput.TotalTime)); doChaos; doChaos = (mode == "background" || (time.Since(start).Seconds() < chaosInput.TotalTime)) {

//Randomly choice if delete pod or scale a DC
randComponent := random(1, 3)
// Changing to only delete pods
randComponent := random(1, 2)

switch randComponent {
case 1:
pods := GetPods(chaosInput.Token, chaosInput.Project, chaosInput.Url)
pods := GetPods(chaosInput.Token, chaosInput.Project, chaosInput.Url, chaosInput.Names)
if pods != nil && len(pods) > 0 {
randPod := random(0, len(pods))
log.Println(pods[randPod])
Expand Down
5 changes: 5 additions & 0 deletions go/monkey-ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ func main() {
flag.String("TOKEN", "", "Bearer token with edit grants to access to the Openshift project")
flag.Float64("INTERVAL", 30, "interval time in seconds")
flag.String("MODE", "background", "Execution mode: background or rest")
flag.String("NAMES", "", "Names to hit with Chaos")

//Binding flags and env vars
viper.BindPFlag("API_SERVER", flag.Lookup("API_SERVER"))
viper.BindPFlag("PROJECT_NAME", flag.Lookup("PROJECT_NAME"))
viper.BindPFlag("TOKEN", flag.Lookup("TOKEN"))
viper.BindPFlag("INTERVAL", flag.Lookup("INTERVAL"))
viper.BindPFlag("MODE", flag.Lookup("MODE"))
viper.BindPFlag("NAMES", flag.Lookup("NAMES"))

viper.BindEnv("KUBERNETES_SERVICE_HOST")
viper.BindEnv("KUBERNETES_SERVICE_PORT")
Expand All @@ -31,6 +33,7 @@ func main() {
viper.BindEnv("TOKEN")
viper.BindEnv("INTERVAL")
viper.BindEnv("MODE")
viper.BindEnv("NAMES")

flag.Parse()

Expand All @@ -46,6 +49,7 @@ func main() {
token := viper.GetString("TOKEN")
interval := viper.GetFloat64("INTERVAL")
mode := viper.GetString("MODE")
names := viper.GetString("NAMES")

if mode == "background" {
// read the service account secret token file at once
Expand All @@ -67,6 +71,7 @@ func main() {
Token: token,
Interval: interval,
TotalTime: 0,
Names: names,
}

//Launh the chaos
Expand Down
2 changes: 2 additions & 0 deletions go/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ type LoginInput struct {
Url string `json:"url"`
}

//The third field sets a default value
type ChaosInput struct {
Url string `json:"url"`
Project string `json:"project"`
Token string `json:"token"`
Interval float64 `json:"interval"`
TotalTime float64 `json:"totalTime"`
Names string `json:"names"`
}

type ChaosOutput struct {
Expand Down
69 changes: 69 additions & 0 deletions jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!groovy
pipeline {

agent {
label 'docker-maven-slave'
}
triggers {
githubPush()
}
parameters {
string(name: 'names', defaultValue: 'ratings', description: 'The names of the pods we want to hit with Chaos', trim: true)
string(name: 'interval', defaultValue: '10', description: 'The time (in seconds) we want to have between each Chaos attack', trim: true)
string(name: 'totalTime', defaultValue: '300', description: 'The duration (in seconds) we want chaos', trim: true)
string(name: 'openshift_url', defaultValue: '', trim: true)
choice(name: 'scaling', choices: ['noscaling', 'scaling'], description: 'Whether or not to scale application')
string(name: 'tokenId', description: 'Your monkey-ops security token', trim: true)
string(name: 'endpoint', description: 'Your monkey-ops route', trim: true)
string(name: 'msid', description: 'Your msib', trim: true)
}

// Trying environment variables
environment {
token = credentials("${tokenId}")
BUILD_VERSION = "$currentBuild.number"
BRANCH = "$BRANCH_NAME"
monkey_url = 'your-base-url'
projectBAK = 'chaos-demo'


OCP_PROJECT = 'chaos-demo'
}
// Trying options
options {
buildDiscarder(logRotator(numToKeepStr: '5'))
}
// Trying stages
stages {
stage('Calculate Default settings') {
steps {
echo "params = $params"
// calculate variables (based on msid)
script {
project = "otu-$msid" // Can be changed to specify your own project
jmeterJob = "otu-$msid-jmeter"
}
}
}
stage('Run Chaos Global Library') {

// Hard coded Chaos tests
//stage ('Chaos Tests') {
steps {

sh """
curl -X POST \
-H 'Content-Type: application/json' \
-d '{"token":"${token}","url":"${openshift_url}","project":"${project}","interval":'${interval}',"totalTime":'${totalTime}',"names":"${names}","scaling":"${scaling}"}' \\
${endpoint}/chaos
"""
}
}

stage('Starting Jmeter Job') {
steps {
build job: "${jmeterJob}"
}
}
}
}
23 changes: 18 additions & 5 deletions openshift/monkey-ops-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ metadata:
tags: instant-app,agent
name: monkey-ops
objects:
- apiVersion: v1
kind: Service
metadata:
name: ${APP_NAME}
labels:
app_name: ${APP_NAME}
spec:
selector:
app_name: ${APP_NAME}
type: ClusterIP
ports:
- name: web
port: 8080
- apiVersion: v1
kind: DeploymentConfig
metadata:
Expand Down Expand Up @@ -43,20 +56,20 @@ objects:
- name: INTERVAL
value: ${INTERVAL}
- name: MODE
value: ${MODE}
value: ${MODE}
- name: TZ
value: ${TZ}
image: dockerpfurmanek/monkey-ops:1
image: produban/monkey-ops:latest
imagePullPolicy: IfNotPresent
name: ${APP_NAME}
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
memory: 20M
memory: 64Mi
request:
memory: 20M
memory: 64Mi
securityContext:
capabilities: {}
privileged: false
Expand Down Expand Up @@ -104,7 +117,7 @@ parameters:
displayName: Execution Mode, It must be "background", i.e., it runs nonstop, or "rest", i.e., it executes via API Rest.
name: MODE
required: true
value: background
value: rest
- description: TimeZone for the running containers.
displayName: TimeZone
name: TZ
Expand Down