Skip to content

Commit 75f21c5

Browse files
committed
switch yaml engine to psych
closes #CNVS-27229 Change-Id: I257718e3e4603a0e8a25519ab10247f26d57394b Reviewed-on: https://gerrit.instructure.com/77480 Tested-by: Jenkins Reviewed-by: Cody Cutrer <cody@instructure.com> Product-Review: James Williams <jamesw@instructure.com> QA-Review: James Williams <jamesw@instructure.com>
1 parent 8640d7b commit 75f21c5

12 files changed

Lines changed: 87 additions & 413 deletions

app/models/submission_version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def extract_version_attributes(version, options = {})
4343
begin
4444
return nil unless Submission.where(:id => version.versionable_id).exists?
4545
version.model
46-
rescue ArgumentError
46+
rescue Psych::SyntaxError
4747
return nil
4848
end
4949
else

db/migrate/20160210153643_begin_psych_migration.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
class BeginPsychMigration < ActiveRecord::Migration
2-
tag :postdeploy
2+
tag :predeploy
33

4-
disable_ddl_transaction!
4+
def runnable?
5+
Shard.current.default?
6+
end
57

68
def up
7-
DataFixup::PsychMigration.run if CANVAS_RAILS4_0 || !Rails.env.test?
9+
if User.exists? # don't raise for a fresh install
10+
raise "WARNING:\n
11+
This migration needs to be run with the release/2016-04-23 version of canvas-lms to
12+
change all yaml columns in the database to a Psych compatible format.\n"
13+
end
814
end
915

1016
def down
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CleanseTheSyckness < ActiveRecord::Migration
2+
tag :postdeploy
3+
4+
def up
5+
DataFixup::SycknessCleanser.send_later_if_production_enqueue_args(:run, {:strand => Shard.current.database_server.id.to_s})
6+
end
7+
8+
def down
9+
end
10+
end

lib/canvas_yaml.rb

Lines changed: 3 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,15 @@
2020
# and before canvas-jobs
2121

2222
# We need to make sure that safe_yaml is loaded *after* the YAML engine
23-
# is switched to Syck. Otherwise we
23+
# is switched to Psych. Otherwise we
2424
# won't have access to (safe|unsafe)_load.
2525
require 'yaml'
2626

27-
require 'syck'
28-
YAML::ENGINE.yamler = 'syck' if defined?(YAML::ENGINE)
27+
require 'syck' # so we can undo all the things before something else requires it
28+
YAML::ENGINE.yamler = 'psych' if defined?(YAML::ENGINE)
2929

3030
require 'safe_yaml'
3131

