Skip to content

Commit

Permalink
Allow psych v4 (#98)
Browse files Browse the repository at this point in the history
In psych v4, the YAML.load method has been updated to provide a similar
interface and semantics to YAML.safe_load. Refactor the code to use
YAML.safe_load for a consistent behaviour between psych V3 and V4.

Psych will automatically convert strings that look like dates to Ruby
Date objects. We need to permit this class when loading CloudFormation
YAML.

The permitted_classes keyword argument for YAML.safe_load was introduced
in psych v3.1.0. So this is now the minimum compatible version of psych.
  • Loading branch information
orien committed May 31, 2022
1 parent 3ca8460 commit 57f6382
Show file tree
Hide file tree
Showing 9 changed files with 20 additions and 18 deletions.
6 changes: 4 additions & 2 deletions Gemfile.lock
Expand Up @@ -3,7 +3,7 @@ PATH
specs:
cfn-model (9.9.9)
kwalify (= 0.7.2)
psych (~> 3)
psych (>= 3.1, < 5)

GEM
remote: https://rubygems.org/
Expand All @@ -16,7 +16,8 @@ GEM
parallel (1.19.1)
parser (2.7.0.2)
ast (~> 2.4.0)
psych (3.1.0)
psych (4.0.3)
stringio
rainbow (3.0.0)
rake (13.0.3)
rspec (3.9.0)
Expand Down Expand Up @@ -46,6 +47,7 @@ GEM
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.2)
stringio (3.0.1)
unicode-display_width (1.6.1)

PLATFORMS
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -32,7 +32,7 @@ upon which static analysis can be conducted.
The `CfnModel` is a container for other object that have been parsed, wrapped and potentially linked to
other wrapped objects.

The raw Hash output of `YAML.load` is also available from `CfnModel`.
The raw Hash output of `YAML.safe_load` is also available from `CfnModel`.

require 'cfn-model'
Expand Down
2 changes: 1 addition & 1 deletion cfn-model.gemspec
Expand Up @@ -26,5 +26,5 @@ Gem::Specification.new do |s|
s.add_development_dependency('simplecov', '~> 0.11')

s.add_runtime_dependency('kwalify', '0.7.2')
s.add_runtime_dependency('psych', '~> 3')
s.add_runtime_dependency('psych', '>= 3.1', '< 5')
end
2 changes: 1 addition & 1 deletion lib/cfn-model/model/cfn_model.rb
Expand Up @@ -6,7 +6,7 @@ class CfnModel
attr_reader :resources, :parameters, :line_numbers, :conditions, :globals, :mappings, :element_types

##
# if you really want it, here it is - the raw Hash from YAML.load. you'll have to mess with structural nits of
# if you really want it, here it is - the raw Hash from YAML.safe_load. you'll have to mess with structural nits of
# CloudFormation and deal with variations between yaml/json refs and all that
#
attr_accessor :raw_model
Expand Down
2 changes: 1 addition & 1 deletion lib/cfn-model/parser/cfn_parser.rb
Expand Up @@ -65,7 +65,7 @@ def parse_without_parameters(cloudformation_yml, with_line_numbers=false, condit
if with_line_numbers
parse_with_line_numbers(cloudformation_yml)
else
YAML.load cloudformation_yml
YAML.safe_load cloudformation_yml, permitted_classes: [Date]
end

# Transform raw resources in template as performed by
Expand Down
2 changes: 1 addition & 1 deletion lib/cfn-model/validator/cloudformation_validator.rb
Expand Up @@ -12,7 +12,7 @@ def validate(cloudformation_string)

schema = SchemaGenerator.new.generate cloudformation_string
validator = Kwalify::Validator.new(schema)
validator.validate(YAML.load(cloudformation_string))
validator.validate(YAML.safe_load(cloudformation_string, permitted_classes: [Date]))
rescue ArgumentError, IOError, NameError => e
raise ParserError, e.inspect
end
Expand Down
2 changes: 1 addition & 1 deletion lib/cfn-model/validator/resource_type_validator.rb
Expand Up @@ -5,7 +5,7 @@
class ResourceTypeValidator

def self.validate(cloudformation_yml)
hash = YAML.load cloudformation_yml
hash = YAML.safe_load cloudformation_yml, permitted_classes: [Date]
if hash == false || hash.nil?
raise ParserError.new 'yml empty'
end
Expand Down
4 changes: 2 additions & 2 deletions lib/cfn-model/validator/schema_generator.rb
Expand Up @@ -19,7 +19,7 @@ def generate(cloudformation_yml)
parameters_schema = generate_schema_for_parameter_keys cloudformation_hash
resources_schema = generate_schema_for_resource_keys cloudformation_hash

main_schema = YAML.load IO.read(schema_file('schema.yml.erb'))
main_schema = YAML.safe_load IO.read(schema_file('schema.yml.erb'))
if parameters_schema.empty?
main_schema['mapping'].delete 'Parameters'
else
Expand Down Expand Up @@ -82,7 +82,7 @@ def schema_for_type(type)
if !File.exist? schema_file_path
nil
else
YAML.load IO.read(schema_file_path)
YAML.safe_load IO.read(schema_file_path)
end
end
end
16 changes: 8 additions & 8 deletions spec/validator/reference_validator_spec.rb
Expand Up @@ -23,7 +23,7 @@
JimBob: !Ref someResource
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
expect(unresolved_references).to eq Set.new(%w(dino))
end
end
Expand All @@ -48,7 +48,7 @@
JimBob: !Ref someResource
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
expect(unresolved_references).to eq Set.new(%w(dino))
end
end
Expand All @@ -72,7 +72,7 @@
END

expect {
_ = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
_ = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
}.to raise_error(ParserError, 'Ref target must be string literal: {"Ref"=>{"Fn::GetAtt"=>["someResource", "Fred"]}}')
end
end
Expand All @@ -90,7 +90,7 @@
Barney: !Ref AWS::Region
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
expect(unresolved_references).to eq Set.new([])
end
end
Expand All @@ -115,7 +115,7 @@
JimBob: !Ref someResource
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
expect(unresolved_references).to eq Set.new(%w(dino2))
end
end
Expand Down Expand Up @@ -144,7 +144,7 @@
JimBob: !Ref someResource
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_missing_ref)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_missing_ref)
expect(unresolved_references).to eq Set.new(%w(dino2))
end
end
Expand All @@ -170,7 +170,7 @@
Ricky: !Ref someResource.Version
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_pseudo_refs)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_pseudo_refs)
expect(unresolved_references).to eq Set.new(%w())
end
end
Expand All @@ -196,7 +196,7 @@
Ricky: !Ref bogus.Version
END

unresolved_references = ReferenceValidator.new.unresolved_references YAML.load(cfn_yaml_with_pseudo_refs)
unresolved_references = ReferenceValidator.new.unresolved_references YAML.safe_load(cfn_yaml_with_pseudo_refs)
expect(unresolved_references).to eq Set.new(%w(bogus.Version))
end
end
Expand Down

0 comments on commit 57f6382

Please sign in to comment.