diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e9eb644..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -coverage.out -.idea/ diff --git a/chaosmonkey b/chaosmonkey new file mode 100755 index 0000000..42ad87d Binary files /dev/null and b/chaosmonkey differ diff --git a/chaosmonkey.toml b/chaosmonkey.toml new file mode 100644 index 0000000..2e6126a --- /dev/null +++ b/chaosmonkey.toml @@ -0,0 +1,14 @@ +[spinnaker] +endpoint = "http://localhost:8084" +ignoreSSL = true + +[monkey] +leashed = true # So Chaos Monkey wonโ€™t actually terminate anything + +[logging] +level = "debug" + +[schedule] +enabled = true +frequency = "daily" +time = "09:00" diff --git a/go.mod b/go.mod index 5ebe0c3..0bb94e8 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/spf13/jwalterweatherman v0.0.0-20160311093646-33c24e77fb80 // indirect github.com/stretchr/testify v1.8.1 // indirect github.com/ziutek/mymysql v1.5.4 // indirect - golang.org/x/sys v0.0.0-20160916181909-8f0908ab3b24 // indirect + golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.9.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/gorp.v1 v1.7.1 // indirect diff --git a/go.sum b/go.sum index 652568f..ff26a57 100644 --- a/go.sum +++ b/go.sum @@ -59,10 +59,10 @@ github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= golang.org/x/crypto v0.0.0-20160922170629-8e06e8ddd962 h1:mWFWs/KZ0R2cLgNYRn+C4pQvMDmpkqxF1Npt3NEAPg0= golang.org/x/crypto v0.0.0-20160922170629-8e06e8ddd962/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/sys v0.0.0-20160916181909-8f0908ab3b24 h1:BL/wcoHkjubwHn2wDTAD1fehKZ9lf67KOVzucRKWPtM= -golang.org/x/sys v0.0.0-20160916181909-8f0908ab3b24/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.0.0-20160922232553-a7c023693a94 h1:QmdGgXvDlzDdp+l90rsC+qLFmFhl2nn+rSfBnS8P4zI= -golang.org/x/text v0.0.0-20160922232553-a7c023693a94/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 0000000..acc51d3 --- /dev/null +++ b/ui/index.html @@ -0,0 +1,255 @@ + + + + + + Chaos Command Center - Dashboard + + + + + + + + + +
+
+
+ + + + +

Chaos Command Center

+
+ +
+
+ + +
+ + +
+ + +
+

Event Analytics

+
+ +
+
+ + +
+

Service Dependency Map

+
+ +
+ User/Client +
+ + + + + +
+ API Gateway +
+ + + + + +
+
Auth Service
+
Recommendations API
+
Streaming CDN
+
+
+
+ +
+ + +
+ + +
+

Quick Actions

+ + + + + RUN SIMULATION + +
+ + +
+

Service Status

+
+ +
+ API Gateway +
+
+ Operational +
+
+ +
+ Auth Service +
+
+ Operational +
+
+ +
+ Recommendations API +
+
+ Operational +
+
+ +
+ Payment Gateway +
+
+ Degraded +
+
+ +
+ Streaming CDN +
+
+ Operational +
+
+ +
+ User DB (Primary) +
+
+ Operational +
+
+ +
+ User DB (Replica) +
+
+ Offline +
+
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/ui/simulation.html b/ui/simulation.html new file mode 100644 index 0000000..ee0d5d5 --- /dev/null +++ b/ui/simulation.html @@ -0,0 +1,487 @@ + + + + + + Chaos Command Center - Simulation + + + + + + + + + +
+ +
+ + +
+
+
+ + + + +

Chaos Command Center

+
+ +
+
+ + +
+ +
+ + +
+ + +
+

Simulation Controls

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
50
+
+ + +
+
+ + +
+
+

System Status

+
+
+ Loading... +
+
+
+
+ Last Experiment: + Never +
+
+ Active Services: + 0 / 0 +
+
+
+ +
+ + +
+

+ + + + + + + + Live Experiment Log +

+
+ +
+
+
+ + +
+

Experiment Analytics

+ + +
+
+

Total Experiments Run

+ 0 +
+
+

Avg. Recovery Time

+ 0.0s +
+
+

Total Services Impacted

+ 0 +
+
+ + +
+

Service Impact Over Time

+
+ +
+
+
+ +
+ + + + \ No newline at end of file diff --git a/ui_server.go b/ui_server.go new file mode 100644 index 0000000..4f63ecb --- /dev/null +++ b/ui_server.go @@ -0,0 +1,71 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + "os/exec" + "sync" + "time" +) + +type Status struct { + LastTriggered string `json:"lastTriggered"` + Message string `json:"message"` + Logs []string `json:"logs"` +} + +var ( + lastTriggered string + logs []string + mu sync.Mutex +) + +func triggerChaos(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() + lastTriggered = time.Now().Format(time.RFC1123) + cmd := exec.Command("./chaosmonkey", "intest") + out, _ := cmd.CombinedOutput() + entry := fmt.Sprintf("[%s] Chaos Triggered! Output: %s", lastTriggered, string(out)) + logs = append(logs, entry) + resp := Status{LastTriggered: lastTriggered, Message: "Chaos Triggered!", Logs: logs} + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(resp) +} + +func getStatus(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() + resp := Status{ + LastTriggered: lastTriggered, + Message: "System running", + Logs: logs, + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(resp) +} + +func submitSuggestion(w http.ResponseWriter, r *http.Request) { + type Suggestion struct { + Text string `json:"text"` + } + var s Suggestion + json.NewDecoder(r.Body).Decode(&s) + entry := fmt.Sprintf("[%s] ๐Ÿ’ก Suggestion: %s", time.Now().Format(time.RFC1123), s.Text) + mu.Lock() + logs = append(logs, entry) + mu.Unlock() + w.WriteHeader(http.StatusOK) +} + +func main() { + fs := http.FileServer(http.Dir("ui")) + http.Handle("/", fs) + http.HandleFunc("/api/status", getStatus) + http.HandleFunc("/api/trigger", triggerChaos) + http.HandleFunc("/api/suggest", submitSuggestion) + + fmt.Println("๐Ÿš€ Fancy UI running at http://localhost:8080") + http.ListenAndServe(":8080", nil) +}