32-
trusted_tags = SafeYAML::TRUSTED_TAGS.dup
33-
trusted_tags << 'tag:yaml.org,2002:merge'
34-
SafeYAML.send(:remove_const, :TRUSTED_TAGS)
35-
SafeYAML.const_set(:TRUSTED_TAGS, trusted_tags.freeze)
36-
3732
module FixSafeYAMLNullMerge
3833
def merge_into_hash(hash, array)
3934
return unless array
@@ -49,25 +44,6 @@ def merge_into_hash(hash, array)
4944
# This tag whitelist is syck specific. We'll need to tweak it when we upgrade to psych.
5045
# See the tests in spec/lib/safe_yaml_spec.rb
5146
whitelisted_tags: %w[
52-
tag:ruby.yaml.org,2002:symbol
53-
tag:yaml.org,2002:float
54-
tag:yaml.org,2002:float#exp
55-
tag:yaml.org,2002:float#inf
56-
tag:yaml.org,2002:str
57-
tag:yaml.org,2002:timestamp
58-
tag:yaml.org,2002:timestamp#iso8601
59-
tag:yaml.org,2002:timestamp#spaced
60-
tag:yaml.org,2002:map:HashWithIndifferentAccess
61-
tag:yaml.org,2002:map:ActiveSupport::HashWithIndifferentAccess
62-
tag:ruby.yaml.org,2002:object:Class
63-
tag:ruby.yaml.org,2002:object:OpenStruct
64-
tag:ruby.yaml.org,2002:object:Scribd::Document
65-
tag:ruby.yaml.org,2002:object:Mime::Type
66-
tag:ruby.yaml.org,2002:object:URI::HTTP
67-
tag:ruby.yaml.org,2002:object:URI::HTTPS
68-
tag:ruby.yaml.org,2002:object:OpenObject
69-
tag:yaml.org,2002:map:WeakParameters
70-
] + %w[
7147
!ruby/symbol
7248
!binary
7349
!float
@@ -96,43 +72,6 @@ def merge_into_hash(hash, array)
9672

9773
module Syckness
9874
TAG = "#GETDOWNWITHTHESYCKNESS\n"
99-
100-
module SyckDumper
101-
def dump(*args)
102-
Psych.dump(*args)
103-
end
104-
end
105-
106-
module PsychDumper
107-
def dump(*args)
108-
yaml = super
109-
yaml += TAG if yaml.is_a?(String)
110-
yaml
111-
end
112-
end
113-
114-
module SafeLoader
115-
require "safe_yaml/psych_resolver"
116-
require "safe_yaml/safe_to_ruby_visitor"
117-
118-
def load(yaml, *args)
119-
if yaml.is_a?(String) && yaml.end_with?(TAG)
120-
SafeYAML::PsychResolver.new.resolve_node(Psych.parse(yaml))
121-
else
122-
super
123-
end
124-
end
125-
end
126-
127-
module UnsafeLoader
128-
def unsafe_load(yaml, *args)
129-
if yaml.is_a?(String) && yaml.end_with?(TAG)
130-
Psych.load(yaml)
131-
else
132-
super
133-
end
134-
end
135-
end
13675
end
13776

13877
[Object, Hash, Struct, Array, Exception, String, Symbol, Range, Regexp, Time,
@@ -142,11 +81,6 @@ def unsafe_load(yaml, *args)
14281
end
14382
end
14483

145-
Syck.singleton_class.prepend(Syckness::SyckDumper)
146-
Psych.singleton_class.prepend(Syckness::PsychDumper)
147-
SafeYAML.singleton_class.prepend(Syckness::SafeLoader)
148-
YAML.singleton_class.prepend(Syckness::UnsafeLoader)
149-
15084
SafeYAML::PsychResolver.class_eval do
15185
attr_accessor :aliased_nodes
15286
end

lib/data_fixup/psych_migration.rb

Lines changed: 0 additions & 166 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module DataFixup
2+
module SycknessCleanser
3+
def self.columns_hash
4+
result = ActiveRecord::Base.all_models.map do |model|
5+
next unless model.superclass == ActiveRecord::Base
6+
next if model.name == 'RemoveQuizDataIds::QuizQuestionDataMigrationARShim'
7+
8+
attributes = model.serialized_attributes.select do |attr, coder|
9+
coder.is_a?(ActiveRecord::Coders::YAMLColumn)
10+
end
11+
next if attributes.empty?
12+
[model, attributes.keys]
13+
end.compact.to_h
14+
result[Version] = ['yaml']
15+
result[Delayed::Backend::ActiveRecord::Job] = ['handler']
16+
result[Delayed::Backend::ActiveRecord::Job::Failed] = ['handler']
17+
result
18+
end
19+
20+
def self.run
21+
self.columns_hash.each do |model, columns|
22+
update_sqls = {}
23+
quoted = {}
24+
25+
columns.each do |column|
26+
quoted[column] = model.connection.quote_column_name(column)
27+
update_sqls[column] = "#{quoted[column]} = left(#{quoted[column]}, -#{Syckness::TAG.length})"
28+
end
29+
model.find_ids_in_ranges do |min_id, max_id|
30+
columns.each do |column|
31+
model.where(model.primary_key => min_id..max_id).where("#{quoted[column]} LIKE ?", "%#{Syckness::TAG}").update_all(update_sqls[column])
32+
end
33+
delay = Setting.get("syckness_sleeping_ms", nil)
34+
if delay
35+
sleep(delay.to_i.fdiv(1000)) # just in case the cleansing is a little too strong
36+
end
37+
end
38+
end
39+
end
40+
end
41+
end

spec/gem_integration/canvas_stringex/canvas_stringex_spec.rb

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)