Diagnostics command

Initial work is on #17609

"arvados-client diagnostics"

Current level of functionality:
  • reveal common problems that can be hard to notice/recognize, especially for someone who is new to installing arvados (e.g., invalid TLS certificate for websocket, which breaks workbench but presents no error message)
  • produce output that can be shared with others to help with troubleshooting
Desired/requested features:
  • download data using s3 protocol
  • run config-check (if cluster config file is accessible)
  • check all health endpoints (if cluster config file is accessible)
  • make internal/external client recognition mandatory (or at least default to expecting one)
  • enable debug/trace mode for a single test number
  • more verbose errors/explanations
  • for each service, report version currently running
  • for each service, report version currently installed ("/proc/self/exe -version"?)
  • for each service, report md5/timestamp of config file that is currently being used (not necessarily same as one currently on disk)
  • for each service, report md5/timestamp of config file on disk
  • check Ruby command-line tools (arv) are installed and working
  • check Python command-line tools (like arv-put) are installed and working
  • check Docker is installed on current host, and is usable by arv-keepdocker
  • check arvados-cwl-runner is installed and working (run a workflow)
  • set up a user account with "arv user setup"
  • test that webshell actually works (currently just tries connecting, but this probably doesn't reveal pam config problems)
Undesired features that really belong elsewhere:
  • check for problems in config file (this should be done in config-check instead)
Internal (code) updates wanted:
  • (from #17609#note-18, re big runtests() func) I think we will need to split this up sooner or later. I'm thinking one big section to do the initial staging setup (current user, scratch project/collection) and then something more modular for an ever-growing set of test funcs that are independent of one another. Not sure whether I should do it right now, or put it on the todo list. Something like this might work, with minimal repetition:
    type testenv struct {
      project    arvados.Group
      collection arvados.Collection
    }
    
    var _ = addtest(1234, "testing some stuff", func(env *testenv) error { ... })