sensu/sensu-settings

View on GitHub
lib/sensu/settings/validators/check.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require "parse-cron"

module Sensu
  module Settings
    module Validators
      module Check
        # Validate check name.
        # Validates: name
        #
        # @param check [Hash] sensu check definition.
        def validate_check_name(check)
          must_be_a_string(check[:name]) ||
            invalid(check, "check name must be a string")
          must_match_regex(/\A[\w\.-]+\z/, check[:name]) ||
            invalid(check, "check name cannot contain spaces or special characters")
        end

        # Validate check execution.
        # Validates: command, extension, timeout
        #
        # @param check [Hash] sensu check definition.
        def validate_check_execution(check)
          must_be_a_string_if_set(check[:command]) ||
            invalid(check, "check command must be a string")
          must_be_a_string_if_set(check[:extension]) ||
            invalid(check, "check extension must be a string")
          (!check[:command].nil? ^ !check[:extension].nil?) ||
            invalid(check, "either check command or extension must be set")
          must_be_a_numeric_if_set(check[:timeout]) ||
            invalid(check, "check timeout must be numeric")
          must_be_boolean_if_set(check[:stdin]) ||
            invalid(check, "check stdin must be boolean")
        end

        # Validate check source.
        # Validates: source
        #
        # @param check [Hash] sensu check definition.
        def validate_check_source(check)
          if is_a_string?(check[:source])
            must_match_regex(/\A[\w\.-]*([:]{3}[\w\|\.-]+[:]{3}[\w\.-]*|[\w\.-]+)\z/, check[:source]) ||
              invalid(check, "check source cannot contain spaces, special characters, or invalid tokens")
          else
            invalid(check, "check source must be a string")
          end
        end

        # Validate check cron.
        # Validates: cron
        #
        # @param check [Hash] sensu check definition.
        def validate_check_cron(check)
          must_be_a_string(check[:cron]) ||
            invalid(check, "check cron must be a string")
          begin
            cron_parser = CronParser.new(check[:cron])
            cron_parser.next(Time.now)
          rescue ArgumentError
            invalid(check, "check cron string must use the cron syntax")
          end
        end

        # Validate check scheduling.
        # Validates: publish, interval, standalone, subscribers
        #
        # @param check [Hash] sensu check definition.
        def validate_check_scheduling(check)
          must_be_boolean_if_set(check[:publish]) ||
            invalid(check, "check publish must be boolean")
          unless check[:publish] == false
            if check[:cron]
              validate_check_cron(check)
            else
              (must_be_an_integer(check[:interval]) && check[:interval] > 0) ||
                invalid(check, "check interval must be an integer greater than 0")
            end
          end
          must_be_boolean_if_set(check[:standalone]) ||
            invalid(check, "check standalone must be boolean")
          unless check[:standalone]
            if is_an_array?(check[:subscribers])
              items_must_be_strings(check[:subscribers]) ||
                invalid(check, "check subscribers must each be a string")
            else
              invalid(check, "check subscribers must be an array")
            end
          end
        end

        # Validate check proxy requests.
        # Validates: proxy_requests (client_attributes, splay, splay_coverage)
        #
        # @param check [Hash] sensu check definition.
        def validate_check_proxy_requests(check)
          if is_a_hash?(check[:proxy_requests])
            proxy_requests = check[:proxy_requests]
            must_be_a_hash(proxy_requests[:client_attributes]) ||
              invalid(check, "check proxy_requests client_attributes must be a hash")
            must_be_boolean_if_set(proxy_requests[:splay]) ||
              invalid(check, "check proxy_requests splay must be boolean")
            if proxy_requests[:splay_coverage]
              (must_be_an_integer(proxy_requests[:splay_coverage]) &&
                proxy_requests[:splay_coverage] > 0 &&
                proxy_requests[:splay_coverage] < 100) ||
                invalid(check, "check proxy_requests splay_coverage must be an integer greater than 0 and less than 100")
            end
          else
            invalid(check, "check proxy_requests must be a hash")
          end
        end

        # Validate check handling.
        # Validates: handler, handlers
        #
        # @param check [Hash] sensu check definition.
        def validate_check_handling(check)
          must_be_a_string_if_set(check[:handler]) ||
            invalid(check, "check handler must be a string")
          must_be_an_array_if_set(check[:handlers]) ||
            invalid(check, "check handlers must be an array")
          if is_an_array?(check[:handlers])
            items_must_be_strings(check[:handlers]) ||
              invalid(check, "check handlers must each be a string")
          end
        end

        # Validate check ttl.
        # Validates: ttl, ttl_status
        #
        # @param check [Hash] sensu check definition.
        def validate_check_ttl(check)
          if is_an_integer?(check[:ttl])
            check[:ttl] > 0 ||
              invalid(check, "check ttl must be greater than 0")
          else
            invalid(check, "check ttl must be an integer")
          end
          must_be_an_integer_if_set(check[:ttl_status]) ||
            invalid(check, "check ttl_status must be an integer")
        end

        # Validate check aggregate.
        # Validates: aggregate
        #
        # @param check [Hash] sensu check definition.
        def validate_check_aggregate(check)
          if check[:aggregates]
            if is_an_array?(check[:aggregates])
              items_must_be_strings(check[:aggregates], /\A[\w\.:|-]+\z/) ||
                invalid(check, "check aggregates items must be strings without spaces or special characters")
            else
              invalid(check, "check aggregates must be an array")
            end
          end
          if check[:aggregate]
            if is_a_string?(check[:aggregate])
              must_match_regex(/\A[\w\.:|-]+\z/, check[:aggregate]) ||
                invalid(check, "check aggregate cannot contain spaces or special characters")
            else
              must_be_boolean(check[:aggregate]) ||
                invalid(check, "check aggregate must be a string (name) or boolean")
            end
          end
        end

        # Validate check flap detection.
        # Validates: low_flap_threshold, high_flap_threshold
        #
        # @param check [Hash] sensu check definition.
        def validate_check_flap_detection(check)
          if either_are_set?(check[:low_flap_threshold], check[:high_flap_threshold])
            must_be_an_integer(check[:low_flap_threshold]) ||
              invalid(check, "check low flap threshold must be an integer")
            must_be_an_integer(check[:high_flap_threshold]) ||
              invalid(check, "check high flap threshold must be an integer")
          end
        end

        # Validate check hook execution.
        # Validates: command, timeout
        #
        # @param check [Hash] sensu check definition.
        # @param hook [Hash] sensu check hook definition.
        def validate_check_hook_execution(check, hook)
          must_be_a_string(hook[:command]) ||
            invalid(check, "check hook command must be a string")
          must_be_a_numeric_if_set(hook[:timeout]) ||
            invalid(check, "check hook timeout must be numeric")
          must_be_boolean_if_set(hook[:stdin]) ||
            invalid(check, "check hook stdin must be boolean")
        end

        # Validate check hooks.
        # Validates: hooks
        #
        # @param check [Hash] sensu check definition.
        def validate_check_hooks(check)
          if check[:hooks].is_a?(Hash)
            check[:hooks].each do |key, hook|
              must_be_either(%w[ok warning critical unknown], key.to_s) ||
                (0..255).map {|i| i.to_s}.include?(key.to_s) ||
                key.to_s == "non-zero" ||
                invalid(check, "check hook key must be a severity, status, or 'non-zero'")
              validate_check_hook_execution(check, hook)
            end
          else
            invalid(check, "check hooks must be a hash")
          end
        end

        # Validate check truncate output.
        # Validates: truncate_output, truncate_output_length
        #
        # @param check [Hash] sensu check definition.
        def validate_check_truncate_output(check)
          must_be_boolean_if_set(check[:truncate_output]) ||
            invalid(check, "check truncate_output must be boolean")
          if check[:truncate_output_length]
            (must_be_an_integer(check[:truncate_output_length]) &&
             check[:truncate_output_length] > 0) ||
              invalid(check, "check truncate_output_length must be an integer greater than 0")
          end
        end

        # Validate check subdue.
        # Validates: subdue
        #
        # @param check [Hash] sensu check definition.
        def validate_check_subdue(check)
          validate_time_windows(check, "check", :subdue)
        end

        # Validate a Sensu check definition.
        #
        # @param check [Hash] sensu check definition.
        def validate_check(check)
          validate_check_name(check)
          validate_check_execution(check)
          validate_check_source(check) if check[:source]
          validate_check_scheduling(check)
          validate_check_proxy_requests(check) if check[:proxy_requests]
          validate_check_handling(check)
          validate_check_ttl(check) if check[:ttl]
          validate_check_aggregate(check)
          validate_check_flap_detection(check)
          validate_check_hooks(check) if check[:hooks]
          validate_check_truncate_output(check)
          validate_check_subdue(check) if check[:subdue]
        end
      end
    end
  end
end