From c87213f4a29d618247b32b68c0497d42a994138c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Moitti=C3=A9?= Date: Mon, 19 Aug 2024 09:57:12 +0200 Subject: [PATCH] Fix bug when bad external id is set in tf --- src/parser/TerraformListener.js | 99 ++++++++++++++++++++----------- tests/resources/js/main.js | 28 ++++----- tests/resources/js/parserError.js | 13 ++++ tests/resources/tf/main.tf | 22 +++---- tests/resources/tf/parserError.tf | 8 +++ tests/resources/tf/validMain.tf | 14 ++--- 6 files changed, 117 insertions(+), 67 deletions(-) diff --git a/src/parser/TerraformListener.js b/src/parser/TerraformListener.js index 8646657..0643ef3 100644 --- a/src/parser/TerraformListener.js +++ b/src/parser/TerraformListener.js @@ -1,5 +1,6 @@ /* eslint class-methods-use-this: 0 */ import antlr4 from 'antlr4'; +import { ParserLog } from '@ditrit/leto-modelizer-plugin-core'; import TerraformVariable from '../models/TerraformVariable'; import TerraformComponentAttribute from '../models/TerraformComponentAttribute'; import TerraformComponent from '../models/TerraformComponent'; @@ -309,6 +310,14 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { // Enter a parse tree produced by terraformParser#argument. enterArgument(ctx) { + let definition = null; + if (!this.isVariable() && this.currentBlockType !== 'local') { + definition = this.getAttributeDefinition( + this.currentObjectField || this.currentComponent, + ctx.identifier().getText(), + ); + } + if (ctx.expression()?.section()?.map_()) { if (this.currentObjectField) { this.fieldsTree.push(this.currentObjectField); @@ -319,10 +328,7 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { name, type: 'Object', value: [], - definition: this.getAttributeDefinition( - this.currentObjectField || this.currentComponent, - name, - ), + definition, }); } @@ -342,10 +348,10 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { this.currentField = new TerraformComponentAttribute({ name: ctx.identifier().getText(), }); - this.currentField.definition = this.getAttributeDefinition( - this.currentComponent, - this.currentField.name, - ); + } + + if (this.currentField) { + this.currentField.definition = definition; } } @@ -366,16 +372,8 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { if (this.currentObjectField) { this.currentObjectField.value.push(this.currentField); - this.currentField.definition = this.getAttributeDefinition( - this.currentObjectField, - this.currentField.name, - ); } else { this.currentComponent.attributes.push(this.currentField); - this.currentField.definition = this.getAttributeDefinition( - this.currentComponent, - this.currentField.name, - ); } } else { this.currentObjectField.name = ctx.identifier().getText(); @@ -406,22 +404,33 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { } } - if (this.currentField?.definition?.type === 'Link') { - this.currentField.type = 'Array'; - if (Array.isArray(this.currentField.value)) { - this.currentField.value = this.currentField.value.map((v) => { - const match = /([^.]+\.[^.]+)\.([^.]+)/.exec(v); - // match[1] is `type.externalId` - return this.createIdFromTypeExternalId(match[1]); - }); - } - - const match = /([^.]+\.[^.]+)(\.([^.]+))?/.exec(this.currentField.value); - - if (match) { - this.currentField.value = [this.createIdFromTypeExternalId(match[1])]; - } - } + // if (this.currentField?.definition?.type === 'Link') { + // this.currentField.type = 'Array'; + // if (Array.isArray(this.currentField.value)) { + // // this.currentField.value = this.currentField.value.map((v) => { + // // const match = /([^.]+\.[^.]+)\.([^.]+)/.exec(v); + // // + // // if (!match) { + // // this.addError(ctx.children[0], new ParserLog({ + // // attribute: this.currentField.name, + // // severity: ParserLog.SEVERITY_ERROR, + // // message: 'terrator-plugin.parser.error.badExternalId', + // // extraData: v, + // // })); + // // + // // return null; + // // } + // // // match[1] is `type.externalId` + // // return this.createIdFromTypeExternalId(match[1]); + // // }).filter((value) => !!value); + // } + // // + // // const match = /([^.]+\.[^.]+)(\.([^.]+))?/.exec(this.currentField.value); + // // + // // if (match) { + // // this.currentField.value = [this.createIdFromTypeExternalId(match[1])]; + // // } + // } this.currentField = null; } @@ -554,7 +563,25 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { return; } - if (this.currentField.type === 'Array') { + if (this.currentField.definition?.type === 'Link') { + this.currentField.type = 'Array'; + const match = /([^.]+\.[^.]+)\.([^.]+)/.exec(value); + + if (!this.currentField.value) { + this.currentField.value = []; + } + + if (!match) { + this.addError(ctx, new ParserLog({ + attribute: this.currentField.name, + severity: ParserLog.SEVERITY_ERROR, + message: 'terrator-plugin.parser.error.badExternalId', + extraData: value, + })); + } else { + this.currentField.value.push(this.createIdFromTypeExternalId(match[1])); + } + } else if (this.currentField.type === 'Array') { this.currentField.value.push(value); } else { this.currentField.value = value; @@ -612,8 +639,10 @@ class TerraformListener extends antlr4.tree.ParseTreeListener { type: 'Array', value: [], }); - } else if (this.currentField) { - this.currentField.type = 'Array'; + } + + this.currentField.type = 'Array'; + if (!this.currentField.value) { this.currentField.value = []; } diff --git a/tests/resources/js/main.js b/tests/resources/js/main.js index a17f4f3..84b4450 100644 --- a/tests/resources/js/main.js +++ b/tests/resources/js/main.js @@ -1262,8 +1262,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'evaluation_periods', - type: 'String', - value: '2', + type: 'Number', + value: 2, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.evaluation_periods.def, }), new TerraformComponentAttribute({ @@ -1280,8 +1280,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'period', - type: 'String', - value: '120', + type: 'Number', + value: 120, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.period.def, }), new TerraformComponentAttribute({ @@ -1292,8 +1292,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'threshold', - type: 'String', - value: '85', + type: 'Number', + value: 85, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.threshold.def, }), new TerraformComponentAttribute({ @@ -1385,8 +1385,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'evaluation_periods', - type: 'String', - value: '2', + type: 'Number', + value: 2, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.evaluation_periods.def, }), new TerraformComponentAttribute({ @@ -1403,8 +1403,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'period', - type: 'String', - value: '120', + type: 'Number', + value: 120, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.period.def, }), new TerraformComponentAttribute({ @@ -1415,8 +1415,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'threshold', - type: 'String', - value: '30', + type: 'Number', + value: 30, definition: defs.resource.aws_cloudwatch_metric_alarm.attrs.threshold.def, }), new TerraformComponentAttribute({ @@ -1485,8 +1485,8 @@ export const mainComponents = [ }), new TerraformComponentAttribute({ name: 'port', - type: 'String', - value: '80', + type: 'Number', + value: 80, definition: defs.resource.aws_lb_listener.attrs.port.def, }), new TerraformComponentAttribute({ diff --git a/tests/resources/js/parserError.js b/tests/resources/js/parserError.js index beb00fc..687a920 100644 --- a/tests/resources/js/parserError.js +++ b/tests/resources/js/parserError.js @@ -87,6 +87,19 @@ const errors = [ severity: ParserLog.SEVERITY_ERROR, initialErrorMessage: null, }), + new ParserLog({ + path: 'parserError.tf', + componentId: 'id_6', + attribute: 'target_group_arn', + startLineNumber: 21, + startColumn: 25, + endLineNumber: 21, + endColumn: 36, + message: 'terrator-plugin.parser.error.badExternalId', + severity: ParserLog.SEVERITY_ERROR, + initialErrorMessage: null, + extraData: 'lb_target', + }), ]; export default errors; diff --git a/tests/resources/tf/main.tf b/tests/resources/tf/main.tf index f1c5f65..8667551 100644 --- a/tests/resources/tf/main.tf +++ b/tests/resources/tf/main.tf @@ -131,7 +131,7 @@ resource "aws_subnet" "cms_dmz_subnet" { resource "aws_security_group" "cms_frontend_secgroup" { name = "cms_frontend_secgroup" description = "Default Rules for the CMS Front-End servers" - vpc_id = aws_vpc.cms_main_vpc + vpc_id = aws_vpc.cms_main_vpc.id ingress { description = "HTTP from VPC" from_port = 8000 @@ -172,7 +172,7 @@ resource "aws_security_group" "cms_frontend_secgroup" { resource "aws_security_group" "cms_backend_secgroup" { name = "cms_backend_secgroup" description = "Default Rules for the CMS Back-End servers" - vpc_id = aws_vpc.cms_main_vpc + vpc_id = aws_vpc.cms_main_vpc.id ingress { description = "MySQL from VPC" from_port = 3306 @@ -198,7 +198,7 @@ resource "aws_security_group" "cms_backend_secgroup" { resource "aws_security_group" "cms_lb_secgroup" { name = "cms_lb_secgroup" description = "Default Rules for the CMS LoadBalancer" - vpc_id = aws_vpc.cms_main_vpc + vpc_id = aws_vpc.cms_main_vpc.id ingress { from_port = 443 to_port = 443 @@ -254,7 +254,7 @@ resource "aws_lb_target_group" "cms_lb_target" { target_type = "instance" port = 8000 protocol = "HTTP" - vpc_id = aws_vpc.cms_main_vpc + vpc_id = aws_vpc.cms_main_vpc.id } resource "aws_launch_configuration" "cms_launch_conf" { @@ -296,12 +296,12 @@ resource "aws_autoscaling_policy" "cms_policy_up" { resource "aws_cloudwatch_metric_alarm" "cms_cpu_alarm_up" { alarm_name = "cms_cpu_alarm_up" comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "2" + evaluation_periods = 2 metric_name = "CPUUtilization" namespace = "AWS/EC2" - period = "120" + period = 120 statistic = "Average" - threshold = "85" + threshold = 85 dimensions = { AutoScalingGroupName = aws_autoscaling_group.cms_asg.name } @@ -322,12 +322,12 @@ resource "aws_autoscaling_policy" "cms_policy_down" { resource "aws_cloudwatch_metric_alarm" "cms_cpu_alarm_down" { alarm_name = "cms_cpu_alarm_down" comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "2" + evaluation_periods = 2 metric_name = "CPUUtilization" namespace = "AWS/EC2" - period = "120" + period = 120 statistic = "Average" - threshold = "30" + threshold = 30 dimensions = { AutoScalingGroupName = aws_autoscaling_group.cms_asg.name } @@ -345,7 +345,7 @@ resource "aws_efs_file_system" "cms_fileshare" { resource "aws_lb_listener" "cms_lb_listener" { load_balancer_arn = aws_lb.cms_frontend_lb.arn - port = "80" + port = 80 protocol = "HTTP" default_action { type = "forward" diff --git a/tests/resources/tf/parserError.tf b/tests/resources/tf/parserError.tf index c4840a1..4e6df3e 100644 --- a/tests/resources/tf/parserError.tf +++ b/tests/resources/tf/parserError.tf @@ -13,3 +13,11 @@ resource "aws_lb_target_group" "" {} blabla "test" {} provider "aws" {} + +resource "aws_lb_listener" "http_lb_listener" { + load_balancer_arn = [aws_lb.frontend_lb.id] + default_action { + type = "forward" + target_group_arn = ["lb_target"] + } +} diff --git a/tests/resources/tf/validMain.tf b/tests/resources/tf/validMain.tf index 072bd5f..ddf3ae2 100644 --- a/tests/resources/tf/validMain.tf +++ b/tests/resources/tf/validMain.tf @@ -320,12 +320,12 @@ resource "aws_autoscaling_policy" "cms_policy_up" { resource "aws_cloudwatch_metric_alarm" "cms_cpu_alarm_up" { alarm_name = "cms_cpu_alarm_up" comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "2" + evaluation_periods = 2 metric_name = "CPUUtilization" namespace = "AWS/EC2" - period = "120" + period = 120 statistic = "Average" - threshold = "85" + threshold = 85 dimensions = { AutoScalingGroupName = [ aws_autoscaling_group.cms_asg.id, @@ -350,12 +350,12 @@ resource "aws_autoscaling_policy" "cms_policy_down" { resource "aws_cloudwatch_metric_alarm" "cms_cpu_alarm_down" { alarm_name = "cms_cpu_alarm_down" comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "2" + evaluation_periods = 2 metric_name = "CPUUtilization" namespace = "AWS/EC2" - period = "120" + period = 120 statistic = "Average" - threshold = "30" + threshold = 30 dimensions = { AutoScalingGroupName = [ aws_autoscaling_group.cms_asg.id, @@ -377,7 +377,7 @@ resource "aws_lb_listener" "cms_lb_listener" { load_balancer_arn = [ aws_lb.cms_frontend_lb.id, ] - port = "80" + port = 80 protocol = "HTTP" default_action { type = "forward"