REST service endpoint?

So, for services, I’m in a bit of a quandary. We’re wanting to expose start, stop, etc., of services (daemons) that are apps in snaps. That is, we’re letting clients the , where there’s a clear hierarchical path to those nouns (they’re an app inside a snap, after all). So one naive way of doing this would be to expose /snaps/<snap>/<app>, POSTing something like {"action": "stop"} to it to get what we want. This matches what you do when managing a single snap, e.g. you POST to /snaps/<snap> with {"action": "install"}, etc.

However, we’ve learned that we also want to support operating on multiple snaps at a time (more common for remove than for install, but still), so we’ve added POSTing directly to /snaps/ with {"action": "x", "snaps": ["foo","bar", ...]}.

Further, the way the user would specify starting/stopping services lends itself well to supporting doing it for multiple, that is: there’s no real reason not to support snap (status|logs|start|stop|enable|disable) [snap[.app]] .... But POSTing at /snaps seems to me to be bending things rather far (and making status and logs be a POST just feels strange).

Which means I’m leaning heavily towards having a /services endpoint. What do you think?

I think /v2/services is a good idea. We could then do some interesting things, apart from the obvious service control we could do live streaming of service logs (snap log --follow snap) and having a dedicated, not already overloaded, endpoint helps.

The requirement for that feature doesn’t actually justify the design proposed by John above. Not saying it’s a bad design, but still thinking about the pros and cons of this compared to the alternatives.

Okay, I can’t think of anything better than this after sleeping on it for a few days. The one thing I kept trying to imagine is whether there might be a more general abstraction focused on the applications instead of snaps, but generalized for all applications instead of services. The problem, as we discussed, is that we’ll need to special-cases services either way inside that interface since they are special in a few different ways. So, even if we do decide to create such a general API, it sounds fine and easy to maintain a separate API which is more specifically tailored for them.

The one thing that would be nice to fix now instead of later is that idea of having a task to run those commands, instead of running them synchronously. The problem, again as we talked during the standup meeting, is that those APIs are incompatible, so we can’t just decide later to move them to a task. I suggest using a single task “execute-command” for all of them, and varying the data we pass to the task. Our existing hook tasks should serve as inspiration to create something much simpler for this one need, perhaps under a execstate package if there’s nothing better.

Thanks again for pushing this forward.