@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
88 lines (71 loc) • 3.71 kB
text/typescript
// SPDX-License-Identifier: Apache-2.0
import fs from 'node:fs/promises';
import path from 'node:path';
import {inject, injectable} from 'tsyringe-neo';
import {ContainerEngineClient} from './container-engine-client.js';
import {InjectTokens} from '../../core/dependency-injection/inject-tokens.js';
import {patchInject} from '../../core/dependency-injection/container-helper.js';
import {KindClient} from '../kind/kind-client.js';
import {ShellRunner} from '../../core/shell-runner.js';
import {type SoloLogger} from '../../core/logging/solo-logger.js';
import {DefaultKindClientBuilder} from '../kind/impl/default-kind-client-builder.js';
import {DependencyManager} from '../../core/dependency-managers/index.js';
import * as constants from '../../core/constants.js';
import {LoadImageArchiveOptionsBuilder} from '../kind/model/load-image-archive/load-image-archive-options-builder.js';
import {LoadImageArchiveOptions} from '../kind/model/load-image-archive/load-image-archive-options.js';
import {Architecture} from '../../business/utils/architecture.js';
()
export class DockerClient implements ContainerEngineClient {
private readonly shellRunner: ShellRunner;
public constructor(
(InjectTokens.KindBuilder) private readonly kindBuilder?: DefaultKindClientBuilder,
(InjectTokens.SoloLogger) private readonly logger?: SoloLogger,
(InjectTokens.DependencyManager) private readonly dependencyManager?: DependencyManager,
) {
this.kindBuilder = patchInject(kindBuilder, InjectTokens.KindBuilder, this.constructor.name);
this.logger = patchInject(logger, InjectTokens.SoloLogger, this.constructor.name);
this.dependencyManager = patchInject(dependencyManager, InjectTokens.DependencyManager, this.constructor.name);
this.shellRunner = new ShellRunner(this.logger);
}
public async pullImage(image: string): Promise<void> {
const platform: string = Architecture.getLinuxPlatform();
await this.shellRunner.run('docker', ['pull', '--platform', platform, image]);
}
public async saveImage(image: string, archivePath: string): Promise<void> {
await fs.mkdir(path.dirname(archivePath), {recursive: true});
const platform: string = Architecture.getLinuxPlatform();
await this.shellRunner.run('crane', ['pull', '--platform', platform, image, archivePath]);
}
public async loadImage(archivePath: string): Promise<void> {
await this.shellRunner.run('docker', ['load', '--input', archivePath]);
}
public async loadImageArchiveIntoCluster(archivePath: string, clusterReference?: string): Promise<void> {
const options: LoadImageArchiveOptions = LoadImageArchiveOptionsBuilder.builder()
.archivePath(archivePath)
.name(clusterReference)
.build();
const kindExecutable: string = await this.dependencyManager.getExecutable(constants.KIND);
const kindClient: KindClient = await this.kindBuilder.executable(kindExecutable).build(true);
await kindClient.loadImageArchive(archivePath, options);
}
public async removeImage(image: string): Promise<void> {
await this.shellRunner.run('docker', ['image', 'rm', image]);
}
public async listLoadedImagesInCluster(clusterName: string): Promise<readonly string[]> {
const nodeName: string = `${clusterName}-control-plane`;
const output: string[] = await this.shellRunner.run('docker', [
'exec',
'--privileged',
nodeName,
'ctr',
'--namespace=k8s.io',
'images',
'ls',
'-q',
]);
return output
.map((line): string => line.trim())
.filter((line): boolean => line.length > 0)
.filter((line): boolean => !line.startsWith('import-'));
}
}