Skip to content

Commit

Permalink
Add device startservice and stopservice commands
Browse files Browse the repository at this point in the history
Change-type: minor
  • Loading branch information
mlveggo authored and otaviojacobi committed Oct 27, 2023
1 parent 1ffa8d3 commit 8222159
Show file tree
Hide file tree
Showing 6 changed files with 368 additions and 2 deletions.
2 changes: 2 additions & 0 deletions automation/capitanodoc/capitanodoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ const capitanoDoc = {
'build/commands/device/restart.js',
'build/commands/device/rm.js',
'build/commands/device/shutdown.js',
'build/commands/device/startservice.js',
'build/commands/device/stopservice.js',
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion completion/_balena
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ _balena() {
app_cmds=( create )
block_cmds=( create )
config_cmds=( generate inject read reconfigure write )
device_cmds=( deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet )
device_cmds=( deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown startservice stopservice track-fleet )
devices_cmds=( supported )
env_cmds=( add rename rm )
fleet_cmds=( create pin purge rename restart rm track-latest )
Expand Down
2 changes: 1 addition & 1 deletion completion/balena-completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ _balena_complete()
app_cmds="create"
block_cmds="create"
config_cmds="generate inject read reconfigure write"
device_cmds="deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown track-fleet"
device_cmds="deactivate identify init local-mode move os-update pin public-url purge reboot register rename restart rm shutdown startservice stopservice track-fleet"
devices_cmds="supported"
env_cmds="add rename rm"
fleet_cmds="create pin purge rename restart rm track-latest"
Expand Down
54 changes: 54 additions & 0 deletions docs/balena-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ are encouraged to regularly update the balena CLI to the latest version.
- [device restart <uuid>](#device-restart-uuid)
- [device rm <uuid(s)>](#device-rm-uuid-s)
- [device shutdown <uuid>](#device-shutdown-uuid)
- [device startservice <uuid>](#device-startservice-uuid)
- [device stopservice <uuid>](#device-stopservice-uuid)

- Releases

Expand Down Expand Up @@ -1157,6 +1159,58 @@ the uuid of the device to shutdown

force action if the update lock is set

## device startservice <uuid>

Start containers on a device.
If the --service flag is provided, then only those services' containers
will be started.

Multiple devices and services may be specified with a comma-separated list
of values (no spaces).

Examples:

$ balena device startservice 23c73a1 --service myService
$ balena device startservice 23c73a1 -s myService1,myService2

### Arguments

#### UUID

comma-separated list (no blank spaces) of device UUIDs to start

### Options

#### -s, --service SERVICE

comma-separated list (no blank spaces) of service names to start

## device stopservice <uuid>

Stop containers on a device.
If the --service flag is provided, then only those services' containers
will be stopped.

Multiple devices and services may be specified with a comma-separated list
of values (no spaces).

Examples:

$ balena device stopservice 23c73a1 --service myService
$ balena device stopservice 23c73a1 -s myService1,myService2

### Arguments

#### UUID

comma-separated list (no blank spaces) of device UUIDs to stop

### Options

#### -s, --service SERVICE

comma-separated list (no blank spaces) of service names to stop

# Releases

## releases <fleet>
Expand Down
155 changes: 155 additions & 0 deletions lib/commands/device/startservice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/**
* @license
* Copyright 2016-2020 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Flags, Args } from '@oclif/core';
import Command from '../../command';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import type {
BalenaSDK,
DeviceWithServiceDetails,
CurrentServiceWithCommit,
} from 'balena-sdk';

export default class DeviceStartServiceCmd extends Command {
public static description = stripIndent`
Start containers on a device.
Start containers on a device.
If the --service flag is provided, then only those services' containers
will be started.
Multiple devices and services may be specified with a comma-separated list
of values (no spaces).
`;
public static examples = [
'$ balena device startservice 23c73a1 --service myService',
'$ balena device startservice 23c73a1 -s myService1,myService2',
];

public static args = {
uuid: Args.string({
description:
'comma-separated list (no blank spaces) of device UUIDs to start',
required: true,
}),
};

public static usage = 'device startservice <uuid>';

public static flags = {
service: Flags.string({
description:
'comma-separated list (no blank spaces) of service names to start',
char: 's',
}),
help: cf.help,
};

public static authenticated = true;

public async run() {
const { args: params, flags: options } = await this.parse(
DeviceStartServiceCmd,
);

const balena = getBalenaSdk();
const ux = getCliUx();

const deviceUuids = params.uuid.split(',');
const serviceNames = options.service?.split(',');

// Iterate sequentially through deviceUuids.
// We may later want to add a batching feature,
// so that n devices are processed in parallel
for (const uuid of deviceUuids) {
ux.action.start(`Starting services on device ${uuid}`);
if (serviceNames) {
await this.startServices(balena, uuid, serviceNames);
}
ux.action.stop();
}
}

async startServices(
balena: BalenaSDK,
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError, instanceOf } = await import('../../errors');
const { getExpandedProp } = await import('../../utils/pine');

// Get device
let device: DeviceWithServiceDetails<CurrentServiceWithCommit>;
try {
device = await balena.models.device.getWithServiceDetails(deviceUuid, {
$expand: {
is_running__release: { $select: 'commit' },
},
});
} catch (e) {
const { BalenaDeviceNotFound } = await import('balena-errors');
if (instanceOf(e, BalenaDeviceNotFound)) {
throw new ExpectedError(`Device ${deviceUuid} not found.`);
} else {
throw e;
}
}

const activeRelease = getExpandedProp(device.is_running__release, 'commit');

// Check specified services exist on this device before startinganything
serviceNames.forEach((service) => {
if (!device.current_services[service]) {
throw new ExpectedError(
`Service ${service} not found on device ${deviceUuid}.`,
);
}
});

// Start services
const startPromises: Array<Promise<void>> = [];
for (const serviceName of serviceNames) {
const service = device.current_services[serviceName];
// Each service is an array of `CurrentServiceWithCommit`
// because when service is updating, it will actually hold 2 services
// Target commit matching `device.is_running__release`
const serviceContainer = service.find((s) => {
return s.commit === activeRelease;
});

if (serviceContainer) {
startPromises.push(
balena.models.device.startService(
deviceUuid,
serviceContainer.image_id,
),
);
}
}

try {
await Promise.all(startPromises);
} catch (e) {
if (e.message.toLowerCase().includes('no online device')) {
throw new ExpectedError(`Device ${deviceUuid} is not online.`);
} else {
throw e;
}
}
}
}
Loading

0 comments on commit 8222159

Please sign in to comment.