-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
262 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
Introduction to Jim | ||
=================== | ||
|
||
Jim is the MailHog Chaos Monkey, inspired by Netflix. | ||
|
||
You can invite Jim to the party using the `invite-jim` flag: | ||
|
||
MailHog -invite-jim | ||
|
||
With Jim around, things aren't going to work how you expect. | ||
|
||
### What can Jim do? | ||
|
||
* Reject connections | ||
* Rate limit connections | ||
* Reject authentication | ||
* Reject senders | ||
* Reject recipients | ||
|
||
It does this randomly, but within defined parameters. | ||
|
||
You can control these using the following command line flags: | ||
|
||
| Flag | Default | Description | ||
| --------------------- | ------- | ---- | ||
| -invite-jim | false | Set to true to invite Jim | ||
| -jim-disconnect | 0.005 | Chance of randomly disconnecting a session | ||
| -jim-accept | 0.99 | Chance of accepting an incoming connection | ||
| -jim-linkspeed-affect | 0.1 | Chance of applying a rate limit | ||
| -jim-linkspeed-min | 1024 | Minimum link speed (in bytes per second) | ||
| -jim-linkspeed-max | 10240 | Maximum link speed (in bytes per second) | ||
| -jim-reject-sender | 0.05 | Chance of rejecting a MAIL FROM command | ||
| -jim-reject-recipient | 0.05 | Chance of rejecting a RCPT TO command | ||
| -jim-reject-auth | 0.05 | Chance of rejecting an AUTH command | ||
|
||
If you enable Jim, you enable all parts. To disable individual parts, set the chance | ||
of it happening to 0, e.g. to disable connection rate limiting: | ||
|
||
MailHog -invite-jim -jim-linkspeed-affect=0 | ||
|
||
### Examples | ||
|
||
Always rate limit to 1 byte per second: | ||
|
||
MailHog -invite-jim -jim-linkspeed-affect=1 -jim-linkspeed-max=1 -jim-linkspeed-min=1 | ||
|
||
Disconnect clients after approximately 5 commands: | ||
|
||
MailHog -invite-jim -jim-disconnect=0.2 | ||
|
||
Simulate a mobile connection (at 10-100kbps) for 10% of clients: | ||
|
||
MailHog -invite-jim -jim-linkspeed-affect=0.1 -jim-linkspeed-min=1250 -jim-linkspeed-max=12500 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package monkey | ||
|
||
import ( | ||
"flag" | ||
"math/rand" | ||
"net" | ||
"time" | ||
|
||
"github.com/ian-kent/linkio" | ||
) | ||
|
||
// Jim is a chaos monkey | ||
type Jim struct { | ||
disconnectChance float64 | ||
acceptChance float64 | ||
linkSpeedAffect float64 | ||
linkSpeedMin float64 | ||
linkSpeedMax float64 | ||
rejectSenderChance float64 | ||
rejectRecipientChance float64 | ||
rejectAuthChance float64 | ||
logf func(message string, args ...interface{}) | ||
} | ||
|
||
// RegisterFlags implements ChaosMonkey.RegisterFlags | ||
func (j *Jim) RegisterFlags() { | ||
flag.Float64Var(&j.disconnectChance, "jim-disconnect", 0.005, "Chance of disconnect") | ||
flag.Float64Var(&j.acceptChance, "jim-accept", 0.99, "Chance of accept") | ||
flag.Float64Var(&j.linkSpeedAffect, "jim-linkspeed-affect", 0.1, "Chance of affecting link speed") | ||
flag.Float64Var(&j.linkSpeedMin, "jim-linkspeed-min", 1024, "Minimum link speed (in bytes per second)") | ||
flag.Float64Var(&j.linkSpeedMax, "jim-linkspeed-max", 10240, "Maximum link speed (in bytes per second)") | ||
flag.Float64Var(&j.rejectSenderChance, "jim-reject-sender", 0.05, "Chance of rejecting a sender (MAIL FROM)") | ||
flag.Float64Var(&j.rejectRecipientChance, "jim-reject-recipient", 0.05, "Chance of rejecting a recipient (RCPT TO)") | ||
flag.Float64Var(&j.rejectAuthChance, "jim-reject-auth", 0.05, "Chance of rejecting authentication (AUTH)") | ||
} | ||
|
||
// Configure implements ChaosMonkey.Configure | ||
func (j *Jim) Configure(logf func(string, ...interface{})) { | ||
j.logf = logf | ||
rand.Seed(time.Now().Unix()) | ||
} | ||
|
||
// Accept implements ChaosMonkey.Accept | ||
func (j *Jim) Accept(conn net.Conn) bool { | ||
if rand.Float64() > j.acceptChance { | ||
j.logf("Jim: Rejecting connection\n") | ||
return false | ||
} | ||
j.logf("Jim: Allowing connection\n") | ||
return true | ||
} | ||
|
||
// LinkSpeed implements ChaosMonkey.LinkSpeed | ||
func (j *Jim) LinkSpeed() *linkio.Throughput { | ||
rand.Seed(time.Now().Unix()) | ||
if rand.Float64() < j.linkSpeedAffect { | ||
lsDiff := j.linkSpeedMax - j.linkSpeedMin | ||
lsAffect := j.linkSpeedMin + (lsDiff * rand.Float64()) | ||
f := linkio.Throughput(lsAffect) * linkio.BytePerSecond | ||
j.logf("Jim: Restricting throughput to %s\n", f) | ||
return &f | ||
} | ||
j.logf("Jim: Allowing unrestricted throughput") | ||
return nil | ||
} | ||
|
||
// ValidRCPT implements ChaosMonkey.ValidRCPT | ||
func (j *Jim) ValidRCPT(rcpt string) bool { | ||
if rand.Float64() < j.rejectRecipientChance { | ||
j.logf("Jim: Rejecting recipient %s\n", rcpt) | ||
return false | ||
} | ||
j.logf("Jim: Allowing recipient%s\n", rcpt) | ||
return true | ||
} | ||
|
||
// ValidMAIL implements ChaosMonkey.ValidMAIL | ||
func (j *Jim) ValidMAIL(mail string) bool { | ||
if rand.Float64() < j.rejectSenderChance { | ||
j.logf("Jim: Rejecting sender %s\n", mail) | ||
return false | ||
} | ||
j.logf("Jim: Allowing sender %s\n", mail) | ||
return true | ||
} | ||
|
||
// ValidAUTH implements ChaosMonkey.ValidAUTH | ||
func (j *Jim) ValidAUTH(mechanism string, args ...string) bool { | ||
if rand.Float64() < j.rejectAuthChance { | ||
j.logf("Jim: Rejecting authentication %s: %s\n", mechanism, args) | ||
return false | ||
} | ||
j.logf("Jim: Allowing authentication %s: %s\n", mechanism, args) | ||
return true | ||
} | ||
|
||
// Disconnect implements ChaosMonkey.Disconnect | ||
func (j *Jim) Disconnect() bool { | ||
if rand.Float64() < j.disconnectChance { | ||
j.logf("Jim: Being nasty, kicking them off\n") | ||
return true | ||
} | ||
j.logf("Jim: Being nice, letting them stay\n") | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package monkey | ||
|
||
import ( | ||
"net" | ||
|
||
"github.com/ian-kent/linkio" | ||
) | ||
|
||
// ChaosMonkey should be implemented by chaos monkeys! | ||
type ChaosMonkey interface { | ||
RegisterFlags() | ||
Configure(func(string, ...interface{})) | ||
|
||
// Accept is called for each incoming connection. Returning false closes the connection. | ||
Accept(conn net.Conn) bool | ||
// LinkSpeed sets the maximum connection throughput (in one direction) | ||
LinkSpeed() *linkio.Throughput | ||
|
||
// ValidRCPT is called for the RCPT command. Returning false signals an invalid recipient. | ||
ValidRCPT(rcpt string) bool | ||
// ValidMAIL is called for the MAIL command. Returning false signals an invalid sender. | ||
ValidMAIL(mail string) bool | ||
// ValidAUTH is called after authentication. Returning false signals invalid authentication. | ||
ValidAUTH(mechanism string, args ...string) bool | ||
|
||
// Disconnect is called after every read. Returning true will close the connection. | ||
Disconnect() bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.