feat(tsdocker): add multi-registry and multi-arch Docker build/push/pull manager, registry storage, Dockerfile handling, and new CLI commands
This commit is contained in:
91
ts/classes.dockerregistry.ts
Normal file
91
ts/classes.dockerregistry.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import * as plugins from './tsdocker.plugins.js';
|
||||
import { logger } from './tsdocker.logging.js';
|
||||
import type { IDockerRegistryOptions } from './interfaces/index.js';
|
||||
|
||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
});
|
||||
|
||||
/**
|
||||
* Represents a Docker registry with authentication capabilities
|
||||
*/
|
||||
export class DockerRegistry {
|
||||
public registryUrl: string;
|
||||
public username: string;
|
||||
public password: string;
|
||||
|
||||
constructor(optionsArg: IDockerRegistryOptions) {
|
||||
this.registryUrl = optionsArg.registryUrl;
|
||||
this.username = optionsArg.username;
|
||||
this.password = optionsArg.password;
|
||||
logger.log('info', `created DockerRegistry for ${this.registryUrl}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DockerRegistry instance from a pipe-delimited environment string
|
||||
* Format: "registryUrl|username|password"
|
||||
*/
|
||||
public static fromEnvString(envString: string): DockerRegistry {
|
||||
const dockerRegexResultArray = envString.split('|');
|
||||
if (dockerRegexResultArray.length !== 3) {
|
||||
logger.log('error', 'malformed docker env var...');
|
||||
throw new Error('malformed docker env var, expected format: registryUrl|username|password');
|
||||
}
|
||||
const registryUrl = dockerRegexResultArray[0].replace('https://', '').replace('http://', '');
|
||||
const username = dockerRegexResultArray[1];
|
||||
const password = dockerRegexResultArray[2];
|
||||
return new DockerRegistry({
|
||||
registryUrl: registryUrl,
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DockerRegistry from environment variables
|
||||
* Looks for DOCKER_REGISTRY, DOCKER_REGISTRY_USER, DOCKER_REGISTRY_PASSWORD
|
||||
* Or for a specific registry: DOCKER_REGISTRY_<NAME>, etc.
|
||||
*/
|
||||
public static fromEnv(registryName?: string): DockerRegistry | null {
|
||||
const prefix = registryName ? `DOCKER_REGISTRY_${registryName.toUpperCase()}_` : 'DOCKER_REGISTRY_';
|
||||
|
||||
const registryUrl = process.env[`${prefix}URL`] || process.env['DOCKER_REGISTRY'];
|
||||
const username = process.env[`${prefix}USER`] || process.env['DOCKER_REGISTRY_USER'];
|
||||
const password = process.env[`${prefix}PASSWORD`] || process.env['DOCKER_REGISTRY_PASSWORD'];
|
||||
|
||||
if (!registryUrl || !username || !password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DockerRegistry({
|
||||
registryUrl: registryUrl.replace('https://', '').replace('http://', ''),
|
||||
username,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in to the Docker registry
|
||||
*/
|
||||
public async login(): Promise<void> {
|
||||
if (this.registryUrl === 'docker.io') {
|
||||
await smartshellInstance.exec(`docker login -u ${this.username} -p ${this.password}`);
|
||||
logger.log('info', 'Logged in to standard docker hub');
|
||||
} else {
|
||||
await smartshellInstance.exec(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`);
|
||||
}
|
||||
logger.log('ok', `docker authenticated for ${this.registryUrl}!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out from the Docker registry
|
||||
*/
|
||||
public async logout(): Promise<void> {
|
||||
if (this.registryUrl === 'docker.io') {
|
||||
await smartshellInstance.exec('docker logout');
|
||||
} else {
|
||||
await smartshellInstance.exec(`docker logout ${this.registryUrl}`);
|
||||
}
|
||||
logger.log('info', `logged out from ${this.registryUrl}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user