run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<void> run() async {
final args = argResults!;
final rest = args.rest;
if (rest.isEmpty) {
throw CliError(
'usage: preset apply <preset.json|preset-id> [<node>] '
'[--label env=prod | --all]',
);
}
// A path if it exists on disk, otherwise the id of a preset saved on the Hub.
// The saved form is the one worth using: a file is whatever copy *this*
// caller happens to have, while an id is the one everybody agrees on.
final source = rest.first;
final file = File(source);
final inline = await file.exists()
? Preset.fromJson(
(jsonDecode(await file.readAsString()) as Map)
.cast<String, dynamic>(),
)
: null;
final client = _apiClientFrom(args);
try {
final nodes = await _selectNodes(
client,
args,
positional: rest.skip(1).toList(),
);
final async = args['async'] as bool;
await _fanOut(nodes, (node) async {
if (async) {
final operation = await client.applyPresetAsync(
node,
presetId: inline == null ? source : null,
preset: inline,
);
return 'dispatched — ops show ${operation.id}';
}
final reply = await client.applyPreset(
node,
presetId: inline == null ? source : null,
preset: inline,
);
final failed = reply.results.where((r) => !r.success).length;
final changed = reply.results.where((r) => r.changed).length;
return failed == 0
? 'applied ${reply.results.length} steps ($changed changed)'
: 'FAILED $failed/${reply.results.length} steps';
});
} finally {
client.close();
}
}