-
-
Notifications
You must be signed in to change notification settings - Fork 46
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
fix: parse error when only outputs is changed #896
Changes from 1 commit
eeee8b5
e40fa52
5d98cba
6fa879f
79bb821
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,7 +64,7 @@ func NewDefaultParser() *DefaultParser { | |
// NewPlanParser is PlanParser initialized with its Regexp | ||
func NewPlanParser() *PlanParser { | ||
return &PlanParser{ | ||
Pass: regexp.MustCompile(`(?m)^(Plan: \d|No changes.)`), | ||
Pass: regexp.MustCompile(`(?m)^(Plan: \d|No changes.|Changes to Outputs:)`), | ||
Fail: regexp.MustCompile(`(?m)^(Error: )`), | ||
// "0 to destroy" should be treated as "no destroy" | ||
HasDestroy: regexp.MustCompile(`(?m)([1-9][0-9]* to destroy.)`), | ||
|
@@ -150,8 +150,8 @@ func (p *PlanParser) Parse(body string) ParseResult { //nolint:cyclop | |
if line == "Terraform will perform the following actions:" { // https://github.com/hashicorp/terraform/blob/332045a4e4b1d256c45f98aac74e31102ace7af7/internal/command/views/plan.go#L252 | ||
startChangeOutput = i + 1 | ||
} | ||
if startChangeOutput != -1 && endChangeOutput == -1 && strings.HasPrefix(line, "Plan: ") { // https://github.com/hashicorp/terraform/blob/dfc12a6a9e1cff323829026d51873c1b80200757/internal/command/views/plan.go#L306 | ||
endChangeOutput = i + 1 | ||
if startChangeOutput != -1 && endChangeOutput == -1 && strings.HasPrefix(line, "-----") { // https://github.com/hashicorp/terraform/blob/1ac7a37d00f3c796f816070847bf02109cb9cab2/internal/command/views/operation.go#L142 | ||
endChangeOutput = i - 1 | ||
} | ||
if strings.HasPrefix(line, "Warning:") && startWarning == -1 { | ||
startWarning = i | ||
|
@@ -201,6 +201,10 @@ func (p *PlanParser) Parse(body string) ParseResult { //nolint:cyclop | |
|
||
changeResult := "" | ||
if startChangeOutput != -1 { | ||
// if we get here before finding a horizontal rule, output all remaining. | ||
if endChangeOutput == -1 { | ||
endChangeOutput = len(lines) - 1 | ||
} | ||
Comment on lines
+212
to
+215
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
changeResult = strings.Join(lines[startChangeOutput:endChangeOutput], "\n") | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,110 @@ can't guarantee that exactly these actions will be performed if | |
"terraform apply" is subsequently run. | ||
` | ||
|
||
const planOnlyOutputChangesSuccessResult0_12 = ` | ||
Refreshing Terraform state in-memory prior to plan... | ||
The refreshed state will be used to calculate this plan, but will not be | ||
persisted to local or remote state storage. | ||
|
||
data.terraform_remote_state.teams_platform_development: Refreshing state... | ||
google_project.my_project: Refreshing state... | ||
aws_iam_policy.datadog_aws_integration: Refreshing state... | ||
aws_iam_user.teams_terraform: Refreshing state... | ||
aws_iam_role.datadog_aws_integration: Refreshing state... | ||
google_project_services.my_project: Refreshing state... | ||
google_bigquery_dataset.gateway_access_log: Refreshing state... | ||
aws_iam_role_policy_attachment.datadog_aws_integration: Refreshing state... | ||
google_logging_project_sink.gateway_access_log_bigquery_sink: Refreshing state... | ||
google_project_iam_member.gateway_access_log_bigquery_sink_writer_is_bigquery_data_editor: Refreshing state... | ||
google_dns_managed_zone.tfnotifyapps_com: Refreshing state... | ||
google_dns_record_set.dev_tfnotifyapps_com: Refreshing state... | ||
|
||
------------------------------------------------------------------------ | ||
|
||
An execution plan has been generated and is shown below. | ||
Resource actions are indicated with the following symbols: | ||
+ create | ||
|
||
Terraform will perform the following actions: | ||
|
||
Plan: 0 to add, 0 to change, 0 to destroy. | ||
|
||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance" | ||
|
||
------------------------------------------------------------------------ | ||
|
||
Note: You didn't specify an "-out" parameter to save this plan, so Terraform | ||
can't guarantee that exactly these actions will be performed if | ||
"terraform apply" is subsequently run. | ||
` | ||
|
||
const planOnlyOutputChangesSuccessResult0_15 = ` | ||
Refreshing Terraform state in-memory prior to plan... | ||
The refreshed state will be used to calculate this plan, but will not be | ||
persisted to local or remote state storage. | ||
|
||
data.terraform_remote_state.teams_platform_development: Refreshing state... | ||
google_project.my_project: Refreshing state... | ||
aws_iam_policy.datadog_aws_integration: Refreshing state... | ||
aws_iam_user.teams_terraform: Refreshing state... | ||
aws_iam_role.datadog_aws_integration: Refreshing state... | ||
google_project_services.my_project: Refreshing state... | ||
google_bigquery_dataset.gateway_access_log: Refreshing state... | ||
aws_iam_role_policy_attachment.datadog_aws_integration: Refreshing state... | ||
google_logging_project_sink.gateway_access_log_bigquery_sink: Refreshing state... | ||
google_project_iam_member.gateway_access_log_bigquery_sink_writer_is_bigquery_data_editor: Refreshing state... | ||
google_dns_managed_zone.tfnotifyapps_com: Refreshing state... | ||
google_dns_record_set.dev_tfnotifyapps_com: Refreshing state... | ||
|
||
------------------------------------------------------------------------ | ||
|
||
An execution plan has been generated and is shown below. | ||
Resource actions are indicated with the following symbols: | ||
+ create | ||
|
||
Terraform will perform the following actions: | ||
|
||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance" | ||
|
||
------------------------------------------------------------------------ | ||
|
||
Note: You didn't specify an "-out" parameter to save this plan, so Terraform | ||
can't guarantee that exactly these actions will be performed if | ||
"terraform apply" is subsequently run. | ||
` | ||
|
||
const planOnlyOutputChangesSuccessInAutomationResult = ` | ||
Refreshing Terraform state in-memory prior to plan... | ||
The refreshed state will be used to calculate this plan, but will not be | ||
persisted to local or remote state storage. | ||
|
||
data.terraform_remote_state.teams_platform_development: Refreshing state... | ||
google_project.my_project: Refreshing state... | ||
aws_iam_policy.datadog_aws_integration: Refreshing state... | ||
aws_iam_user.teams_terraform: Refreshing state... | ||
aws_iam_role.datadog_aws_integration: Refreshing state... | ||
google_project_services.my_project: Refreshing state... | ||
google_bigquery_dataset.gateway_access_log: Refreshing state... | ||
aws_iam_role_policy_attachment.datadog_aws_integration: Refreshing state... | ||
google_logging_project_sink.gateway_access_log_bigquery_sink: Refreshing state... | ||
google_project_iam_member.gateway_access_log_bigquery_sink_writer_is_bigquery_data_editor: Refreshing state... | ||
google_dns_managed_zone.tfnotifyapps_com: Refreshing state... | ||
google_dns_record_set.dev_tfnotifyapps_com: Refreshing state... | ||
|
||
------------------------------------------------------------------------ | ||
|
||
An execution plan has been generated and is shown below. | ||
Resource actions are indicated with the following symbols: | ||
+ create | ||
|
||
Terraform will perform the following actions: | ||
|
||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance" | ||
` | ||
|
||
const planFailureResult = ` | ||
xxxxxxxxx | ||
xxxxxxxxx | ||
|
@@ -351,6 +455,56 @@ func TestPlanParserParse(t *testing.T) { | |
Plan: 1 to add, 0 to change, 0 to destroy.`, | ||
}, | ||
}, | ||
{ | ||
name: "plan output changes only pattern 0.12", | ||
body: planOnlyOutputChangesSuccessResult0_12, | ||
result: ParseResult{ | ||
Result: "Plan: 0 to add, 0 to change, 0 to destroy.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not ideal, but it's very old version... 🙈 |
||
HasAddOrUpdateOnly: true, | ||
HasDestroy: false, | ||
HasNoChanges: false, | ||
HasPlanError: false, | ||
ExitCode: 0, | ||
Error: nil, | ||
ChangedResult: ` | ||
Plan: 0 to add, 0 to change, 0 to destroy. | ||
|
||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance"`, | ||
}, | ||
}, | ||
{ | ||
name: "plan output changes only pattern 0.15", | ||
body: planOnlyOutputChangesSuccessResult0_15, | ||
result: ParseResult{ | ||
Result: "Changes to Outputs:", | ||
HasAddOrUpdateOnly: true, | ||
HasDestroy: false, | ||
HasNoChanges: false, | ||
HasPlanError: false, | ||
ExitCode: 0, | ||
Error: nil, | ||
ChangedResult: ` | ||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance"`, | ||
}, | ||
}, | ||
{ | ||
name: "plan output changes only pattern with TF_IN_AUTOMATION", | ||
body: planOnlyOutputChangesSuccessInAutomationResult, | ||
result: ParseResult{ | ||
Result: "Changes to Outputs:", | ||
HasAddOrUpdateOnly: true, | ||
HasDestroy: false, | ||
HasNoChanges: false, | ||
HasPlanError: false, | ||
ExitCode: 0, | ||
Error: nil, | ||
ChangedResult: ` | ||
Changes to Outputs: | ||
+ aws_instance_name = "my-instance"`, | ||
}, | ||
}, | ||
{ | ||
name: "no stdin", | ||
body: "", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To include changes to outputs coming after
Plan:
, we have to wait for a horizontal rule which comes afterChanges to Outputs:
.