Skip to content

Commit

Permalink
fix(cli): sanitize type arrays
Browse files Browse the repository at this point in the history
some providers sporadically return them double leading to errors in cdktf convert and get
  • Loading branch information
DanielMSchmidt committed Apr 2, 2024
1 parent 84dc27e commit af6d921
Show file tree
Hide file tree
Showing 4 changed files with 282 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -752,3 +752,113 @@ exports[`readSchema generates a single provider schema 1`] = `
}
}"
`;

exports[`sanitizeProviderSchema sanitizes a provider schema 1`] = `
{
"format_version": "0.1",
"provider_schemas": {
"registry.terraform.io/hashicorp/null": {
"data_source_schemas": {},
"provider": {
"block": {
"attributes": {
"correct": {
"type": [
"list",
"string",
],
},
"incorrect": {
"type": [
"list",
"string",
],
},
"version": {
"required": true,
"type": "string",
},
},
"block_types": {
"triggers": {
"block": {
"attributes": {
"correct": {
"type": [
"list",
"string",
],
},
"incorrect": {
"type": [
"list",
"string",
],
},
},
"block_types": {},
},
"nesting_mode": "single",
},
},
},
"version": 0,
},
"resource_schemas": {
"null_resource": {
"block": {
"attributes": {
"correct": {
"type": [
"list",
"string",
],
},
"id": {
"computed": true,
"type": "string",
},
"incorrect": {
"type": [
"list",
"string",
],
},
},
"block_types": {
"triggers": {
"block": {
"attributes": {
"correct": {
"type": [
"list",
"string",
],
},
"incorrect": {
"type": [
"list",
"string",
],
},
"triggers": {
"optional": true,
"type": "string",
},
},
"block_types": {},
},
"nesting_mode": "single",
},
},
},
"version": 0,
},
},
},
},
"provider_versions": {
"registry.terraform.io/hashicorp/null": "3.1.0",
},
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ import {
ConstructsMakerModuleTarget,
ConstructsMakerProviderTarget,
Language,
ProviderSchema,
} from "@cdktf/commons";
import { readModuleSchema, readProviderSchema } from "../provider-schema";
import {
readModuleSchema,
readProviderSchema,
sanitizeProviderSchema,
} from "../provider-schema";

function sanitizeJson(value: any) {
value["format_version"] = "STUBBED VERSION";
Expand Down Expand Up @@ -70,3 +75,94 @@ describe("readSchema", () => {
expect(sanitizeJson(result)).toMatchSnapshot();
}, 120000);
});

describe("sanitizeProviderSchema", () => {
it("sanitizes a provider schema", () => {
const schema: ProviderSchema = {
format_version: "0.1" as const,
provider_versions: {
"registry.terraform.io/hashicorp/null": "3.1.0",
},
provider_schemas: {
"registry.terraform.io/hashicorp/null": {
provider: {
version: 0,
block: {
attributes: {
version: {
type: "string",
required: true,
},
correct: {
type: ["list", "string"],
},
incorrect: {
type: ["list", "string", "list", "string"] as any,
},
},
block_types: {
triggers: {
nesting_mode: "single",
block: {
attributes: {
correct: {
type: ["list", "string"],
},
incorrect: {
type: ["list", "string", "list", "string"] as any,
},
},
block_types: {},
},
},
},
},
},
resource_schemas: {
null_resource: {
version: 0,
block: {
attributes: {
id: {
type: "string",
computed: true,
},
correct: {
type: ["list", "string"],
},
incorrect: {
type: ["list", "string", "list", "string"] as any,
},
},
block_types: {
triggers: {
nesting_mode: "single",
block: {
attributes: {
triggers: {
type: "string",
optional: true,
},
correct: {
type: ["list", "string"],
},
incorrect: {
type: ["list", "string", "list", "string"] as any,
},
},
block_types: {},
},
},
},
},
},
},
data_source_schemas: {},
},
},
};

const result = sanitizeProviderSchema(schema);
expect(result).toMatchSnapshot();
});
});
48 changes: 47 additions & 1 deletion packages/@cdktf/provider-schema/src/provider-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import * as path from "path";

import { convertFiles } from "@cdktf/hcl2json";
import {
Attribute,
AttributeType,
Block,
ConstructsMakerModuleTarget,
ConstructsMakerProviderTarget,
Input,
Expand All @@ -14,6 +17,7 @@ import {
TerraformModuleConstraint,
VersionSchema,
exec,
isNestedTypeAttribute,
withTempDir,
} from "@cdktf/commons";

Expand Down Expand Up @@ -208,7 +212,49 @@ export async function readProviderSchema(
providerSchema.provider_versions = versionSchema.provider_selections;
});

return providerSchema;
return sanitizeProviderSchema(providerSchema);
}

// The providers have some potential bugs that we want to pro-actively
// fix here so that the rest of the code can assume a consistent schema.
export function sanitizeProviderSchema(schema: ProviderSchema): ProviderSchema {
// Mainly some attributes are "doubled", e.g. ["list", "string", "list", "string"]
// instead of ["list", "string"]
function attributeDoublingFix(attribute: Attribute): Attribute {
if (isNestedTypeAttribute(attribute) || !Array.isArray(attribute.type)) {
return attribute;
}

const type =
attribute.type.length === 2
? attribute.type
: (attribute.type as string[]).slice(0, 2); // The types tell us this can't happen, reality begs to differ

attribute.type = type as AttributeType;
return attribute;
}

// Mutates block with the fix
function sanitizeBlock(block: Block) {
Object.values(block.attributes || {}).forEach(attributeDoublingFix);
Object.values(block.block_types || {}).forEach((blockType) => {
sanitizeBlock(blockType.block);
});
}

Object.values(schema.provider_schemas || {}).forEach((provider) => {
const entities = [
provider.provider,
...Object.values(provider.resource_schemas || {}),
...Object.values(provider.data_source_schemas || {}),
];

entities.forEach((entity) => {
sanitizeBlock(entity.block);
});
});

return schema;
}

export async function readModuleSchema(target: ConstructsMakerModuleTarget) {
Expand Down
Loading

0 comments on commit af6d921

Please sign in to comment.