Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 1 | // This binary lets users interact with the scouting web server in order to |
| 2 | // debug it. Run with `--help` to see all the options. |
| 3 | |
| 4 | package main |
| 5 | |
| 6 | import ( |
| 7 | "flag" |
| 8 | "io/ioutil" |
| 9 | "log" |
| 10 | "os" |
| 11 | "os/exec" |
| 12 | "path/filepath" |
| 13 | |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame] | 14 | "github.com/davecgh/go-spew/spew" |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 15 | "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug" |
| 16 | ) |
| 17 | |
| 18 | // Returns the absolute path of the specified path. This is an unwrapped |
| 19 | // version of `filepath.Abs`. |
| 20 | func absPath(path string) string { |
| 21 | result, err := filepath.Abs(path) |
| 22 | if err != nil { |
| 23 | log.Fatal("Failed to determine absolute path for ", path, ": ", err) |
| 24 | } |
| 25 | return result |
| 26 | } |
| 27 | |
| 28 | // Parses the specified JSON file into a binary version (i.e. serialized |
| 29 | // flatbuffer). This uses the `flatc` binary and the JSON's corresponding |
| 30 | // `.fbs` file. |
| 31 | func parseJson(fbsPath string, jsonPath string) []byte { |
| 32 | // Work inside a temporary directory since `flatc` doesn't allow us to |
| 33 | // customize the name of the output file. |
| 34 | dir, err := ioutil.TempDir("", "webserver_debug_cli") |
| 35 | if err != nil { |
| 36 | log.Fatal("Failed to create temporary directory: ", err) |
| 37 | } |
| 38 | defer os.RemoveAll(dir) |
| 39 | |
| 40 | // Turn these paths absolute so that it everything still works from |
| 41 | // inside the temporary directory. |
| 42 | absFlatcPath := absPath("external/com_github_google_flatbuffers/flatc") |
| 43 | absFbsPath := absPath(fbsPath) |
| 44 | |
| 45 | // Create a symlink to the .fbs file so that the output filename that |
| 46 | // `flatc` generates is predictable. I.e. `fb.json` gets serialized |
| 47 | // into `fb.bin`. |
| 48 | jsonSymlink := filepath.Join(dir, "fb.json") |
| 49 | os.Symlink(jsonPath, jsonSymlink) |
| 50 | |
| 51 | // Execute the `flatc` command. |
| 52 | flatcCommand := exec.Command(absFlatcPath, "--binary", absFbsPath, jsonSymlink) |
| 53 | flatcCommand.Dir = dir |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 54 | output, err := flatcCommand.CombinedOutput() |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 55 | if err != nil { |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 56 | log.Fatal("Failed to execute flatc: ", err, ": ", string(output)) |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | // Read the serialized flatbuffer and return it. |
| 60 | binaryPath := filepath.Join(dir, "fb.bin") |
| 61 | binaryFb, err := os.ReadFile(binaryPath) |
| 62 | if err != nil { |
| 63 | log.Fatal("Failed to read flatc output ", binaryPath, ": ", err) |
| 64 | } |
| 65 | return binaryFb |
| 66 | } |
| 67 | |
Philipp Schrader | 02ec8e4 | 2022-03-26 16:37:18 -0700 | [diff] [blame] | 68 | func maybePerformRequest[T interface{}](fbName, fbsPath, requestJsonPath, address string, requester func(string, []byte) (*T, error)) { |
| 69 | if requestJsonPath != "" { |
| 70 | log.Printf("Sending %s to %s", fbName, address) |
| 71 | binaryRequest := parseJson(fbsPath, requestJsonPath) |
| 72 | response, err := requester(address, binaryRequest) |
| 73 | if err != nil { |
| 74 | log.Fatalf("Failed %s: %v", fbName, err) |
| 75 | } |
| 76 | spew.Dump(*response) |
| 77 | } |
| 78 | } |
| 79 | |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 80 | func main() { |
| 81 | // Parse command line arguments. |
Philipp Schrader | 30005e4 | 2022-03-06 13:53:58 -0800 | [diff] [blame] | 82 | indentPtr := flag.String("indent", " ", |
| 83 | "The indentation to use for the result dumping. Default is a space.") |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 84 | addressPtr := flag.String("address", "http://localhost:8080", |
| 85 | "The end point where the server is listening.") |
| 86 | submitDataScoutingPtr := flag.String("submitDataScouting", "", |
| 87 | "If specified, parse the file as a SubmitDataScouting JSON request.") |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 88 | requestAllMatchesPtr := flag.String("requestAllMatches", "", |
| 89 | "If specified, parse the file as a RequestAllMatches JSON request.") |
Philipp Schrader | d1c4bef | 2022-02-28 22:51:30 -0800 | [diff] [blame] | 90 | requestMatchesForTeamPtr := flag.String("requestMatchesForTeam", "", |
| 91 | "If specified, parse the file as a RequestMatchesForTeam JSON request.") |
Philipp Schrader | acf9623 | 2022-03-01 22:03:30 -0800 | [diff] [blame] | 92 | requestDataScoutingPtr := flag.String("requestDataScouting", "", |
| 93 | "If specified, parse the file as a RequestDataScouting JSON request.") |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame] | 94 | refreshMatchListPtr := flag.String("refreshMatchList", "", |
| 95 | "If specified, parse the file as a RefreshMatchList JSON request.") |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 96 | flag.Parse() |
| 97 | |
Philipp Schrader | 30005e4 | 2022-03-06 13:53:58 -0800 | [diff] [blame] | 98 | spew.Config.Indent = *indentPtr |
| 99 | |
Philipp Schrader | fe58384 | 2022-04-08 19:47:07 -0700 | [diff] [blame] | 100 | // Disable pointer addresses. They're not useful for our purposes. |
| 101 | spew.Config.DisablePointerAddresses = true |
| 102 | |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 103 | // Handle the actual arguments. |
Philipp Schrader | 02ec8e4 | 2022-03-26 16:37:18 -0700 | [diff] [blame] | 104 | maybePerformRequest( |
| 105 | "SubmitDataScouting", |
| 106 | "scouting/webserver/requests/messages/submit_data_scouting.fbs", |
| 107 | *submitDataScoutingPtr, |
| 108 | *addressPtr, |
| 109 | debug.SubmitDataScouting) |
| 110 | |
| 111 | maybePerformRequest( |
| 112 | "RequestAllMatches", |
| 113 | "scouting/webserver/requests/messages/request_all_matches.fbs", |
| 114 | *requestAllMatchesPtr, |
| 115 | *addressPtr, |
| 116 | debug.RequestAllMatches) |
| 117 | |
| 118 | maybePerformRequest( |
| 119 | "RequestMatchesForTeam", |
| 120 | "scouting/webserver/requests/messages/request_matches_for_team.fbs", |
| 121 | *requestMatchesForTeamPtr, |
| 122 | *addressPtr, |
| 123 | debug.RequestMatchesForTeam) |
| 124 | |
| 125 | maybePerformRequest( |
| 126 | "RequestDataScouting", |
| 127 | "scouting/webserver/requests/messages/request_data_scouting.fbs", |
| 128 | *requestDataScoutingPtr, |
| 129 | *addressPtr, |
| 130 | debug.RequestDataScouting) |
| 131 | |
| 132 | maybePerformRequest( |
| 133 | "RefreshMatchList", |
| 134 | "scouting/webserver/requests/messages/refresh_match_list.fbs", |
| 135 | *refreshMatchListPtr, |
| 136 | *addressPtr, |
| 137 | debug.RefreshMatchList) |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 138 | } |