mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-03-25 05:25:39 +00:00
Start a dependent if all dependencies are started
The previous behavior required that dependencies were running beefore starting the dependent service. This made it that services dependent on a one-shot service would not get started and goes against the default docker behavior. Depending on a service to be running will require the implementation of [long syntax depends_on](https://docs.docker.com/reference/compose-file/services/#long-syntax-1) and the condition `service_healthy`. Change-type: patch Closes: #2409
This commit is contained in:
parent
b8032edc04
commit
7764f98c9d
@ -921,19 +921,24 @@ class AppImpl implements App {
|
||||
volumePairs: Array<ChangingPair<Volume>>,
|
||||
servicePairs: Array<ChangingPair<Service>>,
|
||||
): boolean {
|
||||
// Firstly we check if a dependency is not already running (this is
|
||||
// Firstly we check if a dependency has already been started (this is
|
||||
// different to a dependency which is in the servicePairs below, as these
|
||||
// are services which are changing). We could have a dependency which is
|
||||
// starting up, but is not yet running.
|
||||
const depInstallingButNotRunning = _.some(this.services, (svc) => {
|
||||
const depCreatedButNotStarted = _.some(this.services, (svc) => {
|
||||
if (target.dependsOn?.includes(svc.serviceName)) {
|
||||
if (!svc.config.running) {
|
||||
if (
|
||||
svc.status === 'Installing' ||
|
||||
svc.startedAt == null ||
|
||||
svc.createdAt == null ||
|
||||
svc.startedAt < svc.createdAt
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (depInstallingButNotRunning) {
|
||||
if (depCreatedButNotStarted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ class ServiceImpl implements Service {
|
||||
public dockerImageId: string | null;
|
||||
public status: ServiceStatus;
|
||||
public createdAt: Date | null;
|
||||
public startedAt: Date | null;
|
||||
|
||||
private static configArrayFields: ServiceConfigArrayField[] = [
|
||||
'volumes',
|
||||
@ -476,6 +477,7 @@ class ServiceImpl implements Service {
|
||||
}
|
||||
|
||||
svc.createdAt = new Date(container.Created);
|
||||
svc.startedAt = new Date(container.State.StartedAt);
|
||||
svc.containerId = container.Id;
|
||||
svc.exitErrorMessage = container.State.Error;
|
||||
|
||||
|
@ -373,6 +373,7 @@ export interface Service {
|
||||
// from docker
|
||||
status: ServiceStatus;
|
||||
createdAt: Date | null;
|
||||
startedAt: Date | null;
|
||||
|
||||
hasNetwork(networkName: string): boolean;
|
||||
hasVolume(volumeName: string): boolean;
|
||||
|
@ -1128,11 +1128,20 @@ describe('compose/application-manager', () => {
|
||||
const { currentApps, availableImages, downloading, containerIdsByAppId } =
|
||||
createCurrentState({
|
||||
services: [
|
||||
await createService({
|
||||
image: 'dep-image',
|
||||
serviceName: 'dep',
|
||||
commit: 'new-release',
|
||||
}),
|
||||
await createService(
|
||||
{
|
||||
image: 'dep-image',
|
||||
serviceName: 'dep',
|
||||
commit: 'new-release',
|
||||
},
|
||||
{
|
||||
state: {
|
||||
createdAt: new Date(Date.now() - 5 * 1000),
|
||||
// Container was started 5 after creation
|
||||
startedAt: new Date(),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
networks: [DEFAULT_NETWORK],
|
||||
images: [
|
||||
|
@ -1458,7 +1458,14 @@ describe('compose/app', () => {
|
||||
services: [
|
||||
await createService(
|
||||
{ appId: 1, serviceName: 'dep' },
|
||||
{ state: { containerId: 'dep-id' } },
|
||||
{
|
||||
state: {
|
||||
containerId: 'dep-id',
|
||||
createdAt: new Date(Date.now() - 5 * 1000),
|
||||
// Container was started 5 after creation
|
||||
startedAt: new Date(),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
networks: [DEFAULT_NETWORK],
|
||||
@ -1475,7 +1482,7 @@ describe('compose/app', () => {
|
||||
.that.deep.includes({ serviceName: 'main' });
|
||||
});
|
||||
|
||||
it('should not start a container when it depends on a service that is not running', async () => {
|
||||
it('should not start a container when it depends on a service that has not been started yet', async () => {
|
||||
const current = createApp({
|
||||
services: [
|
||||
await createService(
|
||||
@ -1535,7 +1542,14 @@ describe('compose/app', () => {
|
||||
services: [
|
||||
await createService(
|
||||
{ appId: 1, serviceName: 'dep' },
|
||||
{ state: { containerId: 'dep-id' } },
|
||||
{
|
||||
state: {
|
||||
containerId: 'dep-id',
|
||||
createdAt: new Date(Date.now() - 5 * 1000),
|
||||
// Container was started 5 after creation
|
||||
startedAt: new Date(),
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
networks: [DEFAULT_NETWORK],
|
||||
|
Loading…
x
Reference in New Issue
Block a user