From 8184bda9b672f1f22a5444983b336d8c44575b39 Mon Sep 17 00:00:00 2001
From: Andrei Nistor <andrei_nistor@smart-x.net>
Date: Wed, 17 Nov 2021 17:04:26 +0200
Subject: [PATCH] feat(manager/kustomize):  support HelmChartInflationGenerator
 (#12628)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---
 .../__fixtures__/kustomizeHelmChart.yaml      | 15 +++++++
 .../__snapshots__/extract.spec.ts.snap        | 16 +++++++
 lib/manager/kustomize/extract.spec.ts         | 42 +++++++++++++++++++
 lib/manager/kustomize/extract.ts              | 29 ++++++++++++-
 lib/manager/kustomize/readme.md               | 11 +++--
 lib/manager/kustomize/types.ts                |  8 ++++
 6 files changed, 116 insertions(+), 5 deletions(-)
 create mode 100644 lib/manager/kustomize/__fixtures__/kustomizeHelmChart.yaml

diff --git a/lib/manager/kustomize/__fixtures__/kustomizeHelmChart.yaml b/lib/manager/kustomize/__fixtures__/kustomizeHelmChart.yaml
new file mode 100644
index 0000000000..56f4887e4a
--- /dev/null
+++ b/lib/manager/kustomize/__fixtures__/kustomizeHelmChart.yaml
@@ -0,0 +1,15 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+helmCharts:
+- name: minecraft
+  includeCRDs: false
+  valuesInline:
+    minecraftServer:
+      eula: true
+      difficulty: hard
+      rcon:
+        enabled: true
+  releaseName: moria
+  version: 3.1.3
+  repo: https://itzg.github.io/minecraft-server-charts
diff --git a/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap b/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
index 4d78020fb5..945e568313 100644
--- a/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
+++ b/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
@@ -160,6 +160,22 @@ Array [
 ]
 `;
 
+exports[`manager/kustomize/extract extractPackageFile() parses helmChart field 1`] = `
+Object {
+  "deps": Array [
+    Object {
+      "currentValue": "3.1.3",
+      "datasource": "helm",
+      "depName": "minecraft",
+      "depType": "HelmChart",
+      "registryUrls": Array [
+        "https://itzg.github.io/minecraft-server-charts",
+      ],
+    },
+  ],
+}
+`;
+
 exports[`manager/kustomize/extract extractPackageFile() should extract bases resources and components from their respective blocks 1`] = `
 Array [
   Object {
diff --git a/lib/manager/kustomize/extract.spec.ts b/lib/manager/kustomize/extract.spec.ts
index 77437cd778..56c99b733d 100644
--- a/lib/manager/kustomize/extract.spec.ts
+++ b/lib/manager/kustomize/extract.spec.ts
@@ -2,8 +2,10 @@ import { loadFixture } from '../../../test/util';
 import * as datasourceDocker from '../../datasource/docker';
 import { GitTagsDatasource } from '../../datasource/git-tags';
 import * as datasourceGitHubTags from '../../datasource/github-tags';
+import { HelmDatasource } from '../../datasource/helm';
 import { SkipReason } from '../../types';
 import {
+  extractHelmChart,
   extractImage,
   extractPackageFile,
   extractResource,
@@ -22,6 +24,7 @@ const kustomizeComponent = loadFixture('component.yaml');
 const newTag = loadFixture('newTag.yaml');
 const newName = loadFixture('newName.yaml');
 const digest = loadFixture('digest.yaml');
+const kustomizeHelmChart = loadFixture('kustomizeHelmChart.yaml');
 
 describe('manager/kustomize/extract', () => {
   it('should successfully parse a valid kustomize file', () => {
@@ -119,6 +122,31 @@ describe('manager/kustomize/extract', () => {
       expect(pkg).toEqual(sample);
     });
   });
+  describe('extractHelmChart', () => {
+    it('should return null on a null input', () => {
+      const pkg = extractHelmChart({
+        name: null,
+        repo: null,
+        version: null,
+      });
+      expect(pkg).toBeNull();
+    });
+    it('should correctly extract a chart', () => {
+      const registryUrl = 'https://docs.renovatebot.com/helm-charts';
+      const sample = {
+        depName: 'renovate',
+        currentValue: '29.6.0',
+        registryUrls: [registryUrl],
+        datasource: HelmDatasource.id,
+      };
+      const pkg = extractHelmChart({
+        name: sample.depName,
+        version: sample.currentValue,
+        repo: registryUrl,
+      });
+      expect(pkg).toEqual(sample);
+    });
+  });
   describe('image extraction', () => {
     it('should return null on a null input', () => {
       const pkg = extractImage({
@@ -346,5 +374,19 @@ describe('manager/kustomize/extract', () => {
         ],
       });
     });
+
+    it('parses helmChart field', () => {
+      const res = extractPackageFile(kustomizeHelmChart);
+      expect(res).toMatchSnapshot({
+        deps: [
+          {
+            depType: 'HelmChart',
+            depName: 'minecraft',
+            currentValue: '3.1.3',
+            registryUrls: ['https://itzg.github.io/minecraft-server-charts'],
+          },
+        ],
+      });
+    });
   });
 });
diff --git a/lib/manager/kustomize/extract.ts b/lib/manager/kustomize/extract.ts
index f012353296..df09e194ee 100644
--- a/lib/manager/kustomize/extract.ts
+++ b/lib/manager/kustomize/extract.ts
@@ -3,12 +3,13 @@ import { load } from 'js-yaml';
 import * as datasourceDocker from '../../datasource/docker';
 import { GitTagsDatasource } from '../../datasource/git-tags';
 import * as datasourceGitHubTags from '../../datasource/github-tags';
+import { HelmDatasource } from '../../datasource/helm';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { regEx } from '../../util/regex';
 import { splitImageParts } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
-import type { Image, Kustomize } from './types';
+import type { HelmChart, Image, Kustomize } from './types';
 
 // URL specifications should follow the hashicorp URL format
 // https://github.com/hashicorp/go-getter#url-format
@@ -106,6 +107,21 @@ export function extractImage(image: Image): PackageDependency | null {
   return null;
 }
 
+export function extractHelmChart(
+  helmChart: HelmChart
+): PackageDependency | null {
+  if (!helmChart.name) {
+    return null;
+  }
+
+  return {
+    depName: helmChart.name,
+    currentValue: helmChart.version,
+    registryUrls: [helmChart.repo],
+    datasource: HelmDatasource.id,
+  };
+}
+
 export function parseKustomize(content: string): Kustomize | null {
   let pkg: Kustomize | null = null;
   try {
@@ -178,6 +194,17 @@ export function extractPackageFile(content: string): PackageFile | null {
     }
   }
 
+  // grab the helm charts
+  for (const helmChart of pkg.helmCharts ?? []) {
+    const dep = extractHelmChart(helmChart);
+    if (dep) {
+      deps.push({
+        ...dep,
+        depType: 'HelmChart',
+      });
+    }
+  }
+
   if (!deps.length) {
     return null;
   }
diff --git a/lib/manager/kustomize/readme.md b/lib/manager/kustomize/readme.md
index 7defd474b6..ae135b4628 100644
--- a/lib/manager/kustomize/readme.md
+++ b/lib/manager/kustomize/readme.md
@@ -1,20 +1,23 @@
-This package will manage two parts of the `kustomization.yaml` file:
+This package will manage the following parts of the `kustomization.yaml` file:
 
-1. [remote bases](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md)
+1. [remote resources](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md)
 2. [image tags](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/image.md)
 3. [components](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/components.md)
+4. [helm charts](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/chart.md)
+5. [remote bases](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/remoteBuild.md) (deprecated since kustomize v2.1.0)
 
 **How It Works**
 
 1. Renovate will search each repository for any `kustomization.yaml` files.
-2. Existing dependencies will be extracted from remote bases & image tags
+2. Existing dependencies will be extracted from remote bases, image tags & helm charts
 3. Renovate will resolve the dependency's source repository and check for SemVer tags if found.
 4. If an update was found, Renovate will update `kustomization.yaml`
 
-This manager uses two `depType`s to allow a fine-grained control of which dependencies are upgraded:
+This manager uses three `depType`s to allow a fine-grained control of which dependencies are upgraded:
 
 - Component
 - Kustomization
+- HelmChart
 
 **Limitations**
 
diff --git a/lib/manager/kustomize/types.ts b/lib/manager/kustomize/types.ts
index d7a7c096e9..22e0ef5738 100644
--- a/lib/manager/kustomize/types.ts
+++ b/lib/manager/kustomize/types.ts
@@ -4,10 +4,18 @@ export interface Image {
   newName?: string;
   digest?: string;
 }
+
+export interface HelmChart {
+  name: string;
+  repo: string;
+  version: string;
+}
+
 export interface Kustomize {
   kind: string;
   bases?: string[]; // deprecated since kustomize v2.1.0
   resources?: string[];
   components?: string[];
   images?: Image[];
+  helmCharts?: HelmChart[];
 }
-- 
GitLab