From f8cf83380ffc53fbd60b9f73729e52f8adb9d552 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 12 Sep 2018 12:16:17 +0200
Subject: [PATCH] refactor: endpoints -> hostRules (#2509)

Renames `endpoints` to `hostRules`
---
 lib/config/cli.js                             |  4 ++-
 lib/config/definitions.js                     |  4 +--
 lib/config/env.js                             | 16 +++++------
 lib/config/index.js                           | 13 ++++-----
 lib/config/migration.js                       |  5 ++++
 lib/datasource/docker.js                      |  4 +--
 lib/datasource/npm.js                         |  4 +--
 lib/manager/composer/lock-file.js             |  4 +--
 lib/platform/bitbucket/bb-got-wrapper.js      |  4 +--
 lib/platform/bitbucket/index.js               | 10 +++----
 lib/platform/github/gh-got-wrapper.js         |  4 +--
 lib/platform/github/index.js                  | 10 +++----
 lib/platform/gitlab/gl-got-wrapper.js         |  4 +--
 lib/platform/gitlab/index.js                  | 10 +++----
 lib/platform/vsts/index.js                    | 10 +++----
 lib/platform/vsts/vsts-got-wrapper.js         |  4 +--
 lib/util/{endpoints.js => host-rules.js}      |  0
 lib/workers/pr/changelog/source-github.js     |  4 +--
 test/config/__snapshots__/env.spec.js.snap    | 20 ++++++-------
 .../__snapshots__/migration.spec.js.snap      |  3 ++
 test/config/cli.spec.js                       | 20 ++++++++-----
 test/config/env.spec.js                       |  2 +-
 test/config/migration.spec.js                 |  1 +
 test/datasource/docker.spec.js                |  6 ++--
 .../platform/bitbucket/bb-got-wrapper.spec.js | 10 +++----
 test/platform/bitbucket/index.spec.js         | 10 +++----
 test/platform/gitlab/index.spec.js            |  6 ++--
 test/platform/vsts/index.spec.js              |  6 ++--
 test/platform/vsts/vsts-got-wrapper.spec.js   |  6 ++--
 ...s.spec.js.snap => host-rules.spec.js.snap} | 10 +++----
 .../{endpoints.spec.js => host-rules.spec.js} |  4 +--
 test/workers/pr/changelog/index.spec.js       | 12 ++++----
 website/docs/configuration-options.md         | 28 +++++++++----------
 website/docs/docker.md                        |  2 +-
 34 files changed, 138 insertions(+), 122 deletions(-)
 rename lib/util/{endpoints.js => host-rules.js} (100%)
 rename test/util/__snapshots__/{endpoints.spec.js.snap => host-rules.spec.js.snap} (63%)
 rename test/util/{endpoints.spec.js => host-rules.spec.js} (94%)

diff --git a/lib/config/cli.js b/lib/config/cli.js
index 2446d01868..086d63fa6a 100644
--- a/lib/config/cli.js
+++ b/lib/config/cli.js
@@ -15,7 +15,9 @@ function getCliName(option) {
   return `--${nameWithHyphens.toLowerCase()}`;
 }
 
