mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-30 16:14:11 +00:00
Remove unnecessary exports from host-config
This limits the host-config interface to necessary methods only Signed-off-by: Christina Ying Wang <christina@balena.io>
This commit is contained in:
parent
53f5641ef1
commit
f99ccb58c6
@ -10,7 +10,7 @@ import * as hostConfig from '../host-config';
|
|||||||
import type {
|
import type {
|
||||||
HostConfiguration,
|
HostConfiguration,
|
||||||
LegacyHostConfiguration,
|
LegacyHostConfiguration,
|
||||||
} from '../host-config';
|
} from '../host-config/types';
|
||||||
import * as applicationManager from '../compose/application-manager';
|
import * as applicationManager from '../compose/application-manager';
|
||||||
import type { CompositionStepAction } from '../compose/composition-steps';
|
import type { CompositionStepAction } from '../compose/composition-steps';
|
||||||
import { generateStep } from '../compose/composition-steps';
|
import { generateStep } from '../compose/composition-steps';
|
||||||
|
@ -12,17 +12,14 @@ import { pathOnRoot } from '../lib/host-utils';
|
|||||||
import log from '../lib/supervisor-console';
|
import log from '../lib/supervisor-console';
|
||||||
import * as updateLock from '../lib/update-lock';
|
import * as updateLock from '../lib/update-lock';
|
||||||
|
|
||||||
export * from './proxy';
|
|
||||||
export * from './types';
|
|
||||||
|
|
||||||
const hostnamePath = pathOnRoot('/etc/hostname');
|
const hostnamePath = pathOnRoot('/etc/hostname');
|
||||||
|
|
||||||
export async function readHostname() {
|
async function readHostname() {
|
||||||
const hostnameData = await fs.readFile(hostnamePath, 'utf-8');
|
const hostnameData = await fs.readFile(hostnamePath, 'utf-8');
|
||||||
return hostnameData.trim();
|
return hostnameData.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setHostname(val: string) {
|
async function setHostname(val: string) {
|
||||||
let hostname = val;
|
let hostname = val;
|
||||||
// If hostname is an empty string, return first 7 digits of device uuid
|
// If hostname is an empty string, return first 7 digits of device uuid
|
||||||
if (!val) {
|
if (!val) {
|
||||||
@ -59,7 +56,7 @@ export function parse(
|
|||||||
throw new Error('Could not parse host config input to a valid format');
|
throw new Error('Could not parse host config input to a valid format');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function patchProxy(
|
function patchProxy(
|
||||||
currentConf: RedsocksConfig,
|
currentConf: RedsocksConfig,
|
||||||
inputConf: Partial<{
|
inputConf: Partial<{
|
||||||
redsocks: Partial<ProxyConfig>;
|
redsocks: Partial<ProxyConfig>;
|
||||||
@ -123,10 +120,12 @@ export async function patch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function get(): Promise<HostConfiguration> {
|
export async function get(): Promise<HostConfiguration> {
|
||||||
|
const proxy = await readProxy();
|
||||||
return {
|
return {
|
||||||
network: {
|
network: {
|
||||||
hostname: await readHostname(),
|
hostname: await readHostname(),
|
||||||
proxy: await readProxy(),
|
// Only return proxy if readProxy is not undefined
|
||||||
|
...(proxy && { proxy }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ async function restartProxyServices() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readNoProxy(): Promise<string[]> {
|
async function readNoProxy(): Promise<string[]> {
|
||||||
try {
|
try {
|
||||||
const noProxy = await readFromBoot(noProxyPath, 'utf-8')
|
const noProxy = await readFromBoot(noProxyPath, 'utf-8')
|
||||||
// Prevent empty newline from being reported as a noProxy address
|
// Prevent empty newline from being reported as a noProxy address
|
||||||
@ -238,7 +238,7 @@ export async function readNoProxy(): Promise<string[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setNoProxy(list: Nullable<string[]>) {
|
async function setNoProxy(list: Nullable<string[]>) {
|
||||||
const current = await readNoProxy();
|
const current = await readNoProxy();
|
||||||
if (!list || !Array.isArray(list) || !list.length) {
|
if (!list || !Array.isArray(list) || !list.length) {
|
||||||
await unlinkAll(noProxyPath);
|
await unlinkAll(noProxyPath);
|
||||||
|
@ -7,7 +7,6 @@ import { stub } from 'sinon';
|
|||||||
import * as fs from 'fs/promises';
|
import * as fs from 'fs/promises';
|
||||||
|
|
||||||
import { get, patch } from '~/src/host-config';
|
import { get, patch } from '~/src/host-config';
|
||||||
import * as hostConfig from '~/src/host-config';
|
|
||||||
import * as config from '~/src/config';
|
import * as config from '~/src/config';
|
||||||
import * as applicationManager from '~/src/compose/application-manager';
|
import * as applicationManager from '~/src/compose/application-manager';
|
||||||
import type { InstancedAppState } from '~/src/compose/types';
|
import type { InstancedAppState } from '~/src/compose/types';
|
||||||
@ -83,96 +82,6 @@ describe('host-config', () => {
|
|||||||
(applicationManager.getCurrentApps as SinonStub).restore();
|
(applicationManager.getCurrentApps as SinonStub).restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('hostname', () => {
|
|
||||||
it('reads hostname', async () => {
|
|
||||||
expect(await hostConfig.readHostname()).to.equal('deadbeef');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets hostname', async () => {
|
|
||||||
await hostConfig.setHostname('test');
|
|
||||||
expect(await config.get('hostname')).to.equal('test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets hostname to first 7 characters of UUID if empty', async () => {
|
|
||||||
await config.set({ uuid: '1234567' });
|
|
||||||
await hostConfig.setHostname('');
|
|
||||||
expect(await config.get('hostname')).to.equal('1234567');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('noProxy', () => {
|
|
||||||
it('reads IPs to exclude from proxy', async () => {
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal([
|
|
||||||
'152.10.30.4',
|
|
||||||
'253.1.1.0/16',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets IPs to exclude from proxy', async () => {
|
|
||||||
await hostConfig.setNoProxy(['balena.io', '1.1.1.1']);
|
|
||||||
expect(await fs.readFile(noProxy, 'utf-8')).to.equal(
|
|
||||||
'balena.io\n1.1.1.1',
|
|
||||||
);
|
|
||||||
await hostConfig.setNoProxy(['balena.io', '2.2.2.2']);
|
|
||||||
expect(await fs.readFile(noProxy, 'utf-8')).to.equal(
|
|
||||||
'balena.io\n2.2.2.2',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns whether noProxy was changed', async () => {
|
|
||||||
// Set initial no_proxy as empty
|
|
||||||
await hostConfig.setNoProxy([]);
|
|
||||||
|
|
||||||
// Change no_proxy
|
|
||||||
expect(await hostConfig.setNoProxy(['balena.io', '1.1.1.1'])).to.be.true;
|
|
||||||
expect(await hostConfig.readNoProxy())
|
|
||||||
.to.deep.include.members(['balena.io', '1.1.1.1'])
|
|
||||||
.and.have.lengthOf(2);
|
|
||||||
|
|
||||||
// Change no_proxy to same value
|
|
||||||
expect(await hostConfig.setNoProxy(['1.1.1.1', 'balena.io'])).to.be.false;
|
|
||||||
expect(await hostConfig.readNoProxy())
|
|
||||||
.to.deep.include.members(['balena.io', '1.1.1.1'])
|
|
||||||
.and.have.lengthOf(2);
|
|
||||||
|
|
||||||
// Remove a value
|
|
||||||
expect(await hostConfig.setNoProxy(['1.1.1.1'])).to.be.true;
|
|
||||||
expect(await hostConfig.readNoProxy())
|
|
||||||
.to.deep.include.members(['1.1.1.1'])
|
|
||||||
.and.have.lengthOf(1);
|
|
||||||
|
|
||||||
// Add a value
|
|
||||||
expect(await hostConfig.setNoProxy(['2.2.2.2', '1.1.1.1'])).to.be.true;
|
|
||||||
expect(await hostConfig.readNoProxy())
|
|
||||||
.to.deep.include.members(['2.2.2.2', '1.1.1.1'])
|
|
||||||
.and.have.lengthOf(2);
|
|
||||||
|
|
||||||
// Remove no_proxy
|
|
||||||
expect(await hostConfig.setNoProxy([])).to.be.true;
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removes no_proxy file if empty or invalid', async () => {
|
|
||||||
// Set initial no_proxy
|
|
||||||
await hostConfig.setNoProxy(['2.2.2.2']);
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal(['2.2.2.2']);
|
|
||||||
|
|
||||||
// Set to empty array
|
|
||||||
await hostConfig.setNoProxy([]);
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal([]);
|
|
||||||
expect(await fs.readdir(proxyBase)).to.not.have.members(['no_proxy']);
|
|
||||||
|
|
||||||
// Reset initial no_proxy
|
|
||||||
await hostConfig.setNoProxy(['2.2.2.2']);
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal(['2.2.2.2']);
|
|
||||||
|
|
||||||
// Set to invalid value
|
|
||||||
await hostConfig.setNoProxy(null as any);
|
|
||||||
expect(await hostConfig.readNoProxy()).to.deep.equal([]);
|
|
||||||
expect(await fs.readdir(proxyBase)).to.not.have.members(['no_proxy']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('reads proxy configs and hostname', async () => {
|
it('reads proxy configs and hostname', async () => {
|
||||||
const { network } = await get();
|
const { network } = await get();
|
||||||
expect(network).to.have.property('hostname', 'deadbeef');
|
expect(network).to.have.property('hostname', 'deadbeef');
|
||||||
@ -204,10 +113,10 @@ describe('host-config', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await patch({ network: { proxy: {} } }, true);
|
await patch({ network: { proxy: {} } }, true);
|
||||||
expect(await hostConfig.readProxy()).to.be.undefined;
|
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
expect.fail(`Expected hostConfig.patch to not throw, but got ${e}`);
|
expect.fail(`Expected hostConfig.patch to not throw, but got ${e}`);
|
||||||
}
|
}
|
||||||
|
expect(await get()).to.deep.equal({ network: { hostname: 'deadbeef' } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('patches hostname regardless of update locks', async () => {
|
it('patches hostname regardless of update locks', async () => {
|
||||||
@ -279,7 +188,7 @@ describe('host-config', () => {
|
|||||||
it('patches proxy to empty if input is empty', async () => {
|
it('patches proxy to empty if input is empty', async () => {
|
||||||
await patch({ network: { proxy: {} } });
|
await patch({ network: { proxy: {} } });
|
||||||
const { network } = await get();
|
const { network } = await get();
|
||||||
expect(network).to.have.property('proxy', undefined);
|
expect(network).to.not.have.property('proxy');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keeps current proxy if input is invalid', async () => {
|
it('keeps current proxy if input is invalid', async () => {
|
||||||
@ -341,7 +250,7 @@ describe('host-config', () => {
|
|||||||
it('patches redsocks.conf to be empty if prompted', async () => {
|
it('patches redsocks.conf to be empty if prompted', async () => {
|
||||||
await patch({ network: { proxy: {} } });
|
await patch({ network: { proxy: {} } });
|
||||||
const { network } = await get();
|
const { network } = await get();
|
||||||
expect(network).to.have.property('proxy', undefined);
|
expect(network).to.not.have.property('proxy');
|
||||||
expect(await fs.readdir(proxyBase)).to.not.have.members([
|
expect(await fs.readdir(proxyBase)).to.not.have.members([
|
||||||
'redsocks.conf',
|
'redsocks.conf',
|
||||||
'no_proxy',
|
'no_proxy',
|
||||||
|
@ -3,8 +3,8 @@ import { stripIndent } from 'common-tags';
|
|||||||
import type { SinonStub } from 'sinon';
|
import type { SinonStub } from 'sinon';
|
||||||
|
|
||||||
import * as hostConfig from '~/src/host-config';
|
import * as hostConfig from '~/src/host-config';
|
||||||
import { RedsocksConf } from '~/src/host-config';
|
import { RedsocksConf } from '~/src/host-config/proxy';
|
||||||
import type { RedsocksConfig, ProxyConfig } from '~/src/host-config';
|
import type { RedsocksConfig, ProxyConfig } from '~/src/host-config/types';
|
||||||
import log from '~/lib/supervisor-console';
|
import log from '~/lib/supervisor-console';
|
||||||
|
|
||||||
describe('RedsocksConf', () => {
|
describe('RedsocksConf', () => {
|
||||||
@ -379,57 +379,6 @@ describe('RedsocksConf', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('src/host-config', () => {
|
describe('src/host-config', () => {
|
||||||
describe('patchProxy', () => {
|
|
||||||
it('patches RedsocksConfig with new values', () => {
|
|
||||||
const current = {
|
|
||||||
redsocks: {
|
|
||||||
type: 'socks5',
|
|
||||||
ip: 'example.org',
|
|
||||||
port: 1080,
|
|
||||||
login: '"foo"',
|
|
||||||
password: '"bar"',
|
|
||||||
},
|
|
||||||
} as RedsocksConfig;
|
|
||||||
const input = {
|
|
||||||
redsocks: {
|
|
||||||
type: 'http-connect',
|
|
||||||
ip: 'test.balena.io',
|
|
||||||
},
|
|
||||||
} as any;
|
|
||||||
const patched = hostConfig.patchProxy(current, input);
|
|
||||||
expect(patched).to.deep.equal({
|
|
||||||
redsocks: {
|
|
||||||
// Patched fields are updated
|
|
||||||
type: 'http-connect',
|
|
||||||
ip: 'test.balena.io',
|
|
||||||
// Unpatched fields retain their original values
|
|
||||||
port: 1080,
|
|
||||||
login: '"foo"',
|
|
||||||
password: '"bar"',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns empty RedsocksConfig if redsocks config block is empty or invalid', () => {
|
|
||||||
const current: RedsocksConfig = {
|
|
||||||
redsocks: {
|
|
||||||
type: 'socks5',
|
|
||||||
ip: 'example.org',
|
|
||||||
port: 1080,
|
|
||||||
login: '"foo"',
|
|
||||||
password: '"bar"',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(hostConfig.patchProxy(current, { redsocks: {} })).to.deep.equal(
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
hostConfig.patchProxy(current, { redsocks: true } as any),
|
|
||||||
).to.deep.equal({});
|
|
||||||
expect(hostConfig.patchProxy(current, {})).to.deep.equal({});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parse', () => {
|
describe('parse', () => {
|
||||||
it('parses valid HostConfiguration', () => {
|
it('parses valid HostConfiguration', () => {
|
||||||
const conf = {
|
const conf = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user