As previously discussed, some of us think that a mock TO server can be beneficial for testing clients. For specific reasoning, refer to that discussion: https://mail-archives.apache.org/mod_mbox/trafficcontrol-dev/201902.mbox/%3CCA%2B5ZNX9pE5F-ecC0atpq6bTkBDnr7zCsADQcW3enXdpVRbpCdQ%40mail.gmail.com%3E
Now some code for that mock server has been written. The Pull Request for it is here: https://github.com/apache/trafficcontrol/pull/3478 but a short description of what it does (and doesn't) do is: The Traffic Ops mock server **SHALL** * Serve all of the API routes supported by the Traffic Ops API * Serve static responses that never change in structure or content* Identify itself through the ``Server`` HTTP header as ``Traffic Ops/{{version}} (Mock)`` * Support all methods supported by the Traffic Ops (the behavior of the server when the client uses erroneous request methods, request paths or request parameters is not defined) * Faithfully reproduce syntactically valid - and self-consistent - responses of the real Traffic Ops The Traffic Ops mock server **SHALL NOT** * Require proper authentication, despite that a real server would (because testing one route shouldn't have extraneous dependencies) * Modify any of its pre-determined responses during runtime. This means that a client may attempt to e.g. create a server object by submitting a ``POST`` request to ``/api/{{version}}/servers`` - which should receive a response indicating the operation was successful (assuming it was syntactically valid and consistent with the static data set) - the new server object will not appear in the response of a subsequent ``GET`` request to the same endpoint Now, with all that in mind, there's been discussion on the PR as to whether it's more appropriate to serve static JSON files or use globally scoped Go structure constants. There are advantages and disadvantages to both approaches. Personally, I favor the Go structures. Global structs aid in consistency; for example, a server's id is declared once and can be used in responses to the ``/api/{{version}}/servers`` endpoint, deliveryservice assignment endpoints etc. If we use JSON files, any change or update will require the developer to check through all remaining JSON files for further instances. They also allow us to use (some of) the same functions as the real Traffic Ops when serving API responses, which gives us correct ``alerts`` objects for free. Since it's supposed to fully mock the API, it should also be able to handle POST/PUT/DELETE requests as well as just GET. In order to be self-consistent, this means we'd need to have prepared responses for those as well - but this isn't possible since e.g. the user can POST a server with any arbitrary (valid) hostname. So when we echo the created object back to the client, we'd need to be able to parse, validate and respond with this unknown input data. Which means writing specific Go handlers for almost every endpoint anyway, so at most static JSON will handle 1/4 of all cases, which is going to leave us with a mixture of using pure JSON and using Go structs. Some downsides of the Go structs: the code is really ugly, and the GET requests have a lot of associated data that could be handled much more simply by just serving from the filesystem. It would also probably grow to use significantly more memory that a JSON approach. The biggest advantage of a JSON file structure is that it's very simple, and it's been argued that the cost of updating things when they change is next to negligible, since the canonical mock server shouldn't need to change actual data - just add new fields. Which is true, my only concern is that the current set of implemented routes is very small and as it grows things will need to change until parity with the real TO API is reached. Doing all of that at once is - in my opinion - certainly far beyond the scope of a single PR. So for anyone who cares: which do you think we should use? (Also I'm sure Rawlin Peters can better articulate his position on using JSON than I have, so please feel free to do that my dude)
