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

refactor(manager/terraform): remove usages of any and use types #19815

Merged
merged 6 commits into from Jan 23, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
6 changes: 5 additions & 1 deletion lib/modules/manager/terraform/base.ts
Expand Up @@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
import { regEx } from '../../../util/regex';
import { TerraformProviderDatasource } from '../../datasource/terraform-provider';
import type { PackageDependency } from '../types';
import type { TerraformDefinitionFile } from './hcl/types';
import type { ProviderLock } from './lockfile/types';
import { getLockedVersion, massageProviderLookupName } from './util';

Expand All @@ -17,7 +18,10 @@ export abstract class DependencyExtractor {
* @param hclRoot HCL parsing artifact.
* @param locks currently existing locks
*/
abstract extract(hclRoot: any, locks: ProviderLock[]): PackageDependency[];
abstract extract(
hclRoot: TerraformDefinitionFile,
locks: ProviderLock[]
): PackageDependency[];
}

export abstract class TerraformProviderExtractor extends DependencyExtractor {
Expand Down
4 changes: 2 additions & 2 deletions lib/modules/manager/terraform/extractors.ts
@@ -1,15 +1,15 @@
import type { DependencyExtractor } from './base';
import { ModuleExtractor } from './extractors/others/modules';
import { ProvidersExtractor } from './extractors/others/providers';
import { GenericDockerImageRef } from './extractors/resources/generic-docker-image-ref';
import { GenericDockerImageRefExtractor } from './extractors/resources/generic-docker-image-ref';
import { HelmReleaseExtractor } from './extractors/resources/helm-release';
import { TerraformWorkspaceExtractor } from './extractors/resources/terraform-workspace';
import { RequiredProviderExtractor } from './extractors/terraform-block/required-provider';
import { TerraformVersionExtractor } from './extractors/terraform-block/terraform-version';

export const resourceExtractors: DependencyExtractor[] = [
new HelmReleaseExtractor(),
new GenericDockerImageRef(),
new GenericDockerImageRefExtractor(),
new TerraformWorkspaceExtractor(),
new RequiredProviderExtractor(),
new TerraformVersionExtractor(),
Expand Down
24 changes: 11 additions & 13 deletions lib/modules/manager/terraform/extractors/others/modules.ts
Expand Up @@ -7,6 +7,7 @@ import { GithubTagsDatasource } from '../../../../datasource/github-tags';
import { TerraformModuleDatasource } from '../../../../datasource/terraform-module';
import type { PackageDependency } from '../../../types';
import { DependencyExtractor } from '../../base';
import type { TerraformDefinitionFile } from '../../hcl/types';

export const githubRefMatchRegex = regEx(
/github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i
Expand All @@ -27,25 +28,22 @@ export class ModuleExtractor extends DependencyExtractor {
return ['module'];
}

extract(hclRoot: any): PackageDependency[] {
extract(hclRoot: TerraformDefinitionFile): PackageDependency[] {
const modules = hclRoot.module;
if (is.nullOrUndefined(modules)) {
return [];
}

const dependencies = [];
for (const moduleKeys of Object.keys(modules)) {
const module = modules[moduleKeys];
for (const moduleElement of module) {
const dep = {
currentValue: moduleElement.version,
managerData: {
source: moduleElement.source,
},
};
const massagedDep = this.analyseTerraformModule(dep);
dependencies.push(massagedDep);
}
for (const moduleElement of Object.values(modules).flat()) {
const dep = {
currentValue: moduleElement.version,
managerData: {
source: moduleElement.source,
},
};
const massagedDep = this.analyseTerraformModule(dep);
dependencies.push(massagedDep);
viceice marked this conversation as resolved.
Show resolved Hide resolved
}
return dependencies;
}
Expand Down
7 changes: 5 additions & 2 deletions lib/modules/manager/terraform/extractors/others/providers.ts
@@ -1,14 +1,18 @@
import is from '@sindresorhus/is';
import type { PackageDependency } from '../../../types';
import { TerraformProviderExtractor } from '../../base';
import type { TerraformDefinitionFile } from '../../hcl/types';
import type { ProviderLock } from '../../lockfile/types';

export class ProvidersExtractor extends TerraformProviderExtractor {
getCheckList(): string[] {
return ['provider'];
}

extract(hclRoot: any, locks: ProviderLock[]): PackageDependency[] {
extract(
hclRoot: TerraformDefinitionFile,
locks: ProviderLock[]
): PackageDependency[] {
const providerTypes = hclRoot?.provider;
if (is.nullOrUndefined(providerTypes)) {
return [];
Expand All @@ -22,7 +26,6 @@ export class ProvidersExtractor extends TerraformProviderExtractor {
currentValue: providerTypeElement.version,
managerData: {
moduleName: providerTypeName,
source: providerTypeElement.source,
viceice marked this conversation as resolved.
Show resolved Hide resolved
},
},
locks,
Expand Down
@@ -1,7 +1,7 @@
import { GenericDockerImageRef } from './generic-docker-image-ref';
import { GenericDockerImageRefExtractor } from './generic-docker-image-ref';

describe('modules/manager/terraform/extractors/resources/generic-docker-image', () => {
const extractor = new GenericDockerImageRef();
describe('modules/manager/terraform/extractors/resources/generic-docker-image-ref', () => {
const extractor = new GenericDockerImageRefExtractor();

it('return empty array if no resource is found', () => {
const res = extractor.extract({});
Expand Down
Expand Up @@ -2,14 +2,15 @@ import is from '@sindresorhus/is';
import { getDep } from '../../../dockerfile/extract';
import type { PackageDependency } from '../../../types';
import { DependencyExtractor } from '../../base';
import type { TerraformDefinitionFile } from '../../hcl/types';
import { generic_image_resource } from './utils';

export class GenericDockerImageRef extends DependencyExtractor {
export class GenericDockerImageRefExtractor extends DependencyExtractor {
getCheckList(): string[] {
return generic_image_resource.map((value) => `"${value.type}"`);
}

extract(hclMap: any): PackageDependency[] {
extract(hclMap: TerraformDefinitionFile): PackageDependency[] {
const resourceTypMap = hclMap.resource;
if (is.nullOrUndefined(resourceTypMap)) {
return [];
Expand All @@ -21,18 +22,13 @@ export class GenericDockerImageRef extends DependencyExtractor {
const { type, path } = image_resource_def;
const resourceInstancesMap = resourceTypMap[type];
// is there a resource with current looked at type ( `image_resource_def` )
if (is.nullOrUndefined(resourceInstancesMap)) {
if (!is.nonEmptyObject(resourceInstancesMap)) {
continue;
}

// loop over instances of a resource type
for (const instanceName of Object.keys(resourceInstancesMap)) {
const instanceList = resourceInstancesMap[instanceName];
for (const instance of instanceList) {
dependencies.push(
...this.walkPath({ depType: type }, instance, path)
);
}
for (const instance of Object.values(resourceInstancesMap).flat()) {
dependencies.push(...this.walkPath({ depType: type }, instance, path));
}
}
return dependencies;
Expand All @@ -48,14 +44,14 @@ export class GenericDockerImageRef extends DependencyExtractor {
*/
private walkPath(
abstractDep: PackageDependency,
parentElement: any,
parentElement: unknown,
leftPath: string[]
): PackageDependency[] {
const dependencies: PackageDependency[] = [];
// if there are no path elements left, we have reached the end of the path
if (leftPath.length === 0) {
// istanbul ignore if
if (is.nullOrUndefined(parentElement)) {
if (!is.nonEmptyString(parentElement)) {
return [
{
...abstractDep,
Expand All @@ -75,7 +71,9 @@ export class GenericDockerImageRef extends DependencyExtractor {
const pathElement = leftPath[0];

// get sub element
const element = parentElement[pathElement];
const element = is.nonEmptyObject(parentElement)
? parentElement[pathElement]
: null;
if (is.nullOrUndefined(element)) {
return leftPath.length === 1 // if this is the last element assume a false defined dependency
? [
Expand Down
45 changes: 22 additions & 23 deletions lib/modules/manager/terraform/extractors/resources/helm-release.ts
Expand Up @@ -4,43 +4,42 @@ import { HelmDatasource } from '../../../../datasource/helm';
import { isOCIRegistry } from '../../../helmv3/utils';
import type { PackageDependency } from '../../../types';
import { DependencyExtractor } from '../../base';
import type { TerraformDefinitionFile } from '../../hcl/types';
import { checkIfStringIsPath } from '../../util';

export class HelmReleaseExtractor extends DependencyExtractor {
getCheckList(): string[] {
return [`"helm_release"`];
}

override extract(hclMap: any): PackageDependency[] {
override extract(hclMap: TerraformDefinitionFile): PackageDependency[] {
const dependencies = [];

const helmReleases = hclMap?.resource?.helm_release;
if (is.nullOrUndefined(helmReleases)) {
return [];
}
for (const helmReleaseName of Object.keys(helmReleases)) {
for (const helmRelease of helmReleases[helmReleaseName]) {
const dep: PackageDependency = {
currentValue: helmRelease.version,
depType: 'helm_release',
depName: helmRelease.chart,
datasource: HelmDatasource.id,
};
if (!is.nullOrUndefined(helmRelease.repository)) {
dep.registryUrls = [helmRelease.repository];
}
if (!helmRelease.chart) {
dep.skipReason = 'invalid-name';
} 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;
} else if (checkIfStringIsPath(helmRelease.chart)) {
dep.skipReason = 'local-chart';
}

dependencies.push(dep);
for (const helmRelease of Object.values(helmReleases).flat()) {
const dep: PackageDependency = {
currentValue: helmRelease.version,
depType: 'helm_release',
depName: helmRelease.chart,
datasource: HelmDatasource.id,
};
if (is.nonEmptyString(helmRelease.repository)) {
dep.registryUrls = [helmRelease.repository];
}
if (!helmRelease.chart) {
dep.skipReason = 'invalid-name';
} 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;
} else if (checkIfStringIsPath(helmRelease.chart)) {
dep.skipReason = 'local-chart';
}

dependencies.push(dep);
}

return dependencies;
Expand Down
@@ -1,34 +1,33 @@
import is from '@sindresorhus/is';
import type { PackageDependency } from '../../../types';
import type { TerraformDefinitionFile } from '../../hcl/types';
import { TerraformVersionExtractor } from '../terraform-block/terraform-version';

export class TerraformWorkspaceExtractor extends TerraformVersionExtractor {
override getCheckList(): string[] {
return [`"tfe_workspace"`];
}

override extract(hclMap: any): PackageDependency[] {
override extract(hclMap: TerraformDefinitionFile): PackageDependency[] {
const dependencies = [];

const workspaces = hclMap?.resource?.tfe_workspace;
if (is.nullOrUndefined(workspaces)) {
return [];
}

for (const workspaceName of Object.keys(workspaces)) {
for (const workspace of workspaces[workspaceName]) {
const dep: PackageDependency = this.analyseTerraformVersion({
currentValue: workspace.terraform_version,
});
for (const workspace of Object.values(workspaces).flat()) {
const dep: PackageDependency = this.analyseTerraformVersion({
currentValue: workspace.terraform_version,
});

if (is.nullOrUndefined(workspace.terraform_version)) {
dep.skipReason = 'no-version';
}
dependencies.push({
...dep,
depType: 'tfe_workspace',
});
if (is.nullOrUndefined(workspace.terraform_version)) {
dep.skipReason = 'no-version';
}
dependencies.push({
...dep,
depType: 'tfe_workspace',
});
}
return dependencies;
}
Expand Down
@@ -1,14 +1,21 @@
import is from '@sindresorhus/is';
import type { PackageDependency } from '../../../types';
import { TerraformProviderExtractor } from '../../base';
import type {
TerraformDefinitionFile,
TerraformRequiredProvider,
} from '../../hcl/types';
import type { ProviderLock } from '../../lockfile/types';

export class RequiredProviderExtractor extends TerraformProviderExtractor {
getCheckList(): string[] {
return ['required_providers'];
}

extract(hclRoot: any, locks: ProviderLock[]): PackageDependency[] {
extract(
hclRoot: TerraformDefinitionFile,
locks: ProviderLock[]
): PackageDependency[] {
const terraformBlocks = hclRoot?.terraform;
if (is.nullOrUndefined(terraformBlocks)) {
return [];
Expand All @@ -21,35 +28,31 @@ export class RequiredProviderExtractor extends TerraformProviderExtractor {
continue;
}

for (const requiredProvidersMap of requiredProviders) {
for (const requiredProviderName of Object.keys(requiredProvidersMap)) {
const value = requiredProvidersMap[requiredProviderName];

// name = version declaration method
let dep: PackageDependency;
if (typeof value === 'string') {
dep = {
currentValue: value,
managerData: {
moduleName: requiredProviderName,
},
};
}
const entries: [string, TerraformRequiredProvider | string][] =
requiredProviders.flatMap(Object.entries);
for (const [requiredProviderName, value] of entries) {
// name = version declaration method
let dep: PackageDependency;
if (is.string(value)) {
dep = {
currentValue: value,
managerData: {
moduleName: requiredProviderName,
},
};
} else {
// block declaration aws = { source = 'aws', version = '2.0.0' }
dep ??= {
dep = {
currentValue: value['version'],
managerData: {
moduleName: requiredProviderName,
source: value['source'],
},
};
const massagedDep = this.analyzeTerraformProvider(
dep,
locks,
'required_provider'
);
dependencies.push(massagedDep);
}
dependencies.push(
this.analyzeTerraformProvider(dep, locks, 'required_provider')
);
}
}
return dependencies;
Expand Down
Expand Up @@ -2,13 +2,14 @@ import is from '@sindresorhus/is';
import { GithubReleasesDatasource } from '../../../../datasource/github-releases';
import type { PackageDependency } from '../../../types';
import { DependencyExtractor } from '../../base';
import type { TerraformDefinitionFile } from '../../hcl/types';

export class TerraformVersionExtractor extends DependencyExtractor {
getCheckList(): string[] {
return ['required_version'];
}

extract(hclRoot: any): PackageDependency[] {
extract(hclRoot: TerraformDefinitionFile): PackageDependency[] {
const terraformBlocks = hclRoot?.terraform;
if (is.nullOrUndefined(terraformBlocks)) {
return [];
Expand Down