159 lines
4.3 KiB
Dart
159 lines
4.3 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:podman/podman.dart';
|
|
|
|
Future<void> main(List<String> args) async {
|
|
if (args.contains('--help') || args.contains('-h')) {
|
|
_printUsage();
|
|
return;
|
|
}
|
|
|
|
final name =
|
|
_readOption(args, 'name') ?? (args.isNotEmpty ? args.first : null);
|
|
final rawValue = _readOption(args, 'value');
|
|
final filePath = _readOption(args, 'file');
|
|
final driver = _readOption(args, 'driver');
|
|
final showSecret = args.contains('--show-secret');
|
|
final cleanup = args.contains('--cleanup');
|
|
final replace = args.contains('--replace');
|
|
final ignore = args.contains('--ignore');
|
|
|
|
if (name == null || name.isEmpty) {
|
|
stderr.writeln('Missing secret name.');
|
|
_printUsage();
|
|
exitCode = 64;
|
|
return;
|
|
}
|
|
|
|
final value = await _resolveSecretValue(
|
|
rawValue: rawValue,
|
|
filePath: filePath,
|
|
);
|
|
if (value == null || value.isEmpty) {
|
|
stderr.writeln(
|
|
'Provide a secret value via --value, --file, or PODMAN_EXAMPLE_SECRET.',
|
|
);
|
|
_printUsage();
|
|
exitCode = 64;
|
|
return;
|
|
}
|
|
|
|
final labels = _readKeyValueOptions(args, 'label');
|
|
final driverOptions = _readKeyValueOptions(args, 'driver-opt');
|
|
|
|
final client = PodmanClient();
|
|
try {
|
|
final created = await client.createSecret(
|
|
SecretCreateOptions(
|
|
name: name,
|
|
data: value,
|
|
driver: driver,
|
|
labels: labels,
|
|
driverOptions: driverOptions,
|
|
replace: replace,
|
|
ignore: ignore,
|
|
),
|
|
);
|
|
|
|
print('Created/updated secret "$name" with id ${created.id}.');
|
|
|
|
final exists = await client.secretExists(name);
|
|
print('Secret exists: $exists');
|
|
|
|
final details = await client.inspectSecret(name, showSecret: showSecret);
|
|
print('Driver: ${details.driver.isEmpty ? 'unknown' : details.driver}');
|
|
print('Labels: ${details.labels.isEmpty ? '(none)' : details.labels}');
|
|
print('Updated: ${details.updatedAt?.toIso8601String() ?? 'unknown'}');
|
|
|
|
if (showSecret) {
|
|
print('Secret payload length: ${details.secretData.length}');
|
|
}
|
|
|
|
final allSecrets = await client.listSecrets();
|
|
print('Total secrets visible to this user: ${allSecrets.length}');
|
|
|
|
if (cleanup) {
|
|
await client.removeSecret(name, ignoreMissing: true);
|
|
print('Removed secret "$name" (--cleanup).');
|
|
}
|
|
} finally {
|
|
await client.close();
|
|
}
|
|
}
|
|
|
|
Future<String?> _resolveSecretValue({
|
|
required String? rawValue,
|
|
required String? filePath,
|
|
}) async {
|
|
if (rawValue != null) {
|
|
return rawValue;
|
|
}
|
|
|
|
if (filePath != null && filePath.isNotEmpty) {
|
|
final file = File(filePath);
|
|
if (!await file.exists()) {
|
|
stderr.writeln('Secret file not found: $filePath');
|
|
return null;
|
|
}
|
|
return file.readAsString();
|
|
}
|
|
|
|
return Platform.environment['PODMAN_EXAMPLE_SECRET'];
|
|
}
|
|
|
|
String? _readOption(List<String> args, String name) {
|
|
final prefix = '--$name=';
|
|
for (final arg in args) {
|
|
if (arg.startsWith(prefix)) {
|
|
return arg.substring(prefix.length);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Map<String, String> _readKeyValueOptions(List<String> args, String name) {
|
|
final prefix = '--$name=';
|
|
final output = <String, String>{};
|
|
|
|
for (final arg in args) {
|
|
if (!arg.startsWith(prefix)) {
|
|
continue;
|
|
}
|
|
final raw = arg.substring(prefix.length);
|
|
final index = raw.indexOf('=');
|
|
if (index <= 0 || index == raw.length - 1) {
|
|
continue;
|
|
}
|
|
|
|
final key = raw.substring(0, index);
|
|
final value = raw.substring(index + 1);
|
|
output[key] = value;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
void _printUsage() {
|
|
print('''
|
|
Secrets workflow example
|
|
|
|
Usage:
|
|
dart run example/secrets_workflow_example.dart --name=<secret-name> [options]
|
|
|
|
Options:
|
|
--name=<name> Secret name (required)
|
|
--value=<plaintext> Secret payload value
|
|
--file=<path> Read secret payload from file
|
|
--driver=<driver> Optional driver (for example: file, pass)
|
|
--label=<k=v> Add label (repeatable)
|
|
--driver-opt=<k=v> Add driver option (repeatable)
|
|
--replace Replace existing secret with same name
|
|
--ignore Ignore creation conflict errors
|
|
--show-secret Request and display secret payload length
|
|
--cleanup Remove secret at the end of the run
|
|
--help, -h Show this help
|
|
|
|
Environment fallback:
|
|
PODMAN_EXAMPLE_SECRET Used when --value/--file are not set
|
|
''');
|
|
}
|