lib/specinfra/command/base.rb in specinfra-2.0.0.beta6 vs lib/specinfra/command/base.rb in specinfra-2.0.0.beta7

- old
+ new

@@ -1,354 +1,94 @@ require 'shellwords' +class Specinfra::Command::Base + attr_accessor :types -module Specinfra - module Command - class Base - class NotImplementedError < Exception; end + class NotImplementedError < Exception; end - def escape(target) - str = case target - when Regexp - target.source - else - target.to_s - end + def self.create + self.new + end - Shellwords.shellescape(str) - end + def escape(target) + str = case target + when Regexp + target.source + else + target.to_s + end - def check_enabled(service, level=3) - raise NotImplementedError.new - end + Shellwords.shellescape(str) + end - def check_yumrepo(repository) - raise NotImplementedError.new - end + def method_missing(meth, *args) + action, resource_type, subaction = breakdown(meth) + method = action + method += "_#{subaction}" if subaction + command_object = command_class(resource_type).create + if command_object.respond_to?(method) + command_object.send(method, *args) + else + raise NotImplementedError.new("#{method} is not implemented in #{command_class(resource_type)}") + end + end - def check_yumrepo_enabled(repository) - raise NotImplementedError.new - end + def command_class(resource_type) + family = os[:family] + version = os[:release] ? "V#{os[:release].to_i}" : nil - def check_mounted(path) - regexp = "on #{path}" - "mount | grep -w -- #{escape(regexp)}" - end + common_class = self.class.const_get('Specinfra').const_get('Command') + base_class = common_class.const_get('Base') + os_class = family.nil? ? base_class : common_class.const_get(family.capitalize) - def check_routing_table(destination) - "ip route | grep -E '^#{destination} |^default '" + if family && version + begin + version_class = os_class.const_get(version) + rescue + version_class = os_class.const_get('Base') end + elsif family.nil? + version_class = os_class + elsif family != 'base' && version.nil? + version_class = os_class.const_get('Base') + end - def check_reachable(host, port, proto, timeout) - if port.nil? - "ping -w #{escape(timeout)} -c 2 -n #{escape(host)}" - else - "nc -vvvvz#{escape(proto[0].chr)} #{escape(host)} #{escape(port)} -w #{escape(timeout)}" - end - end + begin + command_klass = version_class.const_get(resource_type.to_camel_case) + rescue + end - def check_resolvable(name, type) - if type == "dns" - "nslookup -timeout=1 #{escape(name)}" - elsif type == "hosts" - "grep -w -- #{escape(name)} /etc/hosts" - else - "getent hosts #{escape(name)}" - end - end + if command_klass.nil? ||( (command_klass < Specinfra::Command::Base).nil? && (command_klass < Specinfra::Command::Windows::Base).nil? ) + command_klass = base_class.const_get(resource_type.to_camel_case) + end - def check_file(file) - "test -f #{escape(file)}" - end + command_klass + end - def get_file_mtime(file) - "stat -c %Y #{escape(file)}" - end + private + def breakdown(meth) + types = resource_types.map {|t| t.to_snake_case }.join('|') + md = meth.to_s.match(/^([^_]+)_(#{types})_?(.+)?$/) + if md.nil? + message = "Could not break down `#{meth}' to appropriate type and method.\n" + message += "The method name shoud be in the form of `action_type_subaction'." + raise message + end + return md[1], md[2], md[3] + end - def get_file_size(file) - "stat -c %s #{escape(file)}" + def resource_types + if @types.nil? + @types = [] + Specinfra::Command::Base.subclasses.each do |s| + @types << s.to_s.split(':')[-1] end - - def check_socket(file) - "test -S #{escape(file)}" + Specinfra::Command::Windows::Base.subclasses.each do |s| + @types << s.to_s.split(':')[-1] end - - def check_directory(directory) - "test -d #{escape(directory)}" - end - - def check_user(user) - "id #{escape(user)}" - end - - def check_group(group) - "getent group #{escape(group)}" - end - - def check_installed(package, version=nil) - raise NotImplementedError.new - end - - def check_service_installed(service) - raise NotImplementedError.new - end - - def check_service_start_mode(service, mode) - raise NotImplementedError.new - end - - def check_listening(port, options = {}) - pattern = ":#{port}" - pattern = " #{options[:local_address]}#{pattern}" if options[:local_address] - pattern = "^#{options[:protocol]} .*#{pattern}" if options[:protocol] - "netstat -tunl | grep -- #{escape(pattern)}" - end - - def check_listening_with_protocol(port, protocol) - check_listening port, {:protocol => protocol} - end - - def check_running(service) - "service #{escape(service)} status" - end - - def check_running_under_supervisor(service) - "supervisorctl status #{escape(service)} | grep RUNNING" - end - - def check_running_under_upstart(service) - "initctl status #{escape(service)} | grep running" - end - - def check_monitored_by_monit(service) - "monit status" - end - - def check_monitored_by_god(service) - "god status #{escape(service)}" - end - - def check_process(process) - "ps aux | grep -w -- #{escape(process)} | grep -qv grep" - end - - def check_process_count(process,count) - "test $(ps aux | grep -w -- #{escape(process)} | grep -v grep | wc -l) -eq #{escape(count)}" - end - - def get_process(process, opts) - "ps -C #{escape(process)} -o #{opts[:format]} | head -1" - end - - def check_file_contain(file, expected_pattern) - "#{check_file_contain_with_regexp(file, expected_pattern)} || #{check_file_contain_with_fixed_strings(file, expected_pattern)}" - end - - def check_file_contain_with_regexp(file, expected_pattern) - "grep -q -- #{escape(expected_pattern)} #{escape(file)}" - end - - def check_file_contain_with_fixed_strings(file, expected_pattern) - "grep -qF -- #{escape(expected_pattern)} #{escape(file)}" - end - - def check_file_checksum(file, expected) - regexp = "^#{expected}" - "cksum #{escape(file)} | grep -iw -- #{escape(regexp)}" - end - - def check_file_md5checksum(file, expected) - regexp = "^#{expected}" - "md5sum #{escape(file)} | grep -iw -- #{escape(regexp)}" - end - - def check_file_sha256checksum(file, expected) - regexp = "^#{expected}" - "sha256sum #{escape(file)} | grep -iw -- #{escape(regexp)}" - end - - def check_file_contain_within(file, expected_pattern, from=nil, to=nil) - from ||= '1' - to ||= '$' - sed = "sed -n #{escape(from)},#{escape(to)}p #{escape(file)}" - checker_with_regexp = check_file_contain_with_regexp("-", expected_pattern) - checker_with_fixed = check_file_contain_with_fixed_strings("-", expected_pattern) - "#{sed} | #{checker_with_regexp} || #{sed} | #{checker_with_fixed}" - end - - def check_file_contain_lines(file, expected_lines, from=nil, to=nil) - require 'digest/md5' - from ||= '1' - to ||= '$' - sed = "sed -n #{escape(from)},#{escape(to)}p #{escape(file)}" - head_line = expected_lines.first.chomp - lines_checksum = Digest::MD5.hexdigest(expected_lines.map(&:chomp).join("\n") + "\n") - afterwards_length = expected_lines.length - 1 - "#{sed} | grep -A #{escape(afterwards_length)} -F -- #{escape(head_line)} | md5sum | grep -qiw -- #{escape(lines_checksum)}" - end - - def check_mode(file, mode) - regexp = "^#{mode}$" - "stat -c %a #{escape(file)} | grep -- #{escape(regexp)}" - end - - def check_owner(file, owner) - regexp = "^#{owner}$" - "stat -c %U #{escape(file)} | grep -- #{escape(regexp)}" - end - - def check_grouped(file, group) - regexp = "^#{group}$" - "stat -c %G #{escape(file)} | grep -- #{escape(regexp)}" - end - - def check_cron_entry(user, entry) - entry_escaped = entry.gsub(/\*/, '\\*').gsub(/\[/, '\\[').gsub(/\]/, '\\]') - if user.nil? - "crontab -l | grep -v \"#\" -- | grep -- #{escape(entry_escaped)}" - else - "crontab -u #{escape(user)} -l | grep -v \"#\" | grep -- #{escape(entry_escaped)}" - end - end - - def check_link(link, target) - "stat -c %N #{escape(link)} | egrep -e \"-> .#{escape(target)}.\"" - end - - def check_installed_by_gem(name, version=nil) - regexp = "^#{name}" - cmd = "gem list --local | grep -w -- #{escape(regexp)}" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_installed_by_npm(name, version=nil) - cmd = "npm ls #{escape(name)} -g" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_installed_by_pecl(name, version=nil) - regexp = "^#{name}" - cmd = "pecl list | grep -w -- #{escape(regexp)}" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_installed_by_pear(name, version=nil) - regexp = "^#{name}" - cmd = "pear list | grep -w -- #{escape(regexp)}" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_installed_by_pip(name, version=nil) - regexp = "^#{name}" - cmd = "pip list | grep -w -- #{escape(regexp)}" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_installed_by_cpan(name, version=nil) - regexp = "^#{name}" - cmd = "cpan -l | grep -w -- #{escape(regexp)}" - cmd = "#{cmd} | grep -w -- #{escape(version)}" if version - cmd - end - - def check_belonging_group(user, group) - "id #{escape(user)} | awk '{print $3}' | grep -- #{escape(group)}" - end - - def check_gid(group, gid) - regexp = "^#{group}" - "getent group | grep -w -- #{escape(regexp)} | cut -f 3 -d ':' | grep -w -- #{escape(gid)}" - end - - def check_uid(user, uid) - regexp = "^uid=#{uid}(" - "id #{escape(user)} | grep -- #{escape(regexp)}" - end - - def check_login_shell(user, path_to_shell) - "getent passwd #{escape(user)} | cut -f 7 -d ':' | grep -w -- #{escape(path_to_shell)}" - end - - def check_home_directory(user, path_to_home) - "getent passwd #{escape(user)} | cut -f 6 -d ':' | grep -w -- #{escape(path_to_home)}" - end - - def check_authorized_key(user, key) - key.sub!(/\s+\S*$/, '') if key.match(/^\S+\s+\S+\s+\S*$/) - "grep -w -- #{escape(key)} ~#{escape(user)}/.ssh/authorized_keys" - end - - def check_iptables_rule(rule, table=nil, chain=nil) - raise NotImplementedError.new - end - - def check_zfs(zfs, property=nil, value=nil) - raise NotImplementedError.new - end - - def get_mode(file) - "stat -c %a #{escape(file)}" - end - - def check_ipfilter_rule(rule) - raise NotImplementedError.new - end - - def check_ipnat_rule(rule) - raise NotImplementedError.new - end - - def check_svcprop(svc, property, value) - raise NotImplementedError.new - end - - def check_svcprops(svc, property) - raise NotImplementedError.new - end - - def check_selinux(mode) - raise NotImplementedError.new - end - - def check_access_by_user(file, user, access) - raise NotImplementedError.new - end - - def check_kernel_module_loaded(name) - raise NotImplementedError.new - end - - def check_ipv4_address(interface, ip_address) - raise NotImplementedError.new - end - - def check_mail_alias(recipient, target) - target = "[[:space:]]#{target}" - "getent aliases #{escape(recipient)} | grep -- #{escape(target)}$" - end - - def get_file_content(file) - "cat #{file} 2> /dev/null || echo -n" - end - - def check_container(container) - raise NotImplementedError.new - end - - def check_cotainer_running(container) - raise NotImplementedError.new - end - - def get_package_version(package, opts=nil) - raise NotImplementedError.new - end - - def get_ipaddress_of_host(name) - "getent hosts #{escape(name)} | awk '{print $1}'" - end + @types.uniq! end + @types end end + + +