healthchecks / healthchecks

Open-source cron job and background task monitoring service, written in Python & Django

Home Page:https://healthchecks.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Openapi / Swagger specs for the Pinging and Management APIs?

arminrosu opened this issue · comments

Hello,

I'd like to make my life easier and create Typescript clients for the Pinging API and Management API. The latter I need to provision checks as I create resources in pulumi, the former for runtime use.

The easiest would be to have an OpenAPI specfile for these APIs. Based off that clients can be generated in a multitude of languages. Unfortunately, I didn't find any - there's no reference to them and the code doesn't seem to have annotations for generating specfiles.

Did I miss them? Would you consider adding them in the future?

There are no OpenAPI specs currently.

When looking for specfile, where would you expect to find it? (Where did you look for it, in what order?)

Do you have any tips on tools to use to write/generate the specs?

When looking for specfile, where would you expect to find it?

Besides the documentation, these are the most common urls I check:

Then I started looking in the codebase for decorators (e.g. around https://github.com/healthchecks/healthchecks/blob/master/hc/api/views.py) or code generated based on a specfile.

Do you have any tips on tools to use to write/generate the specs?

I usually write out the specfile first, in plain yaml or stoplight (which IMO is a bit pricey for what it does). This allows me to think at a high level. Then I generate code based on a specfile because that also creates request/response validators and type stubs. And you have a humane documentation which can be presented using e.g. slate.

The clients I generate using openapi-generator which in my experience does a great job. It also supports generation of server side code, but only Flask / FastApi for Python.

It seems drf-spectacular is the most common way of generating openapi specfiles from django. It works via annotations and seems to require use of drf. That seems like a major change.

But for now, I think writing a specfile manually would be useful. You can generate https://healthchecks.io/docs/ from them, as well as tests against the API. This way you'll know if they start diverging.

If you like, I could give it a first shot for v3 of the API.

Thanks for the pointers.

If you like, I could give it a first shot for v3 of the API.

That would be awesome!

@cuu508 that took a bit but here it is: https://armin-inc.stoplight.io/docs/healthchecks-io/

Please let me know when you're done with it, I'll take it down after.

The good

You have examples of all major features, including input pattern validation, polymorphism etc. I didn't spec out every endpoint on the Management API, cause it was getting a bit much for me.

You can download the yaml file from there and view how the documentation would look like in stoplight-elements. IMO, that's one of the better doc generators out there, which also generates sample client code in multiple languages and supports static pages.

The bad

It doesn't properly generate response samples when using polymorphism. See create a check vs. list badges. This can be fixed by writing flat schemas, but IMO that is tedious and error prone. There are utilities which will flatten references, so it can be automated eventually.

By default Stoplight Studio generates examples in custom fields. You need to manually set the example field values in code view.

The odd

Not all endpoints have a 401 response. I didn't check if that's because the documentation is missing it or the code doesn't have it. E.g. Get a ping's logged body

Having different response types based on the type of token is unusual. It cannot be specced in openapi - to use the token as a discriminator and makes response caching harder. What prompted this design choice?

Why did you choose to wrap list responses in an object? e.g. { badges: badge[] } instead of just badges[] or { data: badges[], paginationFields }. Just curious.


Hope that helps 😃


schema backup for future generations:

healtchecks.io-Management-API.yaml.zip

Thanks, interesting. What are the next steps, what can I do with this? Can I use the schema to generate docs that match https://healthchecks.io/docs/?

Not all endpoints have a 401 response. I didn't check if that's because the documentation is missing it or the code doesn't have it. E.g. Get a ping's logged body

In some cases we don't want to disclose if the resource exists. If the API returns 404 for missing resources and 401 for existing resources, attackers can poke around and check what resources exist.

Having different response types based on the type of token is unusual. It cannot be specced in openapi - to use the token as a discriminator and makes response caching harder. What prompted this design choice? [...] What prompted this design choice?

Do you mean different response contents depending on API key type? The thinking here is, a major use case for read-only keys is public custom dashboards. When using read-only API keys, the API must be careful not to disclose check UUIDs. Otherwise any visitor of the public dashboard would be able to construct ping URLs and mess with the monitoring.

Aside the from the redacted check UUIDs, the API responses are the same for the regular and the read-only API keys, so it made sense to reuse the same code and the same API endpoints. I was not thinking about openapi constraints.

Why did you choose to wrap list responses in an object?

It was a security thing. I didn't want to think about all possible present and future security concerns around using top-level arrays in API responses, so went with the safe option of wrapping them in an object.

https://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk

What are the next steps, what can I do with this? Can I use the schema to generate docs that match https://healthchecks.io/docs/?

Please have a look at https://armin-inc.stoplight.io/docs/healthchecks-io/. That's basically what the docs would look like with stoplight-elements. If you like that, go ahead and generate the docs. Just add the remaining Management API endpoints to it.

I would also set up some testing against the API itself, to see when it diverges. And create some clients in popular languages, to see if it all works like it should. Then I'd note that in the docs that people can just generate some themselves.

The thinking here is, a major use case for read-only keys is public custom dashboards. When using read-only API keys, the API must be careful not to disclose check UUIDs. Otherwise any visitor of the public dashboard would be able to construct ping URLs and mess with the monitoring.

Interesting, always glad to learn about use cases. I might have removed the properties which expose UUID in the write token response.

Cheers!

To integrate an OpenAPI spec in this project, I would need:

  • a GUI editor for editing the schema (we're not using DRF so cannot generate it automatically. And editing a 900-line YAML file does not seem fun)
  • a way to turn the spec into API documentation

For the editor, I had a look at the GUI editors listed in https://openapi.tools/#gui-editors. The spec may be Open, but most of the tooling seems proprietary? Clicking on the links I get "Start free trial..." and "Sign Up" prompts – thanks but no thanks ;-) If anyone knows of a good libre OpenAPI spec editor, please share.

For generating API documentation, ideally I would like the generated docs look the same as the existing docs – static HTML content, no JS. Hosted with the rest of docs, not on a separate mini-site. Perhaps there is a tool that could be adapted.