We were not allowing newlines previously by virtue of the regex not
allowing them. The docker daemon and supervisor handling code both
support them, so we allow them in the parsing code too.
Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
We were validating the input configuration values by coercing them to
the correct type, and then using the initial value to be saved (which
currently is always converted to a string).
We now use the coerced value as the actual value we will store, and more
importantly emit. This means that the config.on('change' ...) calls will
always be properly typed, which before this change was not a guarantee
that we could make.
Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
Adjacent ports are always grouped together by docker when reporting the
container state (from an inspect), so adjacent ports defined in the
compose file would not match as they would not have been normalized.
We make sure to always normalize the input port configuration, so that
it will match the docker output (if it should).
We also don't sort in the fromComposePorts function anymore as that is
handled by the normalize function.
Closes: #897
Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
In the original implementation it was possible that the delete did not
wait for the kill step to be finished, so it would not be deleted.
We seperate this process into two steps, to allow for the container to
have stopped before proceeding.
Change-type: patch
Closes: #841
Signed-off-by: Cameron Diver <cameron@balena.io>
We define the type for each config value, and validate the data when
retrieving and setting it.
Change-type: minor
Signed-off-by: Cameron Diver <cameron@balena.io>
Docker always returns ports in ascending order, so if they aren't
specified like that in the compose, a restart loop would occur. This
patch changes the port maps to be stored in ascending order, based on
an alphabetical sort of the internalStart port (not taking into account
the protocol). This is the same as how Docker returns them, so they will
match, regardless of input form.
Change-type: patch
Closes: #824
Signed-off-by: Cameron Diver <cameron@balena.io>
Also change the return format of ApplicationManager.getStatus(), which
does not conform to the above.
Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
Up to now, there was a slim but non-zero chance that an image would be downloaded between the call to `@getTarget` inside deviceState
(which gets the target state and creates Service objects using information from available images), and the call to
`@images.getAvailable` in ApplicationManager (which is used to determine whether we should keep waiting for a download or start the
service). If this race condition happened, then the ApplicationManager would infer that a service was ready to be started (because
the image appears as available), but would have incomplete information about the service because the image wasn't available when
the Service object was created. The result would be that the service would be started, and then immediately on the next applyTarget
the ApplicationManager would try to kill it and restart it to update it with the complete information from the image.
This patch changes this behavior by ensuring that all of the additional information about the current state, which includes available images,
is gathered *before* building the current and target states that we compare. This means that if the image is downloaded after the call to getAvailable, the Service might be constructed with all the information about the image, but it won't be started until the next pass, because ApplicationManager will treat it as still downloading.
Change-type: patch
Signed-off-by: Pablo Carranza Velez <pablo@balena.io>
We also replace a createTableIfNotExists in the migrations with hasTable then createTable, to
avoid a warning message about it being not recommended.
Change-type: patch
Signed-off-by: Pablo Carranza Velez <pablo@balena.io>
The move from pure CoffeeScript to TypeScript has brought a
few changes to the way transpiling happens. Previously, through
serendipity, the way `startIPAddressUpdate` was called worked
because of the binding convention pre-transpiling.
However, with the move to TypeScript, this has altered and
the assumption that a lack of parentheses would call the
method before supplying a callback into the returned function
is incorrect. The method must be specifically called first.
Connects-to: #836
Change-type: patch
Signed-off-by: Heds Simons <heds@balena.io>
When updating from old supervisors (<7.0.0), we've been so far using a fake id 1 for serviceId, imageId
and releaseId since these were not available in the old supervisor. This causes problems when the supervisor
tries to report these values to the API. Moreover, the app from the legacy supervisor has an image URL
that doesn't include the content hash - this causes the supervisor to believe the image is not really downloaded
and try to fetch it again.
To fix these issues, we add a request to the API when the supervisor starts up and detects that there's a legacy
app that needs to be normalised. We fetch the appropriate release, and use it to populate the resource ids
and the updated image URL.
This should avoid the unnecessary image download, and errors reporting target state after an update.
Change-type: patch
Signed-off-by: Pablo Carranza Velez <pablo@balena.io>
Now you can either pass a serviceName or imageId to restart a specific
service, which is much easier from a device container.
Change-type: minor
Signed-off-by: Cameron Diver <cameron@balena.io>