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

Unify render errors and handle an edge case #253

Merged
merged 3 commits into from
Apr 17, 2018
Merged

Unify render errors and handle an edge case #253

merged 3 commits into from
Apr 17, 2018

Conversation

KnVerey
Copy link
Contributor

@KnVerey KnVerey commented Mar 19, 2018

Started off fixing an edge case where a .yml file that actually starts with some ERB would raise an exception instead of failing gracefully with a nice message. Ended up shaving a small yak upon noticing that we displayed errors about invalid templates several different ways.

Before

test_deploy_fails_if_required_binding_not_present
image

test_missing_nested_partial_prints_helpful_error
image

test_invalid_yaml_in_partial_prints_helpful_error
image

test_invalid_yaml_fails_fast
image

test_multiple_invalid_k8s_specs_fails_on_apply_and_prints_template
image

After

test_deploy_fails_if_required_binding_not_present
image

test_missing_nested_partial_correctly_identifies_invalid_template_and_its_parents [improved test]
image

test_invalid_yaml_in_partial_prints_helpful_error
image

test_invalid_yaml_fails_fast
image

test_multiple_invalid_k8s_specs_fails_on_apply_and_prints_template
image

@@ -865,4 +879,8 @@ def test_cronjobs_can_be_deployed
cronjobs = FixtureSetAssertions::CronJobs.new(@namespace)
cronjobs.assert_cronjob_present("my-cronjob")
end

def test_friendly_error_on_misidentified_erb_file
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the new one:

image

.rubocop.yml Outdated
@@ -3,3 +3,9 @@ inherit_from:

AllCops:
TargetRubyVersion: 2.3

Style/TrailingCommaInArrayLiteral:
Copy link
Contributor Author

@KnVerey KnVerey Mar 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not opposed to adding these (I guess it must have been added to the styleguide? rubocop started caring about it), but doing so now would cause rebase hell for the several people with huge PRs in flight.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we flip these on when we hit 1.0? I agree these are going to cause a lot of pain for nothing more than a style preference right now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally like enjoy trailing commas in hashes and arrays, they make it easier to add an element, treat every line the same way and they show up as only one line change in git. So I am all for enabling them. But yeah, we shouldn't bug people with open PRs with it.

Copy link
Contributor

@dturn dturn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments. Though I wonder if we want to check for the presence of <% and if its there add something liker "Did you forgot to add .erb suffix?" to the warning message

@@ -225,24 +225,25 @@ def discover_resources
end
end
resources
rescue InvalidTemplateError => e
debug_msg = paragraph_for_invalid_templates(e.message, filenames: [e.filename], content: e.content)
@logger.summary.add_paragraph(debug_msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you envision a case where you'd want generate the message and not log it? If not can you combine these two lines into a function log_invalid_templates ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why log here instead of split_templates

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why log here instead of split_templates

I think I did that because one of the three places that can raise this is the rescue of split_templates, so the alternative is:

    def split_templates(filename)
      ...
    rescue Psych::SyntaxError => e
      log_invalid_templates(e.message, filenames: [filename], content: rendered_content)
      raise FatalDeploymentError, "Failed to render and parse template"
    rescue InvalidTemplateError => e
      log_invalid_templates(e.message, filenames: [e.filename], content: e.content)
      raise FatalDeploymentError, "Failed to render and parse template"
    end

It's a bit of duplication, but I don't feel strongly about it. Do you think that would be easier to follow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think moving it to split_templates is easer to read / understand.

.rubocop.yml Outdated
@@ -3,3 +3,9 @@ inherit_from:

AllCops:
TargetRubyVersion: 2.3

Style/TrailingCommaInArrayLiteral:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we flip these on when we hit 1.0? I agree these are going to cause a lot of pain for nothing more than a style preference right now.

Copy link
Contributor

@klautcomputing klautcomputing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have minor comments, I need to run the tests and take a look at the output before approving it though :)

.rubocop.yml Outdated
@@ -3,3 +3,9 @@ inherit_from:

AllCops:
TargetRubyVersion: 2.3

Style/TrailingCommaInArrayLiteral:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally like enjoy trailing commas in hashes and arrays, they make it easier to add an element, treat every line the same way and they show up as only one line change in git. So I am all for enabling them. But yeah, we shouldn't bug people with open PRs with it.

debug_msg += "> Error from kubectl:\n#{indent_four(err)}"
if file_content.present?
debug_msg += "\n> Rendered template content:\n#{indent_four(file_content)}"
def paragraph_for_invalid_templates(err, filenames:, content:)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a little weird to have one required argument, followed by two required keyword arguments.
Especially since the function has an if content present? block which kind of implies that content is not always required. Maybe make all 3 keyword parameters and give content: a default of nil? or just do the latter?

raise InvalidPartialError, err.message
# get the filename from the first parent, not the missing partial itself
raise err if err.filename == partial
raise InvalidPartialError.new(err.message, filename: partial, content: expanded_template || template)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the underlying code raise the correct error type? Instead of rescuing one type and raising either one or the other?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is transforming the data, not just the error type. rescue PartialNotFound needs to be distinct because it is the first parent (potentially of a long chain) that has the relevant filename and template content. So we hit this case in the missing child (in which case we skip it, L64) and the first parent (in which case we grab the filename and content, L65), and then after that we just add the additional parent name to the list (L67), like we would for any other type of error.

Copy link
Contributor Author

@KnVerey KnVerey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In making the change to have paragraph_for_invalid_templates do the logging itself, I noticed that record_invalid_template could be simplified and merged with it. It was more complex because it supported multiple file paths, but really, calling it once per file path (by refactoring into what is now record_apply_failure) leads to better output anyway. Please take another look.

The main tests affected by the last commit are test_multiple_invalid_k8s_specs_fails_on_apply_and_prints_template, test_output_when_switching_labels_incorrectly and test_invalid_k8s_spec_that_is_valid_yaml_but_has_no_template_path_in_error_prints_helpful_message

"You may wish to roll back this deploy."
@logger.summary.add_paragraph(ColorizedString.new(warn_msg).yellow)

unidentified_errors = []
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a bad idea. If there were a multi-line error message where one of the middle lines has a filename in it, we'd be splitting it up strangely. I haven't seen that, but I certainly haven't seen everything. An alternative is to always dump the complete error before the individual cases we were able to extract and enhance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would totally say, let's deal with it when it comes up

line.scan(%r{"(/\S+\.ya?ml\S*)"}).each_with_object([]) do |matches, bad_files|
matches.each do |path|
content = File.read(path) if File.file?(path)
bad_files << { filename: File.basename(path), err: line, content: content }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lets us split up the various errors we've identified appropriately.

Example before this commit:

image

Example after:

image

@dturn
Copy link
Contributor

dturn commented Mar 29, 2018

LGTM, I'm not worried about the possible edge case with multiline errors and filenames.

"You may wish to roll back this deploy."
@logger.summary.add_paragraph(ColorizedString.new(warn_msg).yellow)

unidentified_errors = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would totally say, let's deal with it when it comes up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants