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

feat: kustomize image digests #11153

Merged
merged 28 commits into from Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
37ff2c6
kustomize: parse digest
thepwagner Aug 7, 2021
ff741d2
kustomize: parse tag@digest images
thepwagner Aug 7, 2021
bdfb160
kustomize: reject newTag+digest
thepwagner Aug 11, 2021
653e0a3
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 11, 2021
73c7c50
prefer assertions to snapshots, simplify
thepwagner Aug 11, 2021
186ea48
mitigate URL injection
thepwagner Aug 12, 2021
fe83a06
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 12, 2021
c7d6f75
extract from newName
thepwagner Aug 12, 2021
664ea41
kustomize: readme incl digests
thepwagner Aug 12, 2021
d534267
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 12, 2021
4e50cc2
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 14, 2021
d2c3518
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 20, 2021
d674978
port new tests to snapshot style
thepwagner Aug 20, 2021
04f742f
Apply suggestions from code review
thepwagner Aug 26, 2021
0a6ffc7
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 26, 2021
1b1591e
Merge remote-tracking branch 'origin/renovate-8089' into renovate-8089
thepwagner Aug 26, 2021
c151d70
Apply suggestions from code review
thepwagner Aug 31, 2021
7af254a
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Aug 31, 2021
1def28a
docker versioning is default for docker source
thepwagner Aug 31, 2021
815f191
Apply suggestions from code review
viceice Sep 6, 2021
b9bc262
Merge branch 'main' into renovate-8089
viceice Sep 6, 2021
6bfdbf0
Merge remote-tracking branch 'renovatebot/main' into renovate-8089
thepwagner Sep 6, 2021
39a33ec
prettier-fix
thepwagner Sep 6, 2021
548564a
Merge branch 'main' into renovate-8089
thepwagner Sep 8, 2021
2a93562
Merge branch 'main' into renovate-8089
rarkins Sep 10, 2021
ee4fab2
Update lib/manager/kustomize/readme.md
viceice Sep 10, 2021
ae23c5f
Merge branch 'main' into renovate-8089
viceice Sep 10, 2021
ef7a87f
Merge branch 'main' into renovate-8089
viceice Sep 10, 2021
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
18 changes: 18 additions & 0 deletions lib/manager/kustomize/__fixtures__/digest.yaml
@@ -0,0 +1,18 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: hasura
images:
- name: postgres
digest: sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
- name: postgres:11
digest: sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
# invalid - includes newTag and digest
- name: postgres
newTag: 11
digest: sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
# invalid - not a string
- name: postgres
digest: 02641143766
# invalid - missing prefix
- name: postgres
digest: b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
10 changes: 10 additions & 0 deletions lib/manager/kustomize/__fixtures__/newName.yaml
@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: hasura
images:
- name: postgres
newName: awesome/postgres:11@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
- name: postgres
newName: awesome/postgres:11
- name: postgres
newName: awesome/postgres@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
11 changes: 11 additions & 0 deletions lib/manager/kustomize/__fixtures__/newTag.yaml
@@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: hasura
images:
- name: postgres
newTag: "11"
- name: postgres
newTag: 11@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
# invalid - renders as `postgres:sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c`
- name: postgres
newTag: sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c
17 changes: 0 additions & 17 deletions lib/manager/kustomize/__fixtures__/sha.yaml

This file was deleted.

89 changes: 86 additions & 3 deletions lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
@@ -1,5 +1,72 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`manager/kustomize/extract extractPackageFile() extracts from digest 1`] = `
Object {
"deps": Array [
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": undefined,
"datasource": "docker",
"depName": "postgres",
"replaceString": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"versioning": "docker",
},
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": "11",
"datasource": "docker",
"depName": "postgres",
"replaceString": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"versioning": "docker",
},
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": 11,
"depName": "postgres",
"skipReason": "invalid-dependency-specification",
},
Object {
"currentValue": 2641143766,
"depName": "postgres",
"skipReason": "invalid-value",
},
Object {
"currentValue": "b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"depName": "postgres",
"skipReason": "invalid-value",
},
],
}
`;

