diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.js index 6582099a2e50ea366586c15bf6f878c1f0639cca..b25e88246532c251f65084f153cc83eb6e5109a7 100644 --- a/lib/datasource/terraform/index.js +++ b/lib/datasource/terraform/index.js @@ -6,6 +6,27 @@ module.exports = { getPkgReleases, }; +function getRegistryRepository(lookupName, registryUrls) { + let registry; + const split = lookupName.split('/'); + if (split.length > 3 && split[0].includes('.')) { + [registry] = split; + split.shift(); + } else if (is.nonEmptyArray(registryUrls)) { + [registry] = registryUrls; + } else { + registry = 'registry.terraform.io'; + } + if (!registry.match('^https?://')) { + registry = `https://${registry}`; + } + const repository = split.join('/'); + return { + registry, + repository, + }; +} + /* * terraform.getPkgReleases * @@ -15,13 +36,13 @@ module.exports = { */ async function getPkgReleases(purl, config) { - const { lookupName: dependency } = purl; - const registry = is.nonEmptyArray(config.repositoryUrls) - ? config.repositoryUrls[0] - : 'https://registry.terraform.io'; - logger.debug({ dependency, registry }, 'terraform.getDependencies()'); + const { registry, repository } = getRegistryRepository( + purl.lookupName, + config.registryUrls + ); + logger.debug({ registry, repository }, 'terraform.getDependencies()'); const cacheNamespace = 'terraform'; - const pkgUrl = `${registry}/v1/modules/${dependency}`; + const pkgUrl = `${registry}/v1/modules/${repository}`; const cachedResult = await renovateCache.get(cacheNamespace, pkgUrl); // istanbul ignore if if (cachedResult) { @@ -33,13 +54,13 @@ async function getPkgReleases(purl, config) { retry: 5, })).body; const returnedName = res.namespace + '/' + res.name + '/' + res.provider; - if (returnedName !== dependency) { + if (returnedName !== repository) { logger.warn({ pkgUrl }, 'Terraform registry result mismatch'); return null; } // Simplify response before caching and returning const dep = { - name: dependency, + name: repository, versions: {}, }; if (res.source) { @@ -49,7 +70,7 @@ async function getPkgReleases(purl, config) { version, })); if (pkgUrl.startsWith('https://registry.terraform.io/')) { - dep.homepage = `https://registry.terraform.io/modules/${dependency}`; + dep.homepage = `https://registry.terraform.io/modules/${repository}`; } logger.trace({ dep }, 'dep'); const cacheMinutes = 30; @@ -58,7 +79,7 @@ async function getPkgReleases(purl, config) { } catch (err) { if (err.statusCode === 404 || err.code === 'ENOTFOUND') { logger.info( - { dependency }, + { dependency: purl.lookupName }, `Terraform registry lookup failure: not found` ); logger.debug({ @@ -67,7 +88,7 @@ async function getPkgReleases(purl, config) { return null; } logger.warn( - { err, dependency }, + { err, dependency: purl.lookupName }, 'Terraform registry failure: Unknown error' ); return null; diff --git a/lib/manager/terraform/extract.js b/lib/manager/terraform/extract.js index d89570b343b230b21b633a33cea955fe094fa131..574948f303fee425ad87fffcd6097f1d604aab1b 100644 --- a/lib/manager/terraform/extract.js +++ b/lib/manager/terraform/extract.js @@ -63,19 +63,12 @@ function extractPackageFile(content) { const moduleParts = dep.source.split('//')[0].split('/'); if (moduleParts[0] === '..') { dep.skipReason = 'local'; - } else if (moduleParts.length === 3) { + } else if (moduleParts.length >= 3) { dep.depType = 'terraform'; dep.depName = moduleParts.join('/'); dep.depNameShort = dep.depName; dep.lineNumber = dep.versionLine; dep.purl = 'pkg:terraform/' + dep.depName; - } else if (moduleParts.length === 4) { - dep.depType = 'terraform'; - dep.registryUrls = ['https://' + moduleParts.shift()]; - dep.depName = moduleParts.join('/'); - dep.depNameShort = dep.depName; - dep.lineNumber = dep.versionLine; - dep.purl = 'pkg:terraform/' + dep.depName; } if (dep.lineNumber) { if (!isValid(dep.currentValue)) { diff --git a/test/datasource/__snapshots__/terraform.spec.js.snap b/test/datasource/__snapshots__/terraform.spec.js.snap index b71e351eccded5c859b462fe7e646e5bf28049d0..c8391673decc4c94584bf1cec20d8f95f334d1bc 100644 --- a/test/datasource/__snapshots__/terraform.spec.js.snap +++ b/test/datasource/__snapshots__/terraform.spec.js.snap @@ -79,3 +79,83 @@ Object { "versions": Object {}, } `; + +exports[`datasource/terraform getPkgReleases processes with registry in name 1`] = ` +Object { + "homepage": "https://registry.terraform.io/modules/hashicorp/consul/aws", + "name": "hashicorp/consul/aws", + "releases": Array [ + Object { + "version": "0.0.1", + }, + Object { + "version": "0.0.2", + }, + Object { + "version": "0.0.3", + }, + Object { + "version": "0.0.4", + }, + Object { + "version": "0.0.5", + }, + Object { + "version": "0.1.0", + }, + Object { + "version": "0.1.1", + }, + Object { + "version": "0.1.2", + }, + Object { + "version": "0.2.0", + }, + Object { + "version": "0.2.1", + }, + Object { + "version": "0.2.2", + }, + Object { + "version": "0.3.0", + }, + Object { + "version": "0.3.1", + }, + Object { + "version": "0.3.2", + }, + Object { + "version": "0.3.3", + }, + Object { + "version": "0.3.4", + }, + Object { + "version": "0.3.5", + }, + Object { + "version": "0.3.6", + }, + Object { + "version": "0.3.7", + }, + Object { + "version": "0.3.8", + }, + Object { + "version": "0.3.9", + }, + Object { + "version": "0.3.10", + }, + Object { + "version": "0.4.0", + }, + ], + "sourceUrl": "https://github.com/hashicorp/terraform-aws-consul", + "versions": Object {}, +} +`; diff --git a/test/datasource/terraform.spec.js b/test/datasource/terraform.spec.js index 7d80c865cef67ac9edebfa8e855f65a17748d36e..4131703f022d071ecabd68201ba1ccad0463bdad 100644 --- a/test/datasource/terraform.spec.js +++ b/test/datasource/terraform.spec.js @@ -55,17 +55,24 @@ describe('datasource/terraform', () => { expect(res).toMatchSnapshot(); expect(res).not.toBeNull(); }); + it('processes with registry in name', async () => { + got.mockReturnValueOnce({ + body: JSON.parse(consulData), + }); + const res = await datasource.getPkgReleases({ + purl: 'pkg:terraform/registry.terraform.io/hashicorp/consul/aws', + }); + expect(res).toMatchSnapshot(); + expect(res).not.toBeNull(); + }); it('rejects mismatch', async () => { got.mockReturnValueOnce({ body: JSON.parse(consulData), }); - const config = { registryUrls: 'https://terraform.company.com' }; - const res = await datasource.getPkgReleases( - { - purl: 'pkg:terraform/consul/foo', - }, - config - ); + const res = await datasource.getPkgReleases({ + purl: 'pkg:terraform/consul/foo', + registryUrls: ['https://terraform.company.com'], + }); expect(res).toBeNull(); }); }); diff --git a/test/manager/terraform/__snapshots__/extract.spec.js.snap b/test/manager/terraform/__snapshots__/extract.spec.js.snap index cb4879e5eca19aefea4e6fb99b279e5575df5823..fad516ed5988bd79a64743c6736cf3681c9bb6f6 100644 --- a/test/manager/terraform/__snapshots__/extract.spec.js.snap +++ b/test/manager/terraform/__snapshots__/extract.spec.js.snap @@ -86,41 +86,32 @@ Object { }, Object { "currentValue": "~> 1.1.0", - "depName": "example-corp/k8s-cluster/azurerm", - "depNameShort": "example-corp/k8s-cluster/azurerm", + "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", + "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm", "depType": "terraform", "lineNumber": 71, "moduleName": "consul", - "purl": "pkg:terraform/example-corp/k8s-cluster/azurerm", - "registryUrls": Array [ - "https://app.terraform.io", - ], + "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm", "source": "app.terraform.io/example-corp/k8s-cluster/azurerm", }, Object { "currentValue": "~> 1.1", - "depName": "example-corp/k8s-cluster/azurerm", - "depNameShort": "example-corp/k8s-cluster/azurerm", + "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", + "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm", "depType": "terraform", "lineNumber": 76, "moduleName": "consul2", - "purl": "pkg:terraform/example-corp/k8s-cluster/azurerm", - "registryUrls": Array [ - "https://app.terraform.io", - ], + "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm", "source": "app.terraform.io/example-corp/k8s-cluster/azurerm", }, Object { "currentValue": "~~ 1.1", - "depName": "example-corp/k8s-cluster/azurerm", - "depNameShort": "example-corp/k8s-cluster/azurerm", + "depName": "app.terraform.io/example-corp/k8s-cluster/azurerm", + "depNameShort": "app.terraform.io/example-corp/k8s-cluster/azurerm", "depType": "terraform", "lineNumber": 81, "moduleName": "consul3", - "purl": "pkg:terraform/example-corp/k8s-cluster/azurerm", - "registryUrls": Array [ - "https://app.terraform.io", - ], + "purl": "pkg:terraform/app.terraform.io/example-corp/k8s-cluster/azurerm", "skipReason": "unsupported-version", "source": "app.terraform.io/example-corp/k8s-cluster/azurerm", },