-function getConfig(argv) {
+function getConfig(input) {
+  // massage migrated configuration keys
+  const argv = input.map(a => a.replace('--endpoints=', '--host-rules='));
   const options = configDefinitions.getOptions();
 
   const config = {};
diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 8a076d4fff..c3435d386e 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -1158,8 +1158,8 @@ const options = [
     default: true,
   },
   {
-    name: 'endpoints',
-    description: 'Endpoint configuration for credentials',
+    name: 'hostRules',
+    description: 'Host rules/configuration including credentials',
     type: 'list',
     stage: 'repository',
     cli: true,
diff --git a/lib/config/env.js b/lib/config/env.js
index 242780a0ea..6f231cbf6f 100644
--- a/lib/config/env.js
+++ b/lib/config/env.js
@@ -19,7 +19,7 @@ function getEnvName(option) {
 function getConfig(env) {
   const options = configDefinitions.getOptions();
 
-  const config = { endpoints: [] };
+  const config = { hostRules: [] };
 
   const coersions = {
     boolean: val => val === 'true',
@@ -40,7 +40,7 @@ function getConfig(env) {
   });
 
   if (env.GITHUB_TOKEN) {
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'github',
       endpoint: env.GITHUB_ENDPOINT,
       token: env.GITHUB_TOKEN,
@@ -49,7 +49,7 @@ function getConfig(env) {
   }
 
   if (env.GITHUB_COM_TOKEN) {
-    config.endpoints.push({
+    config.hostRules.push({
       endpoint: 'https://api.github.com/',
       platform: 'github',
       token: env.GITHUB_COM_TOKEN,
@@ -57,7 +57,7 @@ function getConfig(env) {
   }
 
   if (env.GITLAB_TOKEN) {
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'gitlab',
       endpoint: env.GITLAB_ENDPOINT,
       token: env.GITLAB_TOKEN,
@@ -65,14 +65,14 @@ function getConfig(env) {
   }
 
   if (env.BITBUCKET_TOKEN) {
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'bitbucket',
       endpoint: env.BITBUCKET_ENDPOINT,
       token: env.BITBUCKET_TOKEN,
     });
   } else if (env.BITBUCKET_USERNAME && env.BITBUCKET_PASSWORD) {
     const base64 = str => Buffer.from(str, 'binary').toString('base64');
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'bitbucket',
       endpoint: env.BITBUCKET_ENDPOINT,
       token: base64(`${env.BITBUCKET_USERNAME}:${env.BITBUCKET_PASSWORD}`),
@@ -80,7 +80,7 @@ function getConfig(env) {
   }
 
   if (env.VSTS_ENDPOINT || env.VSTS_TOKEN) {
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'vsts',
       endpoint: env.VSTS_ENDPOINT,
       token: env.VSTS_TOKEN,
@@ -88,7 +88,7 @@ function getConfig(env) {
   }
 
   if (env.DOCKER_USERNAME && env.DOCKER_PASSWORD) {
-    config.endpoints.push({
+    config.hostRules.push({
       platform: 'docker',
       username: env.DOCKER_USERNAME,
       password: env.DOCKER_PASSWORD,
diff --git a/lib/config/index.js b/lib/config/index.js
index bbdb8b9d0a..3936ce757e 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -12,7 +12,7 @@ const { getPlatformApi } = require('../platform');
 const { resolveConfigPresets } = require('./presets');
 const { get, getLanguageList, getManagerList } = require('../manager');
 
-const endpoints = require('../util/endpoints');
+const hostRules = require('../util/host-rules');
 
 exports.parseConfigs = parseConfigs;
 exports.mergeChildConfig = mergeChildConfig;
@@ -84,17 +84,17 @@ async function parseConfigs(env, argv) {
 
   // Check platforms and tokens
   const { platform, endpoint, username, password, token } = config;
-  const platformInfo = endpoints.defaults[platform];
+  const platformInfo = hostRules.defaults[platform];
   if (!platformInfo) {
     throw new Error(`Unsupported platform: ${config.platform}.`);
   }
-  config.endpoints.forEach(endpoints.update);
-  delete config.endpoints;
+  config.hostRules.forEach(hostRules.update);
+  delete config.hostRules;
   delete config.token;
   delete config.username;
   delete config.password;
 
-  const credentials = endpoints.find(
+  const credentials = hostRules.find(
     { platform },
     {
       platform,
@@ -113,12 +113,11 @@ async function parseConfigs(env, argv) {
     credentials.token = base64(`${username}:${password}`);
   }
 
-  // we don't need to check endpoint, endpoints.update({}) will do that
   if (!credentials.token) {
     throw new Error(`You need to supply a ${platformInfo.name} token.`);
   }
 
-  endpoints.update({
+  hostRules.update({
     ...credentials,
     default: true,
   });
diff --git a/lib/config/migration.js b/lib/config/migration.js
index 3d9c90efea..311cc47188 100644
--- a/lib/config/migration.js
+++ b/lib/config/migration.js
@@ -376,6 +376,11 @@ function migrateConfig(config) {
           .replace(/newValueMinor/g, 'newMinor');
       }
     }
+    if (migratedConfig.endpoints) {
+      migratedConfig.hostRules = migratedConfig.endpoints;
+      delete migratedConfig.endpoints;
+      isMigrated = true;
+    }
     return { isMigrated, migratedConfig };
   } catch (err) /* istanbul ignore next */ {
     logger.debug({ config }, 'migrateConfig() error');
diff --git a/lib/datasource/docker.js b/lib/datasource/docker.js
index b2d42c9532..9993a75c52 100644
--- a/lib/datasource/docker.js
+++ b/lib/datasource/docker.js
@@ -4,7 +4,7 @@ const URL = require('url');
 const parseLinkHeader = require('parse-link-header');
 const wwwAuthenticate = require('www-authenticate');
 const { isVersion, sortVersions } = require('../versioning/docker');
-const endpoints = require('../util/endpoints');
+const hostRules = require('../util/host-rules');
 
 module.exports = {
   getDigest,
@@ -46,7 +46,7 @@ async function getAuthHeaders(registry, repository) {
     // prettier-ignore
     const authUrl = `${authenticateHeader.parms.realm}?service=${authenticateHeader.parms.service}&scope=repository:${repository}:pull`;
     const { host } = URL.parse(registry);
-    const opts = endpoints.find({ platform: 'docker', host }, { json: true });
+    const opts = hostRules.find({ platform: 'docker', host }, { json: true });
     if (opts.username && opts.password) {
       const auth = Buffer.from(`${opts.username}:${opts.password}`).toString(
         'base64'
diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js
index cf0e3819d6..e66e2af0ff 100644
--- a/lib/datasource/npm.js
+++ b/lib/datasource/npm.js
@@ -9,7 +9,7 @@ const registryAuthToken = require('registry-auth-token');
 const parse = require('github-url-from-git');
 const { isBase64 } = require('validator');
 const { isVersion, sortVersions } = require('../versioning')('semver');
-const endpoints = require('../util/endpoints');
+const hostRules = require('../util/host-rules');
 
 module.exports = {
   maskToken,
@@ -222,7 +222,7 @@ async function getDependency(name, retries = 5) {
     if (res.repository && res.repository.url) {
       const extraBaseUrls = [];
       // istanbul ignore next
-      endpoints.hosts({ platform: 'github' }).forEach(host => {
+      hostRules.hosts({ platform: 'github' }).forEach(host => {
         extraBaseUrls.push(host, `gist.${host}`);
       });
       // Massage www out of github URL
diff --git a/lib/manager/composer/lock-file.js b/lib/manager/composer/lock-file.js
index 30c353e225..2946160ac8 100644
--- a/lib/manager/composer/lock-file.js
+++ b/lib/manager/composer/lock-file.js
@@ -2,7 +2,7 @@ const { exec } = require('child-process-promise');
 const fs = require('fs-extra');
 const upath = require('upath');
 
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 module.exports = {
   getLockFile,
@@ -36,7 +36,7 @@ async function getLockFile(
     if (!config.gitFs) {
       await fs.outputFile(localLockFileName, existingLockFileContent);
     }
-    const credentials = endpoints.find({
+    const credentials = hostRules.find({
       platform: 'github',
       host: 'api.github.com',
     });
diff --git a/lib/platform/bitbucket/bb-got-wrapper.js b/lib/platform/bitbucket/bb-got-wrapper.js
index aa4a981c3e..901e52e9fa 100644
--- a/lib/platform/bitbucket/bb-got-wrapper.js
+++ b/lib/platform/bitbucket/bb-got-wrapper.js
@@ -1,6 +1,6 @@
 const got = require('got');
 const URL = require('url');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 let cache = {};
 
@@ -9,7 +9,7 @@ async function get(path, options) {
   const opts = {
     json: true,
     basic: false,
-    ...endpoints.find({ platform: 'bitbucket', host }),
+    ...hostRules.find({ platform: 'bitbucket', host }),
     ...options,
   };
   const url = URL.resolve(opts.endpoint, path);
diff --git a/lib/platform/bitbucket/index.js b/lib/platform/bitbucket/index.js
index 7bfd379cb7..acb4484973 100644
--- a/lib/platform/bitbucket/index.js
+++ b/lib/platform/bitbucket/index.js
@@ -1,7 +1,7 @@
 const parseDiff = require('parse-diff');
 const api = require('./bb-got-wrapper');
 const utils = require('./utils');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 let config = {};
 
@@ -54,12 +54,12 @@ module.exports = {
 // Get all repositories that the user has access to
 async function getRepos(token, endpoint) {
   logger.debug('getRepos(token, endpoint)');
-  const opts = endpoints.find({ platform: 'bitbucket' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'bitbucket' }, { token, endpoint });
   // istanbul ignore next
   if (!opts.token) {
     throw new Error('No token found for getRepos');
   }
-  endpoints.update({ ...opts, platform: 'bitbucket', default: true });
+  hostRules.update({ ...opts, platform: 'bitbucket', default: true });
   try {
     const repos = await utils.accumulateValues(
       `/2.0/repositories/?role=contributor`
@@ -74,12 +74,12 @@ async function getRepos(token, endpoint) {
 // Initialize bitbucket by getting base branch and SHA
 async function initRepo({ repository, token, endpoint }) {
   logger.debug(`initRepo("${repository}")`);
-  const opts = endpoints.find({ platform: 'bitbucket' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'bitbucket' }, { token, endpoint });
   // istanbul ignore next
   if (!opts.token) {
     throw new Error(`No token found for Bitbucket repository ${repository}`);
   }
-  endpoints.update({ ...opts, platform: 'bitbucket', default: true });
+  hostRules.update({ ...opts, platform: 'bitbucket', default: true });
   api.reset();
   config = {};
   // TODO: get in touch with @rarkins about lifting up the caching into the app layer
diff --git a/lib/platform/github/gh-got-wrapper.js b/lib/platform/github/gh-got-wrapper.js
index c3e7068f9b..9096686c33 100644
--- a/lib/platform/github/gh-got-wrapper.js
+++ b/lib/platform/github/gh-got-wrapper.js
@@ -2,7 +2,7 @@ const URL = require('url');
 const ghGot = require('gh-got');
 const delay = require('delay');
 const parseLinkHeader = require('parse-link-header');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 let cache = {};
 let stats = {};
@@ -10,7 +10,7 @@ let stats = {};
 async function get(path, options, retries = 5) {
   const { host } = URL.parse(path);
   const opts = {
-    ...endpoints.find({ platform: 'github', host }),
+    ...hostRules.find({ platform: 'github', host }),
     ...options,
   };
   const method = opts.method || 'get';
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index eb97aea0e6..f942460244 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -5,7 +5,7 @@ const showdown = require('showdown');
 const URL = require('url');
 
 const get = require('./gh-got-wrapper');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 const Storage = require('./storage');
 const GitStorage = require('../git/storage');
 
@@ -64,11 +64,11 @@ module.exports = {
 // Get all repositories that the user has access to
 async function getRepos(token, endpoint) {
   logger.info('Autodiscovering GitHub repositories');
-  const opts = endpoints.find({ platform: 'github' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'github' }, { token, endpoint });
   if (!opts.token) {
     throw new Error('No token found for getRepos');
   }
-  endpoints.update({ ...opts, platform: 'github', default: true });
+  hostRules.update({ ...opts, platform: 'github', default: true });
   try {
     const res = await get('user/repos', { paginate: true });
     return res.body.map(repo => repo.full_name);
@@ -102,11 +102,11 @@ async function initRepo({
   localDir,
 }) {
   logger.debug(`initRepo("${repository}")`);
-  const opts = endpoints.find({ platform: 'github' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'github' }, { token, endpoint });
   if (!opts.token) {
     throw new Error(`No token found for GitHub repository ${repository}`);
   }
-  endpoints.update({ ...opts, platform: 'github', default: true });
+  hostRules.update({ ...opts, platform: 'github', default: true });
   logger.debug('Resetting platform config');
   // config is used by the platform api itself, not necessary for the app layer to know
   cleanRepo();
diff --git a/lib/platform/gitlab/gl-got-wrapper.js b/lib/platform/gitlab/gl-got-wrapper.js
index 959062d8bd..e27f749ec6 100644
--- a/lib/platform/gitlab/gl-got-wrapper.js
+++ b/lib/platform/gitlab/gl-got-wrapper.js
@@ -3,14 +3,14 @@ const glGot = require('gl-got');
 const delay = require('delay');
 
 const parseLinkHeader = require('parse-link-header');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 let cache = {};
 
 async function get(path, options, retries = 5) {
   const { host } = URL.parse(path);
   const opts = {
-    ...endpoints.find({ platform: 'gitlab', host }),
+    ...hostRules.find({ platform: 'gitlab', host }),
     ...options,
   };
   const method = opts.method || 'get';
diff --git a/lib/platform/gitlab/index.js b/lib/platform/gitlab/index.js
index 57ab08c7cf..ed320929a5 100644
--- a/lib/platform/gitlab/index.js
+++ b/lib/platform/gitlab/index.js
@@ -3,7 +3,7 @@ const addrs = require('email-addresses');
 const showdown = require('showdown');
 
 const get = require('./gl-got-wrapper');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 const converter = new showdown.Converter();
 converter.setFlavor('github');
@@ -60,11 +60,11 @@ module.exports = {
 async function getRepos(token, endpoint) {
   logger.info('Autodiscovering GitLab repositories');
   logger.debug('getRepos(token, endpoint)');
-  const opts = endpoints.find({ platform: 'gitlab' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'gitlab' }, { token, endpoint });
   if (!opts.token) {
     throw new Error('No token found for getRepos');
   }
-  endpoints.update({ ...opts, platform: 'gitlab', default: true });
+  hostRules.update({ ...opts, platform: 'gitlab', default: true });
   try {
     const url = `projects?membership=true&per_page=100`;
     const res = await get(url, { paginate: true });
@@ -88,11 +88,11 @@ function cleanRepo() {
 
 // Initialize GitLab by getting base branch
 async function initRepo({ repository, token, endpoint, gitAuthor }) {
-  const opts = endpoints.find({ platform: 'gitlab' }, { token, endpoint });
+  const opts = hostRules.find({ platform: 'gitlab' }, { token, endpoint });
   if (!opts.token) {
     throw new Error(`No token found for GitLab repository ${repository}`);
   }
-  endpoints.update({ ...opts, platform: 'gitlab', default: true });
+  hostRules.update({ ...opts, platform: 'gitlab', default: true });
   config = {};
   get.reset();
   config.repository = urlEscape(repository);
diff --git a/lib/platform/vsts/index.js b/lib/platform/vsts/index.js
index 1188445845..d637c85ab4 100644
--- a/lib/platform/vsts/index.js
+++ b/lib/platform/vsts/index.js
@@ -1,7 +1,7 @@
 // @ts-nocheck //because of logger, we can't ts-check
 const vstsHelper = require('./vsts-helper');
 const vstsApi = require('./vsts-got-wrapper');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 const config = {};
 
@@ -55,8 +55,8 @@ module.exports = {
 async function getRepos(token, endpoint) {
   logger.info('Autodiscovering vsts repositories');
   logger.debug('getRepos(token, endpoint)');
-  const opts = endpoints.find({ platform: 'vsts' }, { token, endpoint });
-  endpoints.update({ ...opts, platform: 'vsts', default: true });
+  const opts = hostRules.find({ platform: 'vsts' }, { token, endpoint });
+  hostRules.update({ ...opts, platform: 'vsts', default: true });
   const vstsApiGit = await vstsApi.gitApi();
   const repos = await vstsApiGit.getRepositories();
   return repos.map(repo => `${repo.project.name}/${repo.name}`);
@@ -64,8 +64,8 @@ async function getRepos(token, endpoint) {
 
 async function initRepo({ repository, token, endpoint }) {
   logger.debug(`initRepo("${repository}")`);
-  const opts = endpoints.find({ platform: 'vsts' }, { token, endpoint });
-  endpoints.update({ ...opts, platform: 'vsts', default: true });
+  const opts = hostRules.find({ platform: 'vsts' }, { token, endpoint });
+  hostRules.update({ ...opts, platform: 'vsts', default: true });
   config.repository = repository;
   config.fileList = null;
   config.prList = null;
diff --git a/lib/platform/vsts/vsts-got-wrapper.js b/lib/platform/vsts/vsts-got-wrapper.js
index bb49e3c5aa..2054dd10b5 100644
--- a/lib/platform/vsts/vsts-got-wrapper.js
+++ b/lib/platform/vsts/vsts-got-wrapper.js
@@ -1,5 +1,5 @@
 const vsts = require('vso-node-api');
-const endpoints = require('../../util/endpoints');
+const hostRules = require('../../util/host-rules');
 
 module.exports = {
   vstsObj,
@@ -8,7 +8,7 @@ module.exports = {
 };
 
 function vstsObj() {
-  const config = endpoints.find({ platform: 'vsts' }, {});
+  const config = hostRules.find({ platform: 'vsts' }, {});
   if (!config.token) {
     throw new Error(`No token found for vsts`);
   }
diff --git a/lib/util/endpoints.js b/lib/util/host-rules.js
similarity index 100%
rename from lib/util/endpoints.js
rename to lib/util/host-rules.js
diff --git a/lib/workers/pr/changelog/source-github.js b/lib/workers/pr/changelog/source-github.js
index 39c033bbeb..bdb9337c4b 100644
--- a/lib/workers/pr/changelog/source-github.js
+++ b/lib/workers/pr/changelog/source-github.js
@@ -1,5 +1,5 @@
 const URL = require('url');
-const endpoints = require('../../../util/endpoints');
+const hostRules = require('../../../util/host-rules');
 const versioning = require('../../../versioning');
 const ghGot = require('../../../platform/github/gh-got-wrapper');
 const { addReleaseNotes } = require('./release-notes');
@@ -51,7 +51,7 @@ async function getChangeLogJSON({
   );
   const { protocol, host, pathname } = URL.parse(repositoryUrl);
   const githubBaseURL = `${protocol}//${host}/`;
-  const config = endpoints.find({
+  const config = hostRules.find({
     platform: 'github',
     host: host === 'github.com' ? 'api.github.com' : host,
   });
diff --git a/test/config/__snapshots__/env.spec.js.snap b/test/config/__snapshots__/env.spec.js.snap
index ac948687ec..bfe82efcf2 100644
--- a/test/config/__snapshots__/env.spec.js.snap
+++ b/test/config/__snapshots__/env.spec.js.snap
@@ -2,7 +2,7 @@
 
 exports[`config/env .getConfig(env) supports Bitbucket token 1`] = `
 Object {
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "endpoint": "a bitbucket endpoint",
       "platform": "bitbucket",
@@ -15,7 +15,7 @@ Object {
 
 exports[`config/env .getConfig(env) supports Bitbucket username/password 1`] = `
 Object {
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "endpoint": "a bitbucket endpoint",
       "platform": "bitbucket",
@@ -29,14 +29,14 @@ Object {
 exports[`config/env .getConfig(env) supports GitHub custom endpoint 1`] = `
 Object {
   "endpoint": "a ghe endpoint",
-  "endpoints": Array [],
+  "hostRules": Array [],
 }
 `;
 
 exports[`config/env .getConfig(env) supports GitHub custom endpoint and github.com 1`] = `
 Object {
   "endpoint": "a ghe endpoint",
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "default": true,
       "endpoint": "a ghe endpoint",
@@ -55,7 +55,7 @@ Object {
 exports[`config/env .getConfig(env) supports GitHub custom endpoint and github.com and gitlab.com 1`] = `
 Object {
   "endpoint": "a ghe endpoint",
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "default": true,
       "endpoint": "a ghe endpoint",
@@ -78,7 +78,7 @@ Object {
 
 exports[`config/env .getConfig(env) supports GitHub token 1`] = `
 Object {
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "default": true,
       "endpoint": undefined,
@@ -92,7 +92,7 @@ Object {
 exports[`config/env .getConfig(env) supports GitLab custom endpoint 1`] = `
 Object {
   "endpoint": "a gitlab endpoint",
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "endpoint": "a gitlab endpoint",
       "platform": "gitlab",
@@ -106,7 +106,7 @@ Object {
 exports[`config/env .getConfig(env) supports GitLab token 1`] = `
 Object {
   "endpoint": undefined,
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "endpoint": undefined,
       "platform": "gitlab",
@@ -120,7 +120,7 @@ Object {
 exports[`config/env .getConfig(env) supports VSTS 1`] = `
 Object {
   "endpoint": "a vsts endpoint",
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "endpoint": "a vsts endpoint",
       "platform": "vsts",
@@ -133,7 +133,7 @@ Object {
 
 exports[`config/env .getConfig(env) supports docker username/password 1`] = `
 Object {
-  "endpoints": Array [
+  "hostRules": Array [
     Object {
       "password": "some-password",
       "platform": "docker",
diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap
index e4abe7bac7..815ba4b5f2 100644
--- a/test/config/__snapshots__/migration.spec.js.snap
+++ b/test/config/__snapshots__/migration.spec.js.snap
@@ -20,6 +20,9 @@ Object {
     "config:js-app",
     "config:js-lib",
   ],
+  "hostRules": Array [
+    Object {},
+  ],
   "ignorePaths": Array [
     "node_modules/",
   ],
diff --git a/test/config/cli.spec.js b/test/config/cli.spec.js
index b5970bf019..ba6328d848 100644
--- a/test/config/cli.spec.js
+++ b/test/config/cli.spec.js
@@ -67,10 +67,10 @@ describe('config/cli', () => {
     });
     it('parses json lists correctly', () => {
       argv.push(
-        `--endpoints=[{"host":"docker.io","platform":"docker","username":"user","password":"password"}]`
+        `--host-rules=[{"host":"docker.io","platform":"docker","username":"user","password":"password"}]`
       );
       cli.getConfig(argv).should.deep.equal({
-        endpoints: [
+        hostRules: [
           {
             host: 'docker.io',
             platform: 'docker',
@@ -80,16 +80,22 @@ describe('config/cli', () => {
         ],
       });
     });
-    it('parses [] correctly as empty list of endpoints', () => {
-      argv.push(`--endpoints=[]`);
+    it('parses [] correctly as empty list of hostRules', () => {
+      argv.push(`--host-rules=[]`);
       cli.getConfig(argv).should.eql({
-        endpoints: [],
+        hostRules: [],
       });
     });
-    it('parses an empty string correctly as empty list of endpoints', () => {
+    it('parses an empty string correctly as empty list of hostRules', () => {
+      argv.push(`--host-rules=`);
+      cli.getConfig(argv).should.eql({
+        hostRules: [],
+      });
+    });
+    it('migrates --endpoints', () => {
       argv.push(`--endpoints=`);
       cli.getConfig(argv).should.eql({
-        endpoints: [],
+        hostRules: [],
       });
     });
   });
diff --git a/test/config/env.spec.js b/test/config/env.spec.js
index ba51ee23ff..e62472d390 100644
--- a/test/config/env.spec.js
+++ b/test/config/env.spec.js
@@ -3,7 +3,7 @@ const env = require('../../lib/config/env.js');
 describe('config/env', () => {
   describe('.getConfig(env)', () => {
     it('returns empty env', () => {
-      expect(env.getConfig({})).toEqual({ endpoints: [] });
+      expect(env.getConfig({})).toEqual({ hostRules: [] });
     });
     it('supports boolean true', () => {
       const envParam = { RENOVATE_RECREATE_CLOSED: 'true' };
diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js
index d30f70a43c..37fc8a2096 100644
--- a/test/config/migration.spec.js
+++ b/test/config/migration.spec.js
@@ -5,6 +5,7 @@ describe('config/migration', () => {
   describe('migrateConfig(config, parentConfig)', () => {
     it('it migrates config', () => {
       const config = {
+        endpoints: [{}],
         enabled: true,
         extends: [':js-app', 'config:library'],
         maintainYarnLock: true,
diff --git a/test/datasource/docker.spec.js b/test/datasource/docker.spec.js
index 8aa067805f..4dea4ad03f 100644
--- a/test/datasource/docker.spec.js
+++ b/test/datasource/docker.spec.js
@@ -1,15 +1,15 @@
 const got = require('got');
 const docker = require('../../lib/datasource/docker');
-const endpoints = require('../../lib/util/endpoints');
+const hostRules = require('../../lib/util/host-rules');
 
 jest.mock('got');
-jest.mock('../../lib/util/endpoints');
+jest.mock('../../lib/util/host-rules');
 
 describe('api/docker', () => {
   describe('getDigest', () => {
     beforeEach(() => {
       jest.resetAllMocks();
-      endpoints.find.mockReturnValue({
+      hostRules.find.mockReturnValue({
         username: 'some-username',
         password: 'some-password',
       });
diff --git a/test/platform/bitbucket/bb-got-wrapper.spec.js b/test/platform/bitbucket/bb-got-wrapper.spec.js
index 3b71e04339..3a505f6ab6 100644
--- a/test/platform/bitbucket/bb-got-wrapper.spec.js
+++ b/test/platform/bitbucket/bb-got-wrapper.spec.js
@@ -1,18 +1,18 @@
 describe('platform/gl-got-wrapper', () => {
   let get;
   let got;
-  let endpoints;
+  let hostRules;
   beforeEach(() => {
     // reset module
     jest.resetAllMocks();
     jest.mock('got');
     got = require('got');
-    endpoints = require('../../../lib/util/endpoints');
+    hostRules = require('../../../lib/util/host-rules');
     get = require('../../../lib/platform/bitbucket/bb-got-wrapper');
 
-    // clean up endpoints
-    endpoints.clear();
-    endpoints.update({
+    // clean up hostRules
+    hostRules.clear();
+    hostRules.update({
       platform: 'bitbucket',
       token: 'token',
     });
diff --git a/test/platform/bitbucket/index.spec.js b/test/platform/bitbucket/index.spec.js
index 76e8830246..2c3053c818 100644
--- a/test/platform/bitbucket/index.spec.js
+++ b/test/platform/bitbucket/index.spec.js
@@ -18,18 +18,18 @@ function streamToString(stream) {
 describe('platform/bitbucket', () => {
   let bitbucket;
   let api;
-  let endpoints;
+  let hostRules;
   beforeEach(() => {
     // reset module
     jest.resetModules();
     jest.mock('../../../lib/platform/bitbucket/bb-got-wrapper');
-    endpoints = require('../../../lib/util/endpoints');
+    hostRules = require('../../../lib/util/host-rules');
     api = require('../../../lib/platform/bitbucket/bb-got-wrapper');
     bitbucket = require('../../../lib/platform/bitbucket');
 
-    // clean up endpoints
-    endpoints.clear();
-    endpoints.update({
+    // clean up hostRules
+    hostRules.clear();
+    hostRules.update({
       platform: 'bitbucket',
       token: 'token',
     });
diff --git a/test/platform/gitlab/index.spec.js b/test/platform/gitlab/index.spec.js
index dceea5a052..c7b76469f1 100644
--- a/test/platform/gitlab/index.spec.js
+++ b/test/platform/gitlab/index.spec.js
@@ -1,11 +1,11 @@
-const endpoints = require('../../../lib/util/endpoints');
+const hostRules = require('../../../lib/util/host-rules');
 
 describe('platform/gitlab', () => {
   let gitlab;
   let get;
   beforeEach(() => {
-    // clean up endpoints
-    endpoints.clear();
+    // clean up hostRules
+    hostRules.clear();
 
     // reset module
     jest.resetModules();
diff --git a/test/platform/vsts/index.spec.js b/test/platform/vsts/index.spec.js
index 2126036404..72bc721a0e 100644
--- a/test/platform/vsts/index.spec.js
+++ b/test/platform/vsts/index.spec.js
@@ -1,12 +1,12 @@
-const endpoints = require('../../../lib/util/endpoints');
+const hostRules = require('../../../lib/util/host-rules');
 
 describe('platform/vsts', () => {
   let vsts;
   let vstsApi;
   let vstsHelper;
   beforeEach(() => {
-    // clean up endpoints
-    endpoints.clear();
+    // clean up hostRules
+    hostRules.clear();
 
     // reset module
     jest.resetModules();
diff --git a/test/platform/vsts/vsts-got-wrapper.spec.js b/test/platform/vsts/vsts-got-wrapper.spec.js
index f8d4abbf20..458cbabfa8 100644
--- a/test/platform/vsts/vsts-got-wrapper.spec.js
+++ b/test/platform/vsts/vsts-got-wrapper.spec.js
@@ -1,10 +1,10 @@
 describe('platform/vsts/vsts-got-wrapper', () => {
-  let endpoints;
+  let hostRules;
   let vsts;
   beforeEach(() => {
     // reset module
     jest.resetModules();
-    endpoints = require('../../../lib/util/endpoints');
+    hostRules = require('../../../lib/util/host-rules');
     vsts = require('../../../lib/platform/vsts/vsts-got-wrapper');
   });
 
@@ -14,7 +14,7 @@ describe('platform/vsts/vsts-got-wrapper', () => {
       expect(vsts.getCoreApi).toThrow('No token found for vsts');
     });
     it('should set token and endpoint', async () => {
-      endpoints.update({
+      hostRules.update({
         platform: 'vsts',
         token: 'myToken',
         endpoint: 'myEndpoint',
diff --git a/test/util/__snapshots__/endpoints.spec.js.snap b/test/util/__snapshots__/host-rules.spec.js.snap
similarity index 63%
rename from test/util/__snapshots__/endpoints.spec.js.snap
rename to test/util/__snapshots__/host-rules.spec.js.snap
index c9e912f388..b5349b975a 100644
--- a/test/util/__snapshots__/endpoints.spec.js.snap
+++ b/test/util/__snapshots__/host-rules.spec.js.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`util/endpoints find() allows overrides 1`] = `
+exports[`util/host-rules find() allows overrides 1`] = `
 Object {
   "endpoint": "endpoint/",
   "name": "GitHub",
@@ -10,19 +10,19 @@ Object {
 }
 `;
 
-exports[`util/endpoints find() allows overrides 2`] = `
+exports[`util/host-rules find() allows overrides 2`] = `
 Object {
   "token": "secret",
 }
 `;
 
-exports[`util/endpoints find() allows overrides 3`] = `
+exports[`util/host-rules find() allows overrides 3`] = `
 Object {
   "token": "secret",
 }
 `;
 
-exports[`util/endpoints update() uses default endpoint 1`] = `
+exports[`util/host-rules update() uses default endpoint 1`] = `
 Object {
   "endpoint": "https://api.github.com/",
   "name": "GitHub",
@@ -32,7 +32,7 @@ Object {
 }
 `;
 
-exports[`util/endpoints update() uses default endpoint 2`] = `
+exports[`util/host-rules update() uses default endpoint 2`] = `
 Object {
   "endpoint": "https://api.github.com/",
   "name": "GitHub",
diff --git a/test/util/endpoints.spec.js b/test/util/host-rules.spec.js
similarity index 94%
rename from test/util/endpoints.spec.js
rename to test/util/host-rules.spec.js
index d7c4913e15..c456107da7 100644
--- a/test/util/endpoints.spec.js
+++ b/test/util/host-rules.spec.js
@@ -1,6 +1,6 @@
-const { update, find, clear } = require('../../lib/util/endpoints');
+const { update, find, clear } = require('../../lib/util/host-rules');
 
-describe('util/endpoints', () => {
+describe('util/host-rules', () => {
   beforeEach(() => {
     clear();
   });
diff --git a/test/workers/pr/changelog/index.spec.js b/test/workers/pr/changelog/index.spec.js
index 705c961884..9f16a59261 100644
--- a/test/workers/pr/changelog/index.spec.js
+++ b/test/workers/pr/changelog/index.spec.js
@@ -2,7 +2,7 @@ jest.mock('../../../../lib/platform/github/gh-got-wrapper');
 jest.mock('../../../../lib/datasource/npm');
 jest.mock('got');
 
-const endpoints = require('../../../../lib/util/endpoints');
+const hostRules = require('../../../../lib/util/host-rules');
 const ghGot = require('../../../../lib/platform/github/gh-got-wrapper');
 
 const { getChangeLogJSON } = require('../../../../lib/workers/pr/changelog');
@@ -34,8 +34,8 @@ describe('workers/pr/changelog', () => {
   describe('getChangeLogJSON', () => {
     beforeEach(async () => {
       ghGot.mockClear();
-      endpoints.clear();
-      endpoints.update({
+      hostRules.clear();
+      hostRules.update({
         platform: 'github',
         endpoint: 'https://api.github.com/',
       });
@@ -164,7 +164,7 @@ describe('workers/pr/changelog', () => {
       ).toBe(null);
     });
     it('supports github enterprise and github.com changelog', async () => {
-      endpoints.update({
+      hostRules.update({
         platform: 'github',
         token: 'super_secret',
         endpoint: 'https://github-enterprise.example.com/',
@@ -176,7 +176,7 @@ describe('workers/pr/changelog', () => {
       ).toMatchSnapshot();
     });
     it('supports github enterprise and github enterprise changelog', async () => {
-      endpoints.update({
+      hostRules.update({
         platform: 'github',
         endpoint: 'https://github-enterprise.example.com/',
       });
@@ -190,7 +190,7 @@ describe('workers/pr/changelog', () => {
     });
 
     it('supports github enterprise alwo when retrieving data from cache', async () => {
-      endpoints.update({
+      hostRules.update({
         platform: 'github',
         endpoint: 'https://github-enterprise.example.com/',
       });
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index 13947bcd41..bdc6928ff3 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -195,20 +195,6 @@ Example:
 
 See https://renovatebot.com/docs/deep-dives/private-modules for details on how this is used to encrypt npm tokens.
 
-## endpoints
-
-Example for configuring `docker` auth:
-
-```json
-{
-  "endpoints": {
-    "platform": "docker",
-    "username": "<some-username>",
-    "password": "<some-password>"
-  }
-}
-```
-
 ## engines
 
 Extend this if you wish to configure rules specifically for `engines` definitions. Currently only `node` is supported.
@@ -242,6 +228,20 @@ By default, Renovate will "slugify" the groupName to determine the branch name.
 
 And then the branchName would be `renovate/eslint` instead.
 
+## hostRules
+
+Example for configuring `docker` auth:
+
+```json
+{
+  "hostRules": {
+    "platform": "docker",
+    "username": "<some-username>",
+    "password": "<some-password>"
+  }
+}
+```
+
 ## ignoreDeprecated
 
 By default, Renovate won't update any packages to deprecated versions unless the package version was _already_ deprecated. The goal of this is to make sure you don't upgrade from a non-deprecated version to a deprecated one just because it's higher than the current version. If for some reason you wish to _force_ deprecated updates on Renovate, you can set `ignoreDeprecated` to `false`, but this is not recommended for most situations.
diff --git a/website/docs/docker.md b/website/docs/docker.md
index caf3ce8ced..90ba584d65 100644
--- a/website/docs/docker.md
+++ b/website/docs/docker.md
@@ -96,7 +96,7 @@ If you are running your own Renovate bot, add this to your `config.js`:
 
 ```js
 module.exports = {
-  endpoints: [
+  hostRules: [
     {
       platform: 'docker',
       username: '<your-username>',
-- 
GitLab