Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(hostRules): precalculate resolvedHost #9811

Merged
merged 4 commits into from May 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/manager/bundler/artifacts.spec.ts
Expand Up @@ -229,11 +229,11 @@ describe('bundler.updateArtifacts()', () => {
{
hostType: 'bundler',
hostName: 'gems.private.com',
resolvedHost: 'gems.private.com',
username: 'some-user',
password: 'some-password',
},
]);
bundlerHostRules.getDomain.mockReturnValue('gems.private.com');
bundlerHostRules.getAuthenticationHeaderValue.mockReturnValue(
'some-user:some-password'
);
Expand Down
3 changes: 1 addition & 2 deletions lib/manager/bundler/artifacts.ts
Expand Up @@ -19,7 +19,6 @@ import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
import {
findAllAuthenticatable,
getAuthenticationHeaderValue,
getDomain,
} from './host-rules';
import { getGemHome } from './utils';

Expand Down Expand Up @@ -56,7 +55,7 @@ async function getRubyConstraint(
function buildBundleHostVariable(hostRule: HostRule): Record<string, string> {
const varName =
hostConfigVariablePrefix +
getDomain(hostRule)
hostRule.resolvedHost
.split('.')
.map((term) => term.toUpperCase())
.join('__');
Expand Down
71 changes: 18 additions & 53 deletions lib/manager/bundler/host-rules.spec.ts
Expand Up @@ -5,47 +5,12 @@ import { add, clear } from '../../util/host-rules';
import {
findAllAuthenticatable,
getAuthenticationHeaderValue,
getDomain,
} from './host-rules';

describe(getName(), () => {
beforeEach(() => {
clear();
});
describe('getDomain()', () => {
it('returns the hostName if hostName is present', () => {
expect(
getDomain({
hostName: 'api.github.com',
})
).toEqual('api.github.com');
});
it('returns the domainName if domainName is present and hostName is not present', () => {
expect(
getDomain({
domainName: 'github.com',
})
).toEqual('github.com');
});
it('returns the hostName if hostName and domainName are present', () => {
expect(
getDomain({
hostName: 'api.github.com',
domainName: 'github.com',
})
).toEqual('api.github.com');
});
it('returns the baseUrl host if hostName and domainName are not present', () => {
expect(
getDomain({
baseUrl: 'https://github.com',
})
).toEqual('github.com');
});
it('returns undefined if hostName, domainName and baseUrl are not present', () => {
expect(getDomain({})).toBeNull();
});
});
describe('getAuthenticationHeaderValue()', () => {
it('returns the authentication header with the password', () => {
expect(
Expand Down Expand Up @@ -105,56 +70,56 @@ describe(getName(), () => {
delete hostRule.token;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
it('returns the hostRule if using domainName and password', () => {
delete hostRule.hostName;
delete hostRule.token;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
it('returns the hostRule if using hostName and token', () => {
delete hostRule.domainName;
delete hostRule.password;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
it('returns the hostRule if using domainName and token', () => {
delete hostRule.hostName;
delete hostRule.password;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
it('returns the hostRule if using baseUrl and password', () => {
hostRule.baseUrl = 'https://nuget.com';
delete hostRule.domainName;
delete hostRule.hostName;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
it('returns the hostRule if using baseUrl and token', () => {
hostRule.baseUrl = 'https://nuget.com';
delete hostRule.hostName;
delete hostRule.domainName;

add(hostRule);
expect(findAllAuthenticatable({ hostType: 'nuget' } as any)).toEqual([
hostRule,
]);
expect(
findAllAuthenticatable({ hostType: 'nuget' } as any)
).toMatchObject([hostRule]);
});
});
});
17 changes: 1 addition & 16 deletions lib/manager/bundler/host-rules.ts
@@ -1,10 +1,9 @@
import URL from 'url';
import { HostRule } from '../../types';
import { findAll } from '../../util/host-rules';

function isAuthenticatable(rule: HostRule): boolean {
return (
(!!rule.hostName || !!rule.domainName || !!rule.baseUrl) &&
!!rule.resolvedHost &&
((!!rule.username && !!rule.password) || !!rule.token)
);
}
Expand All @@ -17,20 +16,6 @@ export function findAllAuthenticatable({
return findAll({ hostType }).filter(isAuthenticatable);
}

export function getDomain(hostRule: HostRule): string {
if (hostRule.hostName) {
return hostRule.hostName;
}
if (hostRule.domainName) {
return hostRule.domainName;
}
if (hostRule.baseUrl) {
return URL.parse(hostRule.baseUrl).host;
}

return null;
}

export function getAuthenticationHeaderValue(hostRule: HostRule): string {
if (hostRule.username) {
return `${hostRule.username}:${hostRule.password}`;
Expand Down
2 changes: 1 addition & 1 deletion lib/manager/composer/artifacts.spec.ts
Expand Up @@ -94,7 +94,7 @@ describe('.updateArtifacts()', () => {
});
hostRules.add({
hostType: datasourcePackagist.id,
endpoint: 'https://artifactory.yyyyyyy.com/artifactory/api/composer/',
baseUrl: 'https://artifactory.yyyyyyy.com/artifactory/api/composer/',
username: 'some-other-username',
password: 'some-other-password',
});
Expand Down
28 changes: 3 additions & 25 deletions lib/manager/composer/artifacts.ts
@@ -1,4 +1,3 @@
import url from 'url';
import is from '@sindresorhus/is';
import { quote } from 'shlex';
import upath from 'upath';
Expand All @@ -13,7 +12,6 @@ import {
} from '../../constants/platforms';
import * as datasourcePackagist from '../../datasource/packagist';
import { logger } from '../../logger';
import { HostRule } from '../../types';
import { ExecOptions, exec } from '../../util/exec';
import {
deleteLocalFile,
Expand All @@ -40,25 +38,6 @@ interface AuthJson {
'http-basic'?: Record<string, UserPass>;
}

function getHost({
hostName,
domainName,
endpoint,
baseUrl,
}: HostRule): string | null {
let host = hostName || domainName;
if (!host) {
try {
host = endpoint || baseUrl;
host = url.parse(host).host;
} catch (err) {
logger.warn(`Composer: can't parse ${host}`);
host = null;
}
}
return host;
}

function getAuthJson(): string | null {
const authJson: AuthJson = {};

Expand All @@ -85,11 +64,10 @@ function getAuthJson(): string | null {
hostRules
.findAll({ hostType: datasourcePackagist.id })
?.forEach((hostRule) => {
const { username, password } = hostRule;
const host = getHost(hostRule);
if (host && username && password) {
const { resolvedHost, username, password } = hostRule;
if (resolvedHost && username && password) {
authJson['http-basic'] = authJson['http-basic'] || {};
authJson['http-basic'][host] = { username, password };
authJson['http-basic'][resolvedHost] = { username, password };
}
});

Expand Down
28 changes: 8 additions & 20 deletions lib/manager/npm/post-update/index.ts
Expand Up @@ -443,26 +443,14 @@ export async function getAdditionalFiles(
hostType: 'npm',
});
for (const hostRule of npmHostRules) {
if (hostRule.token) {
if (hostRule.baseUrl) {
rarkins marked this conversation as resolved.
Show resolved Hide resolved
additionalNpmrcContent.push(
`${hostRule.baseUrl}:_authToken=${hostRule.token}`
.replace('https://', '//')
.replace('http://', '//')
);
} else if (hostRule.hostName) {
additionalNpmrcContent.push(
`//${hostRule.hostName}/:_authToken=${hostRule.token}`
);
}
} else if (is.string(hostRule.username) && is.string(hostRule.password)) {
const password = Buffer.from(hostRule.password).toString('base64');
if (hostRule.baseUrl) {
const uri = hostRule.baseUrl.replace(/^https?:/, '');
additionalNpmrcContent.push(`${uri}:username=${hostRule.username}`);
additionalNpmrcContent.push(`${uri}:_password=${password}`);
} else if (hostRule.hostName) {
const uri = `//${hostRule.hostName}/`;
if (hostRule.resolvedHost) {
const uri = hostRule.baseUrl
? hostRule.baseUrl.replace(/^https?:/, '')
: `//${hostRule.resolvedHost}/`;
if (hostRule.token) {
additionalNpmrcContent.push(`${uri}:_authToken=${hostRule.token}`);
} else if (is.string(hostRule.username) && is.string(hostRule.password)) {
const password = Buffer.from(hostRule.password).toString('base64');
additionalNpmrcContent.push(`${uri}:username=${hostRule.username}`);
additionalNpmrcContent.push(`${uri}:_password=${password}`);
}
Expand Down
1 change: 1 addition & 0 deletions lib/types/host-rules.ts
Expand Up @@ -19,4 +19,5 @@ export interface HostRule {
enabled?: boolean;
enableHttp2?: boolean;
concurrentRequestLimit?: number;
resolvedHost?: string;
}
3 changes: 1 addition & 2 deletions lib/util/host-rules.spec.ts
Expand Up @@ -159,11 +159,10 @@ describe(getName(), () => {
hostName: 'nuget.org',
username: 'root',
password: 'p4$$w0rd',
token: undefined,
};
add(hostRule);
expect(findAll({ hostType: 'nuget' })).toHaveLength(1);
expect(findAll({ hostType: 'nuget' })[0]).toEqual(hostRule);
expect(findAll({ hostType: 'nuget' })[0]).toMatchObject(hostRule);
});
});
});
11 changes: 9 additions & 2 deletions lib/util/host-rules.ts
Expand Up @@ -2,6 +2,7 @@ import URL from 'url';
import merge from 'deepmerge';
import { logger } from '../logger';
import { HostRule } from '../types';
import { clone } from './clone';
import * as sanitize from './sanitize';

let hostRules: HostRule[] = [];
Expand All @@ -17,8 +18,9 @@ export function add(params: HostRule): void {
throw new Error('hostRules cannot contain both a hostName and baseUrl');
}
const confidentialFields = ['password', 'token'];
const resolvedHost = params.baseUrl || params.hostName || params.domainName;
let resolvedHost = params.baseUrl || params.hostName || params.domainName;
if (resolvedHost) {
resolvedHost = URL.parse(resolvedHost).hostname || resolvedHost;
confidentialFields.forEach((field) => {
if (params[field]) {
logger.debug(
Expand All @@ -39,7 +41,11 @@ export function add(params: HostRule): void {
).toString('base64');
sanitize.add(secret);
}
hostRules.push(params);
const hostRule = clone(params);
if (resolvedHost) {
hostRule.resolvedHost = resolvedHost;
}
hostRules.push(hostRule);
}

export interface HostRuleSearch {
Expand Down Expand Up @@ -150,6 +156,7 @@ export function find(search: HostRuleSearch): HostRule {
delete res.domainName;
delete res.hostName;
delete res.baseUrl;
delete res.resolvedHost;
return res;
}

Expand Down