github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/contrib/embargo/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "log" 8 "math/rand" 9 "os" 10 "os/exec" 11 "strings" 12 "time" 13 14 "github.com/pkg/errors" 15 ) 16 17 var ctxb = context.Background() 18 19 func run(ctx context.Context, command string) error { 20 args := strings.Split(command, " ") 21 var checkedArgs []string 22 for _, arg := range args { 23 if len(arg) > 0 { 24 checkedArgs = append(checkedArgs, arg) 25 } 26 } 27 cmd := exec.CommandContext(ctx, checkedArgs[0], checkedArgs[1:]...) 28 var out bytes.Buffer 29 cmd.Stdout = &out 30 cmd.Stderr = &out 31 if err := cmd.Run(); err != nil { 32 fmt.Printf("[%v] ERROR. Command %q. Error: %v. Output:\n%s\n", 33 time.Now().UTC(), command, err, out.String()) 34 return err 35 } 36 fmt.Printf("[%v] Command %q. Output:\n%s\n", time.Now().UTC(), command, out.String()) 37 return nil 38 } 39 40 func increment(atLeast int, args string) error { 41 errCh := make(chan error, 1) 42 ctx, cancel := context.WithTimeout(ctxb, 1*time.Minute) 43 defer cancel() 44 45 addrs := []string{"localhost:9180", "localhost:9182", "localhost:9183"} 46 for _, addr := range addrs { 47 go func(addr string) { 48 errCh <- run(ctx, fmt.Sprintf("dgraph increment --alpha=%s %s", addr, args)) 49 }(addr) 50 } 51 start := time.Now() 52 var ok int 53 for i := 0; i < len(addrs) && ok < atLeast; i++ { 54 if err := <-errCh; err == nil { 55 ok++ 56 } else { 57 fmt.Printf("[%v] Got error during increment: %v\n", time.Now().UTC(), err) 58 } 59 } 60 if ok < atLeast { 61 return errors.Errorf("Increment with atLeast=%d failed. OK: %d", atLeast, ok) 62 } 63 dur := time.Since(start).Round(time.Millisecond) 64 fmt.Printf("\n[%v] ===> TIME taken to converge %d alphas: %s\n\n", 65 time.Now().UTC(), atLeast, dur) 66 return nil 67 } 68 69 func getStatus(zero string) error { 70 cmd := exec.Command("http", "GET", fmt.Sprintf("%s/state", zero)) 71 var out bytes.Buffer 72 cmd.Stdout = &out 73 cmd.Stderr = &out 74 if err := cmd.Run(); err != nil { 75 fmt.Printf("ERROR. Status at %s. Error: %v. Output:\n%s\n", zero, err, out.String()) 76 return err 77 } 78 output := out.String() 79 if strings.Contains(output, "errors") { 80 fmt.Printf("ERROR. Status at %s. Output:\n%s\n", zero, output) 81 return errors.Errorf(output) 82 } 83 // var m map[string]interface{} 84 // if err := json.Unmarshal([]byte(output), &m); err != nil { 85 // return err 86 // } 87 // pretty, err := json.MarshalIndent(m, "", " ") 88 // if err != nil { 89 // return err 90 // } 91 fmt.Printf("Status at %s:\n%s\n", zero, output) 92 return nil 93 } 94 95 func testCommon(remove, join, incrementArgs string, nodes []string, minAlphasUp int) error { 96 fmt.Printf("Nodes: %+v\n", nodes) 97 for _, node := range nodes { 98 if err := getStatus("localhost:6080"); err != nil { 99 return err 100 } 101 fmt.Printf("\n==> Remove cmd %q on NODES: %s\n", remove, node) 102 if err := run(ctxb, remove+" "+node); err != nil { 103 return err 104 } 105 if err := run(ctxb, "embargo status"); err != nil { 106 return err 107 } 108 if err := increment(minAlphasUp, incrementArgs); err != nil { 109 return err 110 } 111 // Then join, if available. 112 if len(join) == 0 { 113 continue 114 } 115 if err := run(ctxb, join); err != nil { 116 return err 117 } 118 if err := increment(3, incrementArgs); err != nil { 119 return err 120 } 121 } 122 return nil 123 } 124 125 func waitForHealthy() error { 126 for _, zero := range []string{"localhost:6080", "localhost:6082", "localhost:6083"} { 127 if err := getStatus(zero); err != nil { 128 return err 129 } 130 } 131 for _, alpha := range []string{"localhost:9180", "localhost:9182", "localhost:9183"} { 132 if err := run(ctxb, "dgraph increment --alpha="+alpha); err != nil { 133 return err 134 } 135 } 136 return nil 137 } 138 139 func runTests() error { 140 for { 141 if err := waitForHealthy(); err != nil { 142 fmt.Printf("Error while waitForHealthy: %v\n.", err) 143 time.Sleep(5 * time.Second) 144 fmt.Println("Retrying...") 145 } else { 146 break 147 } 148 } 149 150 var nodes []string 151 for i := 1; i <= 3; i++ { 152 for j := 1; j <= 3; j++ { 153 nodes = append(nodes, fmt.Sprintf("zero%d dg%d", i, j)) 154 } 155 } 156 157 var alphaNodes []string 158 for i := 1; i <= 3; i++ { 159 alphaNodes = append(alphaNodes, fmt.Sprintf("dg%d", i)) 160 } 161 162 // Setting flaky --all just does not converge. Too many network interruptions. 163 // if err := testCommon("embargo flaky", "embargo fast --all", 3); err != nil { 164 // fmt.Printf("Error testFlaky: %v\n", err) 165 // return err 166 // } 167 // fmt.Println("===> Flaky TEST: OK") 168 169 // if err := testCommon("embargo slow", "embargo fast --all", 3); err != nil { 170 // fmt.Printf("Error testSlow: %v\n", err) 171 // return err 172 // } 173 // fmt.Println("===> Slow TEST: OK") 174 175 if err := testCommon("embargo stop", "embargo start --all", "", nodes, 2); err != nil { 176 fmt.Printf("Error testStop: %v\n", err) 177 return err 178 } 179 fmt.Println("===> Stop TEST: OK") 180 181 if err := testCommon("embargo restart", "", "", nodes, 3); err != nil { 182 fmt.Printf("Error testRestart with restart: %v\n", err) 183 return err 184 } 185 fmt.Println("===> Restart TEST: OK") 186 187 if err := testCommon("embargo partition", "embargo join", "", nodes, 2); err != nil { 188 fmt.Printf("Error testPartitions: %v\n", err) 189 return err 190 } 191 fmt.Println("===> Partition TEST: OK") 192 193 if err := testCommon("embargo partition", "embargo join", "--be", alphaNodes, 3); err != nil { 194 fmt.Printf("Error testPartitionsBestEffort: %v\n", err) 195 return err 196 } 197 fmt.Println("===> Partition best-effort TEST: OK") 198 199 return nil 200 } 201 202 func main() { 203 rand.Seed(time.Now().UnixNano()) 204 fmt.Println("Starting embargo") 205 if err := run(ctxb, "embargo up"); err != nil { 206 log.Fatal(err) 207 } 208 // This defer can be moved within runTests, if we want to destroy embargo, 209 // in case our tests fail. We don't want to do that, because then we won't 210 // be able to get the logs. 211 defer func() { 212 if err := run(ctxb, "embargo destroy"); err != nil { 213 log.Fatalf("While destroying: %v", err) 214 } 215 }() 216 217 if err := runTests(); err != nil { 218 os.Exit(1) 219 } 220 fmt.Println("embargo tests: OK") 221 }