-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
515a70b
commit edf85d4
Showing
18 changed files
with
582 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import yaml from 'js-yaml'; | ||
import { logger } from '../../logger'; | ||
import { getDep } from '../dockerfile/extract'; | ||
|
||
import { PackageFile, PackageDependency } from '../common'; | ||
import { | ||
matchesHelmValuesDockerHeuristic, | ||
HelmDockerImageDependency, | ||
} from './util'; | ||
|
||
/** | ||
* Recursively find all supported dependencies in the yaml object. | ||
* | ||
* @param parsedContent | ||
*/ | ||
function findDependencies( | ||
parsedContent: object | HelmDockerImageDependency, | ||
packageDependencies: Array<PackageDependency> | ||
): Array<PackageDependency> { | ||
if (!parsedContent || typeof parsedContent !== 'object') { | ||
return packageDependencies; | ||
} | ||
|
||
Object.keys(parsedContent).forEach(key => { | ||
if (matchesHelmValuesDockerHeuristic(key, parsedContent[key])) { | ||
const currentItem = parsedContent[key]; | ||
|
||
const registry = currentItem.registry ? `${currentItem.registry}/` : ''; | ||
packageDependencies.push( | ||
getDep(`${registry}${currentItem.repository}:${currentItem.tag}`) | ||
); | ||
} else { | ||
findDependencies(parsedContent[key], packageDependencies); | ||
} | ||
}); | ||
return packageDependencies; | ||
} | ||
|
||
export function extractPackageFile(content: string): PackageFile { | ||
try { | ||
// a parser that allows extracting line numbers would be preferable, with | ||
// the current approach we need to match anything we find again during the update | ||
const parsedContent = yaml.safeLoad(content); | ||
|
||
logger.debug( | ||
{ parsedContent }, | ||
'Trying to find dependencies in helm-values' | ||
); | ||
const deps = findDependencies(parsedContent, []); | ||
|
||
if (deps.length) { | ||
logger.debug({ deps }, 'Found dependencies in helm-values'); | ||
return { deps }; | ||
} | ||
} catch (err) { | ||
logger.error({ err }, 'Failed to parse helm-values file'); | ||
} | ||
|
||
return null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { extractPackageFile } from './extract'; | ||
export { updateDependency } from './update'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import YAWN from 'yawn-yaml/cjs'; | ||
import { logger } from '../../logger'; | ||
import { Upgrade } from '../common'; | ||
import { | ||
matchesHelmValuesDockerHeuristic, | ||
HelmDockerImageDependency, | ||
} from './util'; | ||
|
||
function shouldUpdate( | ||
parentKey: string, | ||
data: unknown | HelmDockerImageDependency, | ||
dockerRepository: string, | ||
currentValue: string, | ||
originalRegistryValue: string | ||
): boolean { | ||
return ( | ||
matchesHelmValuesDockerHeuristic(parentKey, data) && | ||
data.repository === dockerRepository && | ||
data.tag === currentValue && | ||
((!data.registry && !originalRegistryValue) || | ||
data.registry === originalRegistryValue) | ||
); | ||
} | ||
|
||
/** | ||
* Extract the originally set registry value if it is included in the depName. | ||
*/ | ||
function getOriginalRegistryValue( | ||
depName: string, | ||
dockerRepository: string | ||
): string { | ||
if (depName.length > dockerRepository.length) { | ||
return depName.substring(0, depName.lastIndexOf(dockerRepository) - 1); | ||
} | ||
return ''; | ||
} | ||
|
||
/** | ||
* Recursive function that walks the yaml strucuture | ||
* and updates the first match of an 'image' key it finds, | ||
* if it adheres to the supported structure. | ||
* | ||
* @param parsedContent The part of the yaml tree we should look at. | ||
* @param dockerRepository The docker repository that should be updated. | ||
* @param currentValue The current version that should be updated. | ||
* @param newValue The update version that should be set instead of currentValue. | ||
* @returns True if the parsedContent was updated, false otherwise. | ||
*/ | ||
function updateDoc( | ||
parsedContent: object | HelmDockerImageDependency, | ||
dockerRepository: string, | ||
currentValue: string, | ||
newValue: string, | ||
originalRegistryValue: string | ||
): boolean { | ||
for (const key of Object.keys(parsedContent)) { | ||
if ( | ||
shouldUpdate( | ||
key, | ||
parsedContent[key], | ||
dockerRepository, | ||
currentValue, | ||
originalRegistryValue | ||
) | ||
) { | ||
// the next statement intentionally updates the passed in parameter | ||
// with the updated dependency value | ||
// eslint-disable-next-line no-param-reassign | ||
parsedContent[key].tag = newValue; | ||
|
||
return true; | ||
} | ||
|
||
if (typeof parsedContent[key] === 'object') { | ||
const foundMatch = updateDoc( | ||
parsedContent[key], | ||
dockerRepository, | ||
currentValue, | ||
newValue, | ||
originalRegistryValue | ||
); | ||
if (foundMatch) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
export function updateDependency( | ||
fileContent: string, | ||
upgrade: Upgrade | ||
): string | null { | ||
if ( | ||
!upgrade || | ||
!upgrade.depName || | ||
!upgrade.newValue || | ||
!upgrade.currentValue || | ||
!upgrade.dockerRepository | ||
) { | ||
logger.debug('Failed to update dependency, invalid upgrade'); | ||
return fileContent; | ||
} | ||
|
||
const yawn = new YAWN(fileContent); | ||
const doc = yawn.json; | ||
|
||
const originalRegistryValue = getOriginalRegistryValue( | ||
upgrade.depName, | ||
upgrade.dockerRepository | ||
); | ||
updateDoc( | ||
doc, | ||
upgrade.dockerRepository, | ||
upgrade.currentValue, | ||
upgrade.newValue, | ||
originalRegistryValue | ||
); | ||
yawn.json = doc; | ||
|
||
return yawn.yaml; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
export type HelmDockerImageDependency = { | ||
registry?: string; | ||
repository: string; | ||
tag: string; | ||
}; | ||
|
||
/** | ||
* This is a workaround helper to allow the usage of 'unknown' in | ||
* a type-guard function while checking that keys exist. | ||
* | ||
* @see https://github.com/microsoft/TypeScript/issues/21732 | ||
* @see https://stackoverflow.com/a/58630274 | ||
*/ | ||
function hasKey<K extends string>(k: K, o: {}): o is { [_ in K]: {} } { | ||
return typeof o === 'object' && k in o; | ||
} | ||
|
||
/** | ||
* Type guard to determine whether a given partial Helm values.yaml object potentially | ||
* defines a Helm Docker dependency. | ||
* | ||
* There is no exact standard of how Docker dependencies are defined in Helm | ||
* values.yaml files (as of January 1st 2020), this function defines a | ||
* heuristic based on the most commonly used format in the stable Helm charts: | ||
* | ||
* image: | ||
* repository: 'something' | ||
* tag: v1.0.0 | ||
*/ | ||
export function matchesHelmValuesDockerHeuristic( | ||
parentKey: string, | ||
data: unknown | ||
): data is HelmDockerImageDependency { | ||
return ( | ||
parentKey === 'image' && | ||
data && | ||
typeof data === 'object' && | ||
hasKey('repository', data) && | ||
hasKey('tag', data) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.