exports[`manager/kustomize/extract extractPackageFile() extracts from newTag 1`] = `
Object {
"deps": Array [
Object {
"currentDigest": undefined,
"currentValue": "11",
"datasource": "docker",
"depName": "postgres",
"replaceString": "11",
"versioning": "docker",
},
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": "11",
"datasource": "docker",
"depName": "postgres",
"replaceString": "11@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"versioning": "docker",
},
Object {
"currentValue": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"depName": "postgres",
"skipReason": "invalid-value",
},
],
}
`;

exports[`manager/kustomize/extract extractPackageFile() extracts http dependency 1`] = `
Array [
Object {
Expand Down Expand Up @@ -32,15 +99,31 @@ Array [
]
`;

exports[`manager/kustomize/extract extractPackageFile() extracts sha256 instead of tag 1`] = `
exports[`manager/kustomize/extract extractPackageFile() extracts newName 1`] = `
Object {
"deps": Array [
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": "11",
"datasource": "docker",
"depName": "awesome/postgres",
"replaceString": "awesome/postgres:11@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"versioning": "docker",
},
Object {
"currentDigest": undefined,
"currentValue": "11",
"datasource": "docker",
"depName": "awesome/postgres",
"replaceString": "awesome/postgres:11",
"versioning": "docker",
},
Object {
"currentDigest": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"currentValue": undefined,
"datasource": "docker",
"depName": "postgres",
"replaceString": "sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"depName": "awesome/postgres",
"replaceString": "awesome/postgres@sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c",
"versioning": "docker",
},
],
Expand Down
71 changes: 66 additions & 5 deletions lib/manager/kustomize/extract.spec.ts
Expand Up @@ -19,7 +19,9 @@ const kustomizeWithLocal = loadFixture('kustomizeWithLocal.yaml');
const nonKustomize = loadFixture('service.yaml');
const gitImages = loadFixture('gitImages.yaml');
const kustomizeDepsInResources = loadFixture('depsInResources.yaml');
const sha = loadFixture('sha.yaml');
const newTag = loadFixture('newTag.yaml');
const newName = loadFixture('newName.yaml');
const digest = loadFixture('digest.yaml');

