diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 6b01f12bebe36b..d18d6dd44335e8 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -3140,6 +3140,7 @@ This feature works with the following managers: - [`kubernetes`](/modules/manager/kubernetes) - [`ansible`](/modules/manager/ansible) - [`droneci`](/modules/manager/droneci) +- [`terraform`](/modules/manager/terraform) ## registryUrls diff --git a/lib/modules/manager/dockerfile/extract.ts b/lib/modules/manager/dockerfile/extract.ts index 45a6fc56cf4e51..f62f281bf28198 100644 --- a/lib/modules/manager/dockerfile/extract.ts +++ b/lib/modules/manager/dockerfile/extract.ts @@ -182,7 +182,7 @@ export function getDep( ...getDep(`${value}/${groups.depName}`), replaceString: currentFrom, }; - dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep)!; + dep.autoReplaceStringTemplate = getAutoReplaceTemplate(dep); return dep; } } diff --git a/lib/modules/manager/terraform/__fixtures__/docker.tf b/lib/modules/manager/terraform/__fixtures__/docker.tf index de04d0cd91d607..4490a11bff41ea 100644 --- a/lib/modules/manager/terraform/__fixtures__/docker.tf +++ b/lib/modules/manager/terraform/__fixtures__/docker.tf @@ -12,6 +12,10 @@ resource "docker_image" "ignore_variable" { pull_triggers = ["${data.docker_registry_image.ubuntu.sha256_digest}"] } +resource "docker_image" "proxy" { + name = "hub.proxy.test/bitnami/nginx:1.24.0" +} + # docker_container resources # https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs/resources/container diff --git a/lib/modules/manager/terraform/__fixtures__/helm.tf b/lib/modules/manager/terraform/__fixtures__/helm.tf index 6cae1674acbcaf..bef91bd3c646a3 100644 --- a/lib/modules/manager/terraform/__fixtures__/helm.tf +++ b/lib/modules/manager/terraform/__fixtures__/helm.tf @@ -53,3 +53,11 @@ resource "helm_release" "karpenter_oci_repo" { chart = "karpenter" version = "v0.22.1" } + +## chart in OCI registry +resource "helm_release" "proxy_oci_repo" { + name = "kube-prometheus" + repository = "oci://hub.proxy.test/bitnamicharts" + chart = "kube-prometheus" + version = "8.9.1" +} diff --git a/lib/modules/manager/terraform/base.ts b/lib/modules/manager/terraform/base.ts index 274052535b94aa..4947f14f8ddb8d 100644 --- a/lib/modules/manager/terraform/base.ts +++ b/lib/modules/manager/terraform/base.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import { regEx } from '../../../util/regex'; import { TerraformProviderDatasource } from '../../datasource/terraform-provider'; -import type { PackageDependency } from '../types'; +import type { ExtractConfig, PackageDependency } from '../types'; import type { TerraformDefinitionFile } from './hcl/types'; import type { ProviderLock } from './lockfile/types'; import { getLockedVersion, massageProviderLookupName } from './util'; @@ -20,7 +20,8 @@ export abstract class DependencyExtractor { */ abstract extract( hclRoot: TerraformDefinitionFile, - locks: ProviderLock[] + locks: ProviderLock[], + config: ExtractConfig ): PackageDependency[]; } diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts index 62d7b53f00a3dd..c4e8246a9adc16 100644 --- a/lib/modules/manager/terraform/extract.spec.ts +++ b/lib/modules/manager/terraform/extract.spec.ts @@ -401,8 +401,10 @@ describe('modules/manager/terraform/extract', () => { }); it('extracts docker resources', async () => { - const res = await extractPackageFile(docker, 'docker.tf', {}); - expect(res?.deps).toHaveLength(6); + const res = await extractPackageFile(docker, 'docker.tf', { + registryAliases: { 'hub.proxy.test': 'index.docker.io' }, + }); + expect(res?.deps).toHaveLength(7); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(3); expect(res?.deps).toMatchObject([ { @@ -426,6 +428,15 @@ describe('modules/manager/terraform/extract', () => { depType: 'docker_image', replaceString: 'nginx:1.7.8', }, + { + autoReplaceStringTemplate: + 'hub.proxy.test/bitnami/nginx:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '1.24.0', + datasource: 'docker', + depName: 'index.docker.io/bitnami/nginx', + depType: 'docker_image', + replaceString: 'hub.proxy.test/bitnami/nginx:1.24.0', + }, { autoReplaceStringTemplate: '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', @@ -574,8 +585,10 @@ describe('modules/manager/terraform/extract', () => { }); it('extract helm releases', async () => { - const res = await extractPackageFile(helm, 'helm.tf', {}); - expect(res?.deps).toHaveLength(8); + const res = await extractPackageFile(helm, 'helm.tf', { + registryAliases: { 'hub.proxy.test': 'index.docker.io' }, + }); + expect(res?.deps).toHaveLength(9); expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(2); expect(res?.deps).toMatchObject([ { @@ -617,6 +630,13 @@ describe('modules/manager/terraform/extract', () => { depType: 'helm_release', skipReason: 'local-chart', }, + { + currentValue: '8.9.1', + datasource: 'docker', + depName: 'kube-prometheus', + depType: 'helm_release', + packageName: 'index.docker.io/bitnamicharts/kube-prometheus', + }, { currentValue: '1.0.1', datasource: 'helm', diff --git a/lib/modules/manager/terraform/extract.ts b/lib/modules/manager/terraform/extract.ts index e15cc17af3d58b..ef6ac343891362 100644 --- a/lib/modules/manager/terraform/extract.ts +++ b/lib/modules/manager/terraform/extract.ts @@ -46,7 +46,7 @@ export async function extractPackageFile( const locks = await extractLocksForPackageFile(fileName); for (const extractor of passedExtractors) { - const deps = extractor.extract(hclMap, locks); + const deps = extractor.extract(hclMap, locks, config); dependencies.push(...deps); } diff --git a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts index dc8e78c5e1f8a8..6d48a30c6a27d2 100644 --- a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts +++ b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.spec.ts @@ -4,7 +4,7 @@ describe('modules/manager/terraform/extractors/resources/generic-docker-image-re const extractor = new GenericDockerImageRefExtractor(); it('return empty array if no resource is found', () => { - const res = extractor.extract({}); + const res = extractor.extract({}, [], {}); expect(res).toBeArrayOfSize(0); }); }); diff --git a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts index eb3f4c97d92628..7e89f12fd8200e 100644 --- a/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts +++ b/lib/modules/manager/terraform/extractors/resources/generic-docker-image-ref.ts @@ -1,8 +1,9 @@ import is from '@sindresorhus/is'; import { getDep } from '../../../dockerfile/extract'; -import type { PackageDependency } from '../../../types'; +import type { ExtractConfig, PackageDependency } from '../../../types'; import { DependencyExtractor } from '../../base'; import type { TerraformDefinitionFile } from '../../hcl/types'; +import type { ProviderLock } from '../../lockfile/types'; import { generic_image_resource } from './utils'; export class GenericDockerImageRefExtractor extends DependencyExtractor { @@ -10,7 +11,11 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { return generic_image_resource.map((value) => `"${value.type}"`); } - extract(hclMap: TerraformDefinitionFile): PackageDependency[] { + extract( + hclMap: TerraformDefinitionFile, + _locks: ProviderLock[], + config: ExtractConfig + ): PackageDependency[] { const resourceTypMap = hclMap.resource; if (is.nullOrUndefined(resourceTypMap)) { return []; @@ -28,7 +33,9 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { // loop over instances of a resource type for (const instance of Object.values(resourceInstancesMap).flat()) { - dependencies.push(...this.walkPath({ depType: type }, instance, path)); + dependencies.push( + ...this.walkPath({ depType: type }, instance, path, config) + ); } } return dependencies; @@ -45,7 +52,8 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { private walkPath( abstractDep: PackageDependency, parentElement: unknown, - leftPath: string[] + leftPath: string[], + config: ExtractConfig ): PackageDependency[] { const dependencies: PackageDependency[] = []; // if there are no path elements left, we have reached the end of the path @@ -59,7 +67,7 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { }, ]; } - const test = getDep(parentElement); + const test = getDep(parentElement, true, config.registryAliases); const dep: PackageDependency = { ...abstractDep, ...test, @@ -87,11 +95,11 @@ export class GenericDockerImageRefExtractor extends DependencyExtractor { if (is.array(element)) { for (const arrayElement of element) { dependencies.push( - ...this.walkPath(abstractDep, arrayElement, leftPath.slice(1)) + ...this.walkPath(abstractDep, arrayElement, leftPath.slice(1), config) ); } return dependencies; } - return this.walkPath(abstractDep, element, leftPath.slice(1)); + return this.walkPath(abstractDep, element, leftPath.slice(1), config); } } diff --git a/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts b/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts index 84f2451c8030bb..7c89c540df6adb 100644 --- a/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts +++ b/lib/modules/manager/terraform/extractors/resources/helm-release.spec.ts @@ -4,7 +4,7 @@ describe('modules/manager/terraform/extractors/resources/helm-release', () => { const extractor = new HelmReleaseExtractor(); it('return empty array if no resource is found', () => { - const res = extractor.extract({}); + const res = extractor.extract({}, [], {}); expect(res).toBeArrayOfSize(0); }); }); diff --git a/lib/modules/manager/terraform/extractors/resources/helm-release.ts b/lib/modules/manager/terraform/extractors/resources/helm-release.ts index c0c54a3b20ce8f..4e2ec94052ff35 100644 --- a/lib/modules/manager/terraform/extractors/resources/helm-release.ts +++ b/lib/modules/manager/terraform/extractors/resources/helm-release.ts @@ -1,12 +1,13 @@ import is from '@sindresorhus/is'; import { logger } from '../../../../../logger'; import { joinUrlParts } from '../../../../../util/url'; -import { DockerDatasource } from '../../../../datasource/docker'; import { HelmDatasource } from '../../../../datasource/helm'; +import { getDep } from '../../../dockerfile/extract'; import { isOCIRegistry } from '../../../helmv3/utils'; -import type { PackageDependency } from '../../../types'; +import type { ExtractConfig, PackageDependency } from '../../../types'; import { DependencyExtractor } from '../../base'; import type { TerraformDefinitionFile } from '../../hcl/types'; +import type { ProviderLock } from '../../lockfile/types'; import { checkIfStringIsPath } from '../../util'; export class HelmReleaseExtractor extends DependencyExtractor { @@ -14,7 +15,11 @@ export class HelmReleaseExtractor extends DependencyExtractor { return [`"helm_release"`]; } - override extract(hclMap: TerraformDefinitionFile): PackageDependency[] { + override extract( + hclMap: TerraformDefinitionFile, + _locks: ProviderLock[], + config: ExtractConfig + ): PackageDependency[] { const dependencies = []; const helmReleases = hclMap?.resource?.helm_release; @@ -46,19 +51,20 @@ export class HelmReleaseExtractor extends DependencyExtractor { } else if (isOCIRegistry(helmRelease.chart)) { // For oci charts, we remove the oci:// and use the docker datasource dep.depName = helmRelease.chart.replace('oci://', ''); - dep.datasource = DockerDatasource.id; + this.processOCI(dep.depName, config, dep); } else if (checkIfStringIsPath(helmRelease.chart)) { dep.skipReason = 'local-chart'; } else if (is.nonEmptyString(helmRelease.repository)) { if (isOCIRegistry(helmRelease.repository)) { - { - // For oci repos, we remove the oci://, join the chart name and use the docker datasource - dep.packageName = joinUrlParts( + // For oci charts, we remove the oci:// and use the docker datasource + this.processOCI( + joinUrlParts( helmRelease.repository.replace('oci://', ''), helmRelease.chart - ); - dep.datasource = DockerDatasource.id; - } + ), + config, + dep + ); } else { dep.registryUrls = [helmRelease.repository]; } @@ -67,4 +73,18 @@ export class HelmReleaseExtractor extends DependencyExtractor { return dependencies; } + + private processOCI( + depName: string, + config: ExtractConfig, + dep: PackageDependency + ): void { + const { depName: packageName, datasource } = getDep( + depName, + false, + config.registryAliases + ); + dep.packageName = packageName; + dep.datasource = datasource; + } }