Project

General

Profile

« Previous | Next » 

Revision 4bae5ced

Added by Stephen Benjamin over 10 years ago

fixes #3697, #3701 - more comprehensive field validations

View differences:

app/models/host/base.rb
has_many :fact_values, :dependent => :destroy, :foreign_key => :host_id
has_many :fact_names, :through => :fact_values
alias_attribute :hostname, :name
validates :name, :presence => true, :uniqueness => true
validate :is_name_downcased?
alias_attribute :hostname, :name
before_validation :normalize_name
validates :name, :presence => true,
:uniqueness => true,
:format => {:with => Net::Validations::HOST_REGEXP}
validates_inclusion_of :owner_type,
:in => OWNER_TYPES,
:allow_blank => true,
......
end
end
def is_name_downcased?
return unless name.present?
errors.add(:name, _("must be lowercase")) unless name == name.downcase
end
def facts_hash
hash = {}
fact_values.includes(:fact_name).collect do |fact|
......
comparison_object.id == id
end
def normalize_name
self.name = Net::Validations.normalize_hostname(name) if self.name.present?
end
end
end
app/models/host/managed.rb
private
def lookup_value_match
normalize_hostname
"fqdn=#{fqdn}"
end
......
# try to assign the domain automatically based on our existing domains from the host FQDN
self.domain = Domain.all.select{|d| name.match(d.name)}.first rescue nil
else
# if our host is in short name, append the domain name
# if we've just updated the domain name, strip off the old one
if !new_record? and changed_attributes['domain_id'].present?
old_domain = Domain.find(changed_attributes["domain_id"])
self.name.gsub(old_domain.to_s,"")
self.name.chomp!("." + old_domain.to_s)
end
# if our host is in short name, append the domain name
self.name += ".#{domain}" unless name =~ /\./i
end
# A managed host we should know the domain for; and the shortname shouldn't include a period
errors.add(:name, _("must not include periods")) if managed? and shortname.include? "."
end
def assign_hostgroup_attributes attrs = []
app/models/nic/managed.rb
attr_accessible :name, :subnet_id, :subnet, :domain_id, :domain
# Don't have to set a hostname for each interface, but it must be unique if it is set.
validates :name, :uniqueness => {:scope => :domain_id}, :allow_nil => true, :allow_blank => true
before_validation :normalize_name
validates :name, :uniqueness => {:scope => :domain_id},
:allow_nil => true,
:allow_blank => true,
:format => {:with => Net::Validations::HOST_REGEXP}
belongs_to :subnet
belongs_to :domain
......
:network => network
}
end
def normalize_name
self.name = Net::Validations.normalize_hostname(name) if self.name.present?
end
end
end
lib/net/validations.rb
module Net
module Validations
IP_REGEXP = /^(\d{1,3}\.){3}\d{1,3}$/
MAC_REGEXP = /^([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}$/i
IP_REGEXP = /\A((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\z/
MAC_REGEXP = /\A([a-f0-9]{1,2}:){5}[a-f0-9]{1,2}\z/i
HOST_REGEXP = /\A(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\z/
class Error < RuntimeError;
end
......
mac
end
# validates the hostname
def validate_hostname hostname
raise Error, "Invalid hostname #{hostname}" unless (hostname =~ HOST_REGEXP)
hostname
end
def validate_network network
begin
validate_ip(network)
......
m.split("-").map { |nibble| "%02x" % ("0x" + nibble) }.join(":")
end
end
def self.normalize_hostname hostname
hostname.downcase! if hostname.present?
hostname
end
end
end
test/fixtures/hosts.yml
owned_by_restricted:
type: Host::Managed
name: owned_by_restricted.mydomain.net
name: owned-by-restricted.mydomain.net
ip: "2.3.4.155"
mac: deadbeeffeed
environment: production
test/lib/net/validations_test.rb
end
end
test "hostname should be valid" do
assert_nothing_raised Net::Validations::Error do
validate_hostname "this.is.an.example.com"
end
assert_nothing_raised Net::Validations::Error do
validate_hostname "this-is.an.example.com"
end
assert_nothing_raised Net::Validations::Error do
validate_hostname "localhost"
end
end
test "hostname should not be valid" do
assert_raise Net::Validations::Error do
validate_hostname "-this.is.a.bad.example.com"
end
assert_raise Net::Validations::Error do
validate_hostname "this_is_a_bad.example.com"
end
end
describe "hostname normalization" do
let(:hostname) { "this.is.an.example.com" }
test "should normalize incorrect case" do
Net::Validations.normalize_hostname("ThIs.Is.An.eXaMPlE.CoM").must_equal(hostname)
end
end
describe "mac normalization" do
let(:mac) { "aa:bb:cc:dd:ee:ff" }
test/unit/host_test.rb
test "should not save without a hostname" do
host = Host.new
assert !host.save
host.valid?
assert_equal "can't be blank", host.errors[:name].first
end
test "should not save with invalid hostname" do
host = Host.new :name => "invalid_hostname"
host.valid?
assert_equal "is invalid", host.errors[:name].first
end
test "should not save hostname with periods in shortname" do
host = Host.new :name => "my.host", :domain => Domain.find_or_create_by_name("mydomain.net"), :managed => true
host.valid?
assert_equal "must not include periods", host.errors[:name].first
end
test "should make hostname lowercase" do
host = Host.new :name => "MYHOST", :domain => Domain.find_or_create_by_name("mydomain.net")
host.valid?
assert_equal "myhost.mydomain.net", host.name
end
test "should update name when domain is changed" do
host = hosts(:one)
host.domain_name = "yourdomain.net"
host.save!
assert_equal "my5name.yourdomain.net", host.name
end
test "should fix mac address hyphens" do
......
end
test "should not add domain name to hostname if it already include it" do
host = Host.create :name => "myhost.COMPANY.COM", :mac => "aabbccddeeff", :ip => "123.1.2.3",
host = Host.create :name => "myhost.company.com", :mac => "aabbccddeeff", :ip => "123.1.2.3",
:domain => Domain.find_or_create_by_name("company.com")
assert_equal "myhost.COMPANY.COM", host.name
assert_equal "myhost.company.com", host.name
end
test "should add hostname if it contains domain name" do
......
assert_equal 'sinn1636.lan.cert', Host.find_by_name('sinn1636.lan').certname
end
test "host is created when uploading facts if setting is true" do
assert_difference 'Host.count' do
Setting[:create_new_host_when_facts_are_uploaded] = true
raw = parse_json_fixture('/facts_with_certname.json')
Host.importHostAndFacts(raw['name'], raw['facts'], raw['certname'])
assert Host.find_by_name('sinn1636.lan')
Setting[:create_new_host_when_facts_are_uploaded] =
Setting.find_by_name("create_new_host_when_facts_are_uploaded").default
end
end
test "host is not created when uploading facts if setting is false" do
Setting[:create_new_host_when_facts_are_uploaded] = false
assert_equal false, Setting[:create_new_host_when_facts_are_uploaded]
......
assert_nil host
end
test "host is created when receiving a report if setting is true" do
assert_difference 'Host.count' do
Setting[:create_new_host_when_report_is_uploaded] = true
Report.import parse_json_fixture("/../fixtures/report-no-logs.json")
assert Host.find_by_name('builder.fm.example.net')
Setting[:create_new_host_when_report_is_uploaded] =
Setting.find_by_name("create_new_host_when_facts_are_uploaded").default
end
end
test "host is not created when receiving a report if setting is false" do
Setting[:create_new_host_when_report_is_uploaded] = false
assert_equal false, Setting[:create_new_host_when_report_is_uploaded]
......
assert_equal ["#{pc} does not belong to the #{h.environment} environment"], h.errors[:puppetclasses]
end
test "name should be lowercase" do
h = hosts(:redhat)
assert h.valid?
h.name.upcase!
assert !h.valid?
end
test "should allow to save root pw" do
h = hosts(:redhat)
pw = h.root_pass
test/unit/nic_test.rb
test "type casting should return the correct class" do
i = ''
i = Nic::Base.create! :ip => "127.2.3.8", :mac => "babbccddeeff", :host => hosts(:one), :name => hosts(:one).name + "!", :type => "Nic::Interface"
i = Nic::Base.create! :ip => "127.2.3.8", :mac => "babbccddeeff", :host => hosts(:one), :name => hosts(:one).name, :type => "Nic::Interface"
assert_equal "Nic::Interface", i.type
end
......
assert i.errors.keys.include?(:mac)
end
test "should fail on invalid dns name" do
i = Nic::Managed.new :mac => "dabbccddeeff", :host => hosts(:one), :name => "invalid_dns_name"
assert !i.valid?
assert i.errors.keys.include?(:name)
end
test "should fix mac address" do
interface = Nic::Base.create! :mac => "cabbccddeeff", :host => hosts(:one)
assert_equal "ca:bb:cc:dd:ee:ff", interface.mac
......
assert_equal subnet.network, interface.network
assert_equal subnet.vlanid, interface.vlanid
end
end
end
test/unit/subnet_test.rb
# missing dot
s.network = "100101.102.103."
refute s.valid?
# greater than 255
s.network = "300.300.300.0"
refute s.valid?
# missing number
s.network = "100.101.102"
refute s.valid?

Also available in: Unified diff