233 lines
7.1 KiB
Dart
233 lines
7.1 KiB
Dart
import 'package:podman/podman.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
import 'support/fake_podman_transport.dart';
|
|
|
|
void main() {
|
|
group('PodmanClient container API', () {
|
|
test('lists containers', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.get,
|
|
path: '/v5.0.0/libpod/containers/json',
|
|
queryParameters: const <String, List<String>>{
|
|
'all': <String>['true'],
|
|
},
|
|
responseBody: <Object?>[
|
|
<String, Object?>{
|
|
'Id': 'abc123',
|
|
'Image': 'hello-world:latest',
|
|
'Names': <String>['web'],
|
|
'State': 'running',
|
|
'Status': 'Up 4m',
|
|
},
|
|
],
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
final containers = await client.listContainers();
|
|
|
|
expect(containers, hasLength(1));
|
|
expect(containers.first.id, 'abc123');
|
|
expect(containers.first.image, 'hello-world:latest');
|
|
expect(containers.first.name, 'web');
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('creates and starts container via run', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/create',
|
|
queryParameters: const <String, List<String>>{
|
|
'name': <String>['web'],
|
|
},
|
|
body: const <String, Object?>{
|
|
'Image': 'docker.io/library/hello-world:latest',
|
|
},
|
|
statusCode: 201,
|
|
responseBody: const <String, Object?>{'Id': 'container-id-123'},
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/container-id-123/start',
|
|
statusCode: 204,
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
final id = await client.run(
|
|
const RunOptions(
|
|
image: 'docker.io/library/hello-world:latest',
|
|
name: 'web',
|
|
),
|
|
);
|
|
|
|
expect(id, 'container-id-123');
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('inspects container details', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.get,
|
|
path: '/v5.0.0/libpod/containers/web/json',
|
|
responseBody: <String, Object?>{
|
|
'Id': 'abc',
|
|
'Name': '/web',
|
|
'ImageName': 'hello-world:latest',
|
|
'State': <String, Object?>{'Status': 'running'},
|
|
'Config': <String, Object?>{
|
|
'Labels': <String, String>{'role': 'frontend'},
|
|
},
|
|
},
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
final details = await client.inspectContainer('web');
|
|
|
|
expect(details.id, 'abc');
|
|
expect(details.name, 'web');
|
|
expect(details.state, 'running');
|
|
expect(details.labels['role'], 'frontend');
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('containerExists returns false for missing container', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.get,
|
|
path: '/v5.0.0/libpod/containers/missing/exists',
|
|
statusCode: 404,
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
final exists = await client.containerExists('missing');
|
|
|
|
expect(exists, isFalse);
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('supports lifecycle operations', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/web/stop',
|
|
queryParameters: const <String, List<String>>{
|
|
't': <String>['10'],
|
|
},
|
|
statusCode: 204,
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/web/start',
|
|
statusCode: 204,
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/web/restart',
|
|
queryParameters: const <String, List<String>>{
|
|
't': <String>['5'],
|
|
},
|
|
statusCode: 204,
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.delete,
|
|
path: '/v5.0.0/libpod/containers/web',
|
|
queryParameters: const <String, List<String>>{
|
|
'force': <String>['true'],
|
|
'v': <String>['true'],
|
|
},
|
|
statusCode: 204,
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/prune',
|
|
statusCode: 200,
|
|
responseBody: const <String, Object?>{},
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
await client.stop('web', timeoutSeconds: 10);
|
|
await client.start('web');
|
|
await client.restart('web', timeoutSeconds: 5);
|
|
await client.removeContainer('web', force: true, removeVolumes: true);
|
|
await client.pruneContainers();
|
|
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('supports logs query options and log polling', () async {
|
|
final since = DateTime.utc(2026, 4, 6, 10, 0, 0);
|
|
final until = DateTime.utc(2026, 4, 6, 11, 0, 0);
|
|
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.get,
|
|
path: '/v5.0.0/libpod/containers/web/logs',
|
|
queryParameters: <String, List<String>>{
|
|
'stdout': <String>['true'],
|
|
'stderr': <String>['false'],
|
|
'timestamps': <String>['true'],
|
|
'since': <String>[since.toIso8601String()],
|
|
'until': <String>[until.toIso8601String()],
|
|
'tail': <String>['25'],
|
|
},
|
|
responseBody: 'log-one\n',
|
|
)
|
|
..enqueue(
|
|
method: HttpMethod.get,
|
|
path: '/v5.0.0/libpod/containers/web/logs',
|
|
queryParameters: <String, List<String>>{
|
|
'stdout': <String>['true'],
|
|
'stderr': <String>['true'],
|
|
'timestamps': <String>['true'],
|
|
'since': <String>[since.toIso8601String()],
|
|
'tail': <String>['10'],
|
|
},
|
|
responseBody: 'log-two\n',
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
final logs = await client.logs(
|
|
'web',
|
|
tail: 25,
|
|
since: since,
|
|
until: until,
|
|
timestamps: true,
|
|
stdout: true,
|
|
stderr: false,
|
|
);
|
|
expect(logs, 'log-one\n');
|
|
|
|
final chunk = await client
|
|
.watchLogs(
|
|
'web',
|
|
since: since,
|
|
tail: 10,
|
|
pollInterval: const Duration(days: 1),
|
|
reconnect: false,
|
|
)
|
|
.first;
|
|
expect(chunk, 'log-two\n');
|
|
|
|
transport.expectNoPending();
|
|
});
|
|
|
|
test('throws on unexpected API status', () async {
|
|
final transport = FakePodmanTransport()
|
|
..enqueue(
|
|
method: HttpMethod.post,
|
|
path: '/v5.0.0/libpod/containers/web/start',
|
|
statusCode: 500,
|
|
responseBody: const <String, Object?>{'message': 'boom'},
|
|
);
|
|
|
|
final client = PodmanClient(transport: transport);
|
|
|
|
await expectLater(
|
|
client.start('web'),
|
|
throwsA(isA<PodmanApiException>()),
|
|
);
|
|
});
|
|
});
|
|
}
|