before_validation :set_timestamps
validates :command, :container_image, :output_path, :cwd, :priority, { presence: true }
validates :priority, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+ validate :validate_runtime_status
validate :validate_state_change
validate :validate_change
validate :validate_lock
end
end
+ # Check that well-known runtime status keys have desired data types
+ def validate_runtime_status
+ [
+ 'error', 'errorDetail', 'warning', 'warningDetail', 'activity'
+ ].each do |k|
+ if self.runtime_status.andand.include?(k) && !self.runtime_status[k].is_a?(String)
+ errors.add(:runtime_status, "'#{k}' value must be a string")
+ end
+ end
+ end
+
def validate_change
permitted = [:state]
end
end
+ test "Container runtime_status data types" do
+ set_user_from_auth :active
+ attrs = {
+ environment: {},
+ mounts: {"BAR" => {"kind" => "FOO"}},
+ output_path: "/tmp",
+ priority: 1,
+ runtime_constraints: {"vcpus" => 1, "ram" => 1}
+ }
+ c, _ = minimal_new(attrs)
+ assert_equal c.runtime_status, {}
+ assert_equal Container::Queued, c.state
+
+ set_user_from_auth :dispatch1
+ c.update_attributes! state: Container::Locked
+ c.update_attributes! state: Container::Running
+
+ [
+ 'error', 'errorDetail', 'warning', 'warningDetail', 'activity'
+ ].each do |k|
+ # String type is allowed
+ string_val = 'A string is accepted'
+ c.update_attributes! runtime_status: {k => string_val}
+ assert_equal string_val, c.runtime_status[k]
+
+ # Other types aren't allowed
+ [
+ 42, false, [], {}, nil
+ ].each do |unallowed_val|
+ assert_raises ActiveRecord::RecordInvalid do
+ c.update_attributes! runtime_status: {k => unallowed_val}
+ end
+ end
+ end
+ end
+
test "Container runtime_status updates" do
set_user_from_auth :active
attrs = {