If a task fails, we can either:
* allow other task ops to be called - we cannot do this because the ops are fine-grained. for example,
a restore failure removes many things and calling set-memory or set-location in that state won't
make sense.
* provide a generic repair route - this allows one to override args and call the failed task
again. this is what we have now but has the issue that this repair function has to know about all
the other op functions. for example, for argument validation. we can do some complicated refactoring
to make it work if we want.
* just a generic total re-configure - this does not work because clone/restore/backup/datadir/uninstall/update
failure leaves the app in a state which re-configure cannot do anything about.
* allow the failed op to be called again - this seems the easiest. we just allow the route to be called again
in the error state.
* if we hit a state where even providing extra args, cannot get you out of this "error" state, we have to provide
some repair route. for example, maybe the container disappeared by some docke error. user clicks 'repair' to
recreate the container. this route does not have to take any args.
The final solution is:
* a failed task can be called again via the route. so we can resubmit any args and we get validation
* repair route just re-configures and can be called in any state to just rebuild container. re-configure is also
doing only local changes (docker, nginx)
* install/clone failures are fixed using repair route. updated manifest can be passed in.
* UI shows backup selector for restore failures
* UI shows domain selector for change location failulre
It seems we cannot separate frame ancestors from CSP because the hide
header just hides everything and not a specific resource. This means
that the user has to set or unset the full policy whole sale.
* Do not allow scheduling tasks in error state
* Only repair is allowed in error state
* Use the error object to track what to 'repair' (like the lastState)
* If uninstall failed, repair will do uninstall
* If move dir failed, repair will do move dir
1. The error classes (like AppsError) now take a 3rd argument details.
We can attach anything in this 3rd argument and this gets sent in the
REST response as well.
2. The HttpError class is now HttpError(statusCode, errorOrMessage). If
it's an error object, it will take the message and other things which
were attached above from it and send them across. Previously, we used to
mark this case an internal error all the time.
3. AppsError only has generic codes now. The UI code then simply checks
for additional information that we attached to show errors. For example,
BAD_FIELD will have a field: 'xx' indicating which field is at fault.
ALREADY_EXISTS has information on which domain or port caused a problem.
The advantage here is we can drop all these error codes that are
specific to each model code.
4. Maybe some day, we can remove all these error classes and have only
one generic class. AppsError right now is pretty generic already. We can
use that error code everywhere... No need to translate errors also
everywhere.
5. Finally, in the router code, I have this function toHttpError (in
apps.js) which is also so much cleaner than what we have now. We keep
writing the same stuff over and over.
App operations can only be done in 'installed' or 'error' state.
If some other operation is in progress, you have to cancel it first.
This guarantees that the old app command got killed.
This option is now obsolete in the standards and browsers are complaining.
This needs to move to be a CSP header but this is hard to do from outside
the app (since it has to be 'merged' with the app's existing CSP).
fixes#596