describe('manager/kustomize/extract', () => {
it('should successfully parse a valid kustomize file', () => {
Expand Down Expand Up @@ -251,13 +253,72 @@ describe('manager/kustomize/extract', () => {
expect(res.deps[1].currentValue).toEqual('1.19.0');
expect(res.deps[1].depName).toEqual('fluxcd/flux');
});
it('extracts sha256 instead of tag', () => {
expect(extractPackageFile(sha)).toMatchSnapshot({
const postgresDigest =
'sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c';
it('extracts from newTag', () => {
viceice marked this conversation as resolved.
Show resolved Hide resolved
expect(extractPackageFile(newTag)).toMatchSnapshot({
deps: [
{
currentDigest:
'sha256:b0cfe264cb1143c7c660ddfd5c482464997d62d6bc9f97f8fdf3deefce881a8c',
currentDigest: undefined,
currentValue: '11',
replaceString: '11',
},
{
currentDigest: postgresDigest,
currentValue: '11',
replaceString: `11@${postgresDigest}`,
},
{
skipReason: SkipReason.InvalidValue,
},
],
});
});
it('extracts from digest', () => {
viceice marked this conversation as resolved.
Show resolved Hide resolved
expect(extractPackageFile(digest)).toMatchSnapshot({
deps: [
{
currentDigest: postgresDigest,
currentValue: undefined,
replaceString: postgresDigest,
},
{
currentDigest: postgresDigest,
currentValue: '11',
replaceString: postgresDigest,
},
{
skipReason: SkipReason.InvalidDependencySpecification,
},
{
skipReason: SkipReason.InvalidValue,
},
{
skipReason: SkipReason.InvalidValue,
},
],
});
});
it('extracts newName', () => {
viceice marked this conversation as resolved.
Show resolved Hide resolved
expect(extractPackageFile(newName)).toMatchSnapshot({
deps: [
{
depName: 'awesome/postgres',
currentDigest: postgresDigest,
currentValue: '11',
replaceString: `awesome/postgres:11@${postgresDigest}`,
},
{
depName: 'awesome/postgres',
currentDigest: undefined,
currentValue: '11',
replaceString: 'awesome/postgres:11',
},
{
depName: 'awesome/postgres',
currentDigest: postgresDigest,
currentValue: undefined,
replaceString: `awesome/postgres@${postgresDigest}`,
},
],
});
Expand Down
78 changes: 59 additions & 19 deletions lib/manager/kustomize/extract.ts
Expand Up @@ -6,6 +6,7 @@ import * as datasourceGitHubTags from '../../datasource/github-tags';
import { logger } from '../../logger';
import { SkipReason } from '../../types';
import * as dockerVersioning from '../../versioning/docker';
thepwagner marked this conversation as resolved.
Show resolved Hide resolved
import { splitImageParts } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types';
import type { Image, Kustomize } from './types';

Expand All @@ -21,7 +22,8 @@ export function extractBase(base: string): PackageDependency | null {
return null;
}

if (match?.groups.path.startsWith('github.com')) {
const { path } = match.groups;
if (path.startsWith('github.com:') || path.startsWith('github.com/')) {
viceice marked this conversation as resolved.
Show resolved Hide resolved
return {
currentValue: match.groups.currentValue,
datasource: datasourceGitHubTags.id,
Expand All @@ -31,40 +33,78 @@ export function extractBase(base: string): PackageDependency | null {

return {
datasource: datasourceGitTags.id,
depName: match.groups.path.replace('.git', ''),
depName: path.replace('.git', ''),
lookupName: match.groups.url,
currentValue: match.groups.currentValue,
};
}

export function extractImage(image: Image): PackageDependency | null {
if (image?.name && image.newTag) {
const replaceString = image.newTag;
let currentValue: string | undefined;
let currentDigest: string | undefined;
if (!is.string(replaceString)) {
if (!image.name) {
return null;
}
const nameDep = splitImageParts(image.newName ?? image.name);
const { depName } = nameDep;
const { digest, newTag } = image;
if (digest && newTag) {
logger.warn(
{ newTag, digest },
'Kustomize ignores newTag when digest is provided. Pick one, or use `newTag: tag@digest`'
);
return {
depName,
currentValue: newTag,
currentDigest: digest,
skipReason: SkipReason.InvalidDependencySpecification,
};
}

if (digest) {
if (!is.string(digest) || !digest.startsWith('sha256:')) {
return {
depName: image.newName ?? image.name,
currentValue: replaceString,
depName,
currentValue: digest,
skipReason: SkipReason.InvalidValue,
};
}
if (replaceString.startsWith('sha256:')) {
currentDigest = replaceString;
currentValue = undefined;
} else {
currentValue = replaceString;
}

return {
datasource: datasourceDocker.id,
viceice marked this conversation as resolved.
Show resolved Hide resolved
versioning: dockerVersioning.id,
thepwagner marked this conversation as resolved.
Show resolved Hide resolved
depName: image.newName ?? image.name,
currentValue,
currentDigest,
replaceString,
depName,
currentValue: nameDep.currentValue,
currentDigest: digest,
replaceString: digest,
};
}

if (newTag) {
if (!is.string(newTag) || newTag.startsWith('sha256:')) {
viceice marked this conversation as resolved.
Show resolved Hide resolved
return {
depName,
currentValue: newTag,
skipReason: SkipReason.InvalidValue,
};
}

const dep = splitImageParts(`${depName}:${newTag}`);
Object.assign(dep, {
datasource: datasourceDocker.id,
versioning: dockerVersioning.id,
thepwagner marked this conversation as resolved.
Show resolved Hide resolved
replaceString: newTag,
});
return dep;
thepwagner marked this conversation as resolved.
Show resolved Hide resolved
}

if (image.newName) {
Object.assign(nameDep, {
datasource: datasourceDocker.id,
versioning: dockerVersioning.id,
replaceString: image.newName,
});
return nameDep;
thepwagner marked this conversation as resolved.
Show resolved Hide resolved
}

return null;
}

Expand Down