@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
158 lines • 8.8 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import { expect } from 'chai';
import { after, before, describe, it } from 'mocha';
import each from 'mocha-each';
import fs from 'node:fs';
import path from 'node:path';
import sinon from 'sinon';
import { HelmDependencyManager } from '../../../../../src/core/dependency-managers/index.js';
import { getTestCacheDirectory, getTemporaryDirectory } from '../../../../test-utility.js';
import * as version from '../../../../../version.js';
import { PathEx } from '../../../../../src/business/utils/path-ex.js';
import { OperatingSystem } from '../../../../../src/business/utils/operating-system.js';
import { InjectTokens } from '../../../../../src/core/dependency-injection/inject-tokens.js';
import { container } from 'tsyringe-neo';
import { platform } from 'node:process';
import * as constants from '../../../../../src/core/constants.js';
describe('HelmDependencyManager', () => {
const originalPlatform = platform;
const temporaryDirectory = PathEx.join(getTemporaryDirectory(), 'bin');
const installationDirectory = getTemporaryDirectory();
const originalInstallationDirectory = container.resolve(InjectTokens.HelmInstallationDirectory);
let sandbox;
before(() => {
fs.mkdirSync(temporaryDirectory);
sandbox = sinon.createSandbox();
container.register(InjectTokens.HelmInstallationDirectory, { useValue: installationDirectory });
});
after(() => {
if (fs.existsSync(temporaryDirectory)) {
fs.rmSync(temporaryDirectory, { recursive: true });
}
if (fs.existsSync(installationDirectory)) {
fs.rmSync(installationDirectory, { recursive: true });
}
container.register(InjectTokens.HelmInstallationDirectory, { useValue: originalInstallationDirectory });
});
afterEach(() => {
container.register(InjectTokens.OsPlatform, { useValue: originalPlatform });
sandbox.restore();
});
it('should return helm version', () => {
const helmDependencyManager = new HelmDependencyManager(undefined, undefined, temporaryDirectory, undefined, undefined);
expect(helmDependencyManager.getRequiredVersion()).to.equal(version.HELM_VERSION);
});
it('should be able to check when helm not installed', () => {
const helmDependencyManager = new HelmDependencyManager(undefined, undefined, temporaryDirectory, undefined, undefined);
expect(helmDependencyManager.isInstalledLocally()).not.to.be.ok;
});
it('should be able to check when helm is installed', async () => {
const helmDependencyManager = new HelmDependencyManager(undefined, undefined, temporaryDirectory, undefined, undefined);
// Create the local executable file for testing
const localPath = PathEx.join(temporaryDirectory, 'helm');
fs.writeFileSync(localPath, '');
expect(helmDependencyManager.isInstalledLocally()).to.be.ok;
});
describe('Helm Installation Tests', () => {
afterEach(() => {
container.register(InjectTokens.OsPlatform, { useValue: originalPlatform });
container.register(InjectTokens.HelmInstallationDirectory, { useValue: originalInstallationDirectory });
sandbox.restore();
if (fs.existsSync(temporaryDirectory)) {
fs.rmSync(temporaryDirectory, { recursive: true });
}
if (fs.existsSync(installationDirectory)) {
fs.rmSync(installationDirectory, { recursive: true });
}
});
each([
[OperatingSystem.OS_LINUX, 'x64'],
[OperatingSystem.OS_LINUX, 'amd64'],
[OperatingSystem.OS_WIN32, 'amd64'],
]).it('should be able to install helm base on %s and %s', async (osPlatform, osArch) => {
container.register(InjectTokens.OsPlatform, { useValue: osPlatform });
container.register(InjectTokens.HelmInstallationDirectory, { useValue: installationDirectory });
const helmDependencyManager = new HelmDependencyManager(undefined, undefined, installationDirectory, osArch, undefined);
if (fs.existsSync(temporaryDirectory)) {
fs.rmSync(temporaryDirectory, { recursive: true });
}
if (fs.existsSync(getTestCacheDirectory())) {
fs.rmSync(getTestCacheDirectory(), { recursive: true });
}
helmDependencyManager.uninstallLocal();
expect(helmDependencyManager.isInstalledLocally()).not.to.be.ok;
// Stub accessSync so the native PATH scan finds no global helm installation.
sandbox.stub(fs, 'accessSync').throws(Object.assign(new Error('ENOENT'), { code: 'ENOENT' }));
expect(await helmDependencyManager.install(getTestCacheDirectory())).to.be.true;
expect(helmDependencyManager.isInstalledLocally()).to.be.ok;
if (fs.existsSync(temporaryDirectory)) {
fs.rmSync(temporaryDirectory, { recursive: true });
}
});
});
describe('when helm is installed globally', () => {
let helmDependencyManager;
let runStub;
beforeEach(() => {
helmDependencyManager = new HelmDependencyManager(undefined, undefined, temporaryDirectory, process.arch, undefined);
helmDependencyManager.uninstallLocal();
runStub = sandbox.stub(helmDependencyManager, 'run');
});
afterEach(() => {
sandbox.restore();
});
it('should prefer the global installation if it meets the requirements', async () => {
// Point PATH at a fake directory and stub accessSync to make the native PATH
// scan discover a fake global helm binary without creating a real file.
const fakeGlobalBinDirectory = '/test-solo-global-bin';
const fakeGlobalHelmPath = `${fakeGlobalBinDirectory}/helm`;
const originalPath = process.env.PATH ?? '';
process.env.PATH = `${fakeGlobalBinDirectory}${path.delimiter}${originalPath}`;
sandbox.stub(fs, 'accessSync').callsFake((filePath) => {
if (String(filePath) === fakeGlobalHelmPath) {
return;
}
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
});
runStub.withArgs(`"${fakeGlobalHelmPath}" version --short`).resolves(['v4.1.3+gc94d381']);
try {
// @ts-expect-error TS2341: Property isInstalledGloballyAndMeetsRequirements is private
const result = await helmDependencyManager.isInstalledGloballyAndMeetsRequirements();
expect(result).to.be.true;
expect(await helmDependencyManager.install(getTestCacheDirectory())).to.be.true;
// Should not install locally since global installation meets requirements
expect(fs.existsSync(PathEx.join(temporaryDirectory, 'helm'))).to.be.not.ok;
// Should return global path since it meets requirements
expect(await helmDependencyManager.getExecutable()).to.equal(constants.HELM);
}
finally {
process.env.PATH = originalPath;
}
});
it('should install helm locally if the global installation does not meet the requirements', async () => {
const fakeGlobalBinDirectory = '/test-solo-global-bin';
const fakeGlobalHelmPath = `${fakeGlobalBinDirectory}/helm`;
const originalPath = process.env.PATH ?? '';
process.env.PATH = `${fakeGlobalBinDirectory}${path.delimiter}${originalPath}`;
sandbox.stub(fs, 'accessSync').callsFake((filePath) => {
if (String(filePath) === fakeGlobalHelmPath) {
return;
}
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
});
runStub.withArgs(`"${fakeGlobalHelmPath}" version --short`).resolves(['v0.1.0+gabcdef']);
try {
// @ts-expect-error TS2341: Property isInstalledGloballyAndMeetsRequirements is private
const result = await helmDependencyManager.isInstalledGloballyAndMeetsRequirements();
expect(result).to.be.false;
expect(await helmDependencyManager.install(getTestCacheDirectory())).to.be.true;
expect(fs.existsSync(PathEx.join(temporaryDirectory, 'helm'))).to.be.ok;
expect(await helmDependencyManager.getExecutable()).to.equal(constants.HELM);
}
finally {
process.env.PATH = originalPath;
}
});
});
});
//# sourceMappingURL=helm-dependency-manager.test.js.map