watchmonkey_cli 1.9.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Gemfile +3 -0
 - data/README.md +14 -2
 - data/VERSION +1 -1
 - data/doc/checker_example.rb +10 -0
 - data/doc/config_example.rb +56 -0
 - data/lib/watchmonkey_cli/application/configuration.rb +37 -2
 - data/lib/watchmonkey_cli/application/configuration.tpl +22 -1
 - data/lib/watchmonkey_cli/application/core.rb +55 -5
 - data/lib/watchmonkey_cli/application/dispatch.rb +6 -2
 - data/lib/watchmonkey_cli/application/output_helper.rb +4 -0
 - data/lib/watchmonkey_cli/application.rb +29 -3
 - data/lib/watchmonkey_cli/checker.rb +30 -6
 - data/lib/watchmonkey_cli/checkers/dev_pry.rb +29 -0
 - data/lib/watchmonkey_cli/checkers/ftp_availability.rb +1 -1
 - data/lib/watchmonkey_cli/checkers/ssl_expiration.rb +1 -1
 - data/lib/watchmonkey_cli/checkers/unix_defaults.rb +3 -1
 - data/lib/watchmonkey_cli/checkers/www_availability.rb +2 -1
 - data/lib/watchmonkey_cli/hooks/platypus.rb +2 -2
 - data/lib/watchmonkey_cli/hooks/requeue.rb +12 -1
 - data/lib/watchmonkey_cli/hooks/telegram_bot.rb +566 -0
 - data/lib/watchmonkey_cli/loopback_connection.rb +7 -0
 - data/lib/watchmonkey_cli/ssh_connection.rb +11 -1
 - data/lib/watchmonkey_cli/version.rb +1 -1
 - data/lib/watchmonkey_cli.rb +2 -0
 - metadata +5 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 5d2615fa891c7ccb38541934fa918c33fa37a93cc3d3c52ece8db41a100e1d0b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 98f2a66da3fdc810c9b7fc1396ba12a605f3cd12d939585e9c9ed03d9f252fbf
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 23307a955c34627a32e0023df5dc40874eda5d72e80f152e2a57bcf12be767b34db53fc565ffbc8329060cbfe8e72871956123bf553f0ff409ed4468528bca0f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c671b5bac01cf8c423eef81ada024cd35a1c82f426c9fa80cee4cb90047aa242c579a39248ef349d2cc69d7be281037caac74afa410d59af633029f5b5860b52
         
     | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -4,10 +4,11 @@ Watchmonkey is a very simple tool to monitor resources with Ruby without the nee 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            Before looking any further you might want to know:
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
              * There is no escalation or notification system but you may add it yourself
         
     | 
| 
       8 
     | 
    
         
            -
              * I created this for being used with [Platypus](http://sveinbjorn.org/platypus) hence the [Platypus Hook](https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/platypus.rb)
         
     | 
| 
      
 7 
     | 
    
         
            +
              * There is no escalation or notification system (except experimental telegram bot) but you may add it yourself
         
     | 
| 
      
 8 
     | 
    
         
            +
              * I originally created this for being used with [Platypus](http://sveinbjorn.org/platypus) hence the [Platypus Hook](https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/platypus.rb)
         
     | 
| 
       9 
9 
     | 
    
         
             
              * This is how the text output looks like: [Screenshot](http://imgur.com/8yLYnKb)
         
     | 
| 
       10 
10 
     | 
    
         
             
              * This is how the Platypus support looks like: [ProgressBar](http://imgur.com/Vd8ZD7A) [HTML/WebView](http://imgur.com/5FwmWFZ)
         
     | 
| 
      
 11 
     | 
    
         
            +
              * This is how Telegram Bot looks for now: [Telegram Screenshot](http://imgur.com/HBONi51)
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
13 
     | 
    
         
             
            ---
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
         @@ -43,6 +44,8 @@ To get a list of available options invoke Watchmonkey with the `--help` or `-h` 
     | 
|
| 
       43 
44 
     | 
    
         
             
                        --generate-config [myconfig] Generates a example config in ~/.watchmonkey
         
     | 
| 
       44 
45 
     | 
    
         
             
                    -l, --log [file]                 Log to file, defaults to ~/.watchmonkey/logs/watchmonkey.log
         
     | 
| 
       45 
46 
     | 
    
         
             
                    -t, --threads [NUM]              Amount of threads to be used for checking (default: 10)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    -e, --except tag1,tag2           Don't run tasks tagged with given tags
         
     | 
| 
      
 48 
     | 
    
         
            +
                    -o, --only tag1,tag2             Only run tasks tagged with given tags
         
     | 
| 
       46 
49 
     | 
    
         
             
                    -s, --silent                     Only print errors and infos
         
     | 
| 
       47 
50 
     | 
    
         
             
                    -q, --quiet                      Only print errors
         
     | 
| 
       48 
51 
     | 
    
         | 
| 
         @@ -81,6 +84,15 @@ If you want to monitor something that is not covered by the buildin handlers you 
     | 
|
| 
       81 
84 
     | 
    
         
             
            By default Watchmonkey will run all tests once and then exit. This addon will enable Watchmonkey to run in a loop and run tests on a periodic interval.
         
     | 
| 
       82 
85 
     | 
    
         
             
            Since this seems like a core feature it might get included directly into Watchmonkey but for now take a look at the [application configuration file](https://github.com/2called-chaos/watchmonkey_cli/blob/master/doc/config_example.rb) and [ReQueue source code](https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/requeue.rb) for integration examples.
         
     | 
| 
       83 
86 
     | 
    
         | 
| 
      
 87 
     | 
    
         
            +
            ### Telegram Bot
         
     | 
| 
      
 88 
     | 
    
         
            +
            Notify via Telegram. Experimental. Refer to [application configuration file](https://github.com/2called-chaos/watchmonkey_cli/blob/master/doc/config_example.rb) and [TelegramBot source code](https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/telegram_bot.rb) for further information.
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            * works with ReQueue (wouldn't make much sense otherwise huh?)
         
     | 
| 
      
 91 
     | 
    
         
            +
            * optional per-user message throttling via checker uniqid (checker name + host + arguments)
         
     | 
| 
      
 92 
     | 
    
         
            +
            * optional per-user only/except filters based on tags
         
     | 
| 
      
 93 
     | 
    
         
            +
            * planned: robust telegram connection failure handling
         
     | 
| 
      
 94 
     | 
    
         
            +
            * planned: per-user regex exclusion filters
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
       84 
96 
     | 
    
         
             
            ### Platypus support
         
     | 
| 
       85 
97 
     | 
    
         
             
            [Platypus](http://sveinbjorn.org/platypus) is a MacOS software to create dead simple GUI wrappers for scripts. There is buildin support for the interface types ProgressBar and WebView. For integration examples take a look at the [application configuration file](https://github.com/2called-chaos/watchmonkey_cli/blob/master/doc/config_example.rb) and [Platypus hook source code](https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/platypus.rb).
         
     | 
| 
       86 
98 
     | 
    
         | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            1. 
     | 
| 
      
 1 
     | 
    
         
            +
            1.12.0
         
     | 
    
        data/doc/checker_example.rb
    CHANGED
    
    | 
         @@ -12,9 +12,18 @@ module MyWatchmonkeyCheckers 
     | 
|
| 
       12 
12 
     | 
    
         
             
                #     e.g. my_checker "http://google.com", some_option: true
         
     | 
| 
       13 
13 
     | 
    
         
             
                self.checker_name = "my_checker"
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
      
 15 
     | 
    
         
            +
                # Maximum amount of time this task may run before it gets killed.
         
     | 
| 
      
 16 
     | 
    
         
            +
                # Set to 0/false to have no time limit whatsoever.
         
     | 
| 
      
 17 
     | 
    
         
            +
                # Set to proc to evaluate at runtime
         
     | 
| 
      
 18 
     | 
    
         
            +
                # Defaults to app.opts[:maxrt] if nil/unset
         
     | 
| 
      
 19 
     | 
    
         
            +
                #self.maxrt = false
         
     | 
| 
      
 20 
     | 
    
         
            +
                #self.maxrt = 5.minutes
         
     | 
| 
      
 21 
     | 
    
         
            +
                #self.maxrt = ->(app, checker, args){ app.opts[:maxrt] && app.opts[:maxrt] * 2 }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       15 
23 
     | 
    
         
             
                # Called by configuration defining a check with all the arguments.
         
     | 
| 
       16 
24 
     | 
    
         
             
                #   e.g. my_checker "http://google.com", some_option: true
         
     | 
| 
       17 
25 
     | 
    
         
             
                # Should invoke `app.enqueue` which will by default call `#check!` method with given arguments.
         
     | 
| 
      
 26 
     | 
    
         
            +
                # Must have options as last argument!
         
     | 
| 
       18 
27 
     | 
    
         
             
                def enqueue host, opts = {}
         
     | 
| 
       19 
28 
     | 
    
         
             
                  opts = { some_option: false }.merge(opts)
         
     | 
| 
       20 
29 
     | 
    
         | 
| 
         @@ -28,6 +37,7 @@ module MyWatchmonkeyCheckers 
     | 
|
| 
       28 
37 
     | 
    
         
             
                end
         
     | 
| 
       29 
38 
     | 
    
         | 
| 
       30 
39 
     | 
    
         
             
                # First argument is the result object, all other arguments came from `app.enqueue` call.
         
     | 
| 
      
 40 
     | 
    
         
            +
                # Must have options as last argument!
         
     | 
| 
       31 
41 
     | 
    
         
             
                def check! result, host, opts = {}
         
     | 
| 
       32 
42 
     | 
    
         
             
                  # Do your checks and modify the result object.
         
     | 
| 
       33 
43 
     | 
    
         
             
                  # Debug messages will not show if -s/--silent or -q/--quiet argument is passed.
         
     | 
    
        data/doc/config_example.rb
    CHANGED
    
    | 
         @@ -43,3 +43,59 @@ if @argv.delete("--platypus") 
     | 
|
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
              @opts[:colorize] = false # doesn't render in platypus
         
     | 
| 
       45 
45 
     | 
    
         
             
            end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            # Integrate Telegram notifications
         
     | 
| 
      
 50 
     | 
    
         
            +
            # For options refer to the source code:
         
     | 
| 
      
 51 
     | 
    
         
            +
            #     https://github.com/2called-chaos/watchmonkey_cli/blob/master/lib/watchmonkey_cli/hooks/telegram_bot.rb
         
     | 
| 
      
 52 
     | 
    
         
            +
            if @argv.delete("--telegram")
         
     | 
| 
      
 53 
     | 
    
         
            +
              require "watchmonkey_cli/hooks/telegram_bot"
         
     | 
| 
      
 54 
     | 
    
         
            +
              WatchmonkeyCli::TelegramBot.hook!(self, {
         
     | 
| 
      
 55 
     | 
    
         
            +
                # to create a bot refer to https://core.telegram.org/bots#6-botfather
         
     | 
| 
      
 56 
     | 
    
         
            +
                api_key: "123456789:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                # poll timeout, the longer this is (in seconds) the longer it will take to gracefully shut down
         
     | 
| 
      
 59 
     | 
    
         
            +
                timeout: 5,
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # optionally log incoming messages
         
     | 
| 
      
 62 
     | 
    
         
            +
                #logger: Logger.new(STDOUT),
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                # purge old throttle data, default: 30.days
         
     | 
| 
      
 65 
     | 
    
         
            +
                #throttle_retention: 30.days,
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                # retry sending messages that failed, default: false
         
     | 
| 
      
 68 
     | 
    
         
            +
                # Not recommended since on connection failure a HUGE amount of messages will accumulate
         
     | 
| 
      
 69 
     | 
    
         
            +
                # and spam you (and reach rate limits) upon connection restore.
         
     | 
| 
      
 70 
     | 
    
         
            +
                #retry_on_egress_failure: false,
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                # configure your notification targets, if not listed you can't interact with the bot
         
     | 
| 
      
 73 
     | 
    
         
            +
                notify: [
         
     | 
| 
      
 74 
     | 
    
         
            +
                  [
         
     | 
| 
      
 75 
     | 
    
         
            +
                    # your telegram ID, if you try talking to the bot it will tell you your ID
         
     | 
| 
      
 76 
     | 
    
         
            +
                    987654321,
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                    # flags
         
     | 
| 
      
 79 
     | 
    
         
            +
                    #   - :all        -- same as :debug, :info, :error (not recommended)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    #   - :debug      -- send all debug messages (not recommended)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    #   - :info       -- send all info messages (not recommended)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    #   - :error      -- send all error messages (RECOMMENDED)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    #   - :admin_flag -- allows access to some commands (/wm_shutdown /stats)
         
     | 
| 
      
 84 
     | 
    
         
            +
                    [:error, :admin_flag],
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    # options (all optional, you can comment them out but leave the {})
         
     | 
| 
      
 87 
     | 
    
         
            +
                    {
         
     | 
| 
      
 88 
     | 
    
         
            +
                      # throttle: seconds(int) -- throttle messages by checker uniqid for this long (0/false = no throttle, default)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      throttle: 15*60,
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                      # only: Array(string, symbol) -- only notify when tagged with given tags
         
     | 
| 
      
 92 
     | 
    
         
            +
                      only: %w[production critical],
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                      # except: Array(string, symbol) -- don't notify when tagged with given tags (runs after only-check)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      except: %w[database],
         
     | 
| 
      
 96 
     | 
    
         
            +
                    }
         
     | 
| 
      
 97 
     | 
    
         
            +
                  ],
         
     | 
| 
      
 98 
     | 
    
         
            +
                  [123456789, [:error], { throttle: 30.minutes }]
         
     | 
| 
      
 99 
     | 
    
         
            +
                ],
         
     | 
| 
      
 100 
     | 
    
         
            +
              })
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -59,9 +59,11 @@ module WatchmonkeyCli 
     | 
|
| 
       59 
59 
     | 
    
         
             
                    end
         
     | 
| 
       60 
60 
     | 
    
         
             
                  end
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                  def initialize app, file
         
     | 
| 
      
 62 
     | 
    
         
            +
                  def initialize app, file = nil, tags = []
         
     | 
| 
       63 
63 
     | 
    
         
             
                    @app = app
         
     | 
| 
       64 
64 
     | 
    
         
             
                    @file = file
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @tags = tags
         
     | 
| 
      
 66 
     | 
    
         
            +
                    return unless file
         
     | 
| 
       65 
67 
     | 
    
         
             
                    begin
         
     | 
| 
       66 
68 
     | 
    
         
             
                      eval File.read(file, encoding: "utf-8"), binding, file
         
     | 
| 
       67 
69 
     | 
    
         
             
                    rescue
         
     | 
| 
         @@ -74,9 +76,42 @@ module WatchmonkeyCli 
     | 
|
| 
       74 
76 
     | 
    
         
             
                    @app.fetch_connection(:ssh, name, opts, &b)
         
     | 
| 
       75 
77 
     | 
    
         
             
                  end
         
     | 
| 
       76 
78 
     | 
    
         | 
| 
      
 79 
     | 
    
         
            +
                  def tag_all! *tags
         
     | 
| 
      
 80 
     | 
    
         
            +
                    @tags = tags.map(&:to_sym)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
       77 
83 
     | 
    
         
             
                  def method_missing meth, *args, &block
         
     | 
| 
       78 
84 
     | 
    
         
             
                    if c = @app.checkers[meth.to_s]
         
     | 
| 
       79 
     | 
    
         
            -
                       
     | 
| 
      
 85 
     | 
    
         
            +
                      opts = args.extract_options!
         
     | 
| 
      
 86 
     | 
    
         
            +
                      only = @app.opts[:tag_only]
         
     | 
| 
      
 87 
     | 
    
         
            +
                      except = @app.opts[:tag_except]
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                      # build tags
         
     | 
| 
      
 90 
     | 
    
         
            +
                      tags = (@tags + (opts[:tags] || []).map(&:to_sym))
         
     | 
| 
      
 91 
     | 
    
         
            +
                      if @app.opts[:autotag]
         
     | 
| 
      
 92 
     | 
    
         
            +
                        tags << :"WMC-#{c.class.checker_name}" # checker name
         
     | 
| 
      
 93 
     | 
    
         
            +
                        if args[0].is_a?(Symbol)
         
     | 
| 
      
 94 
     | 
    
         
            +
                          tags << :"WMS-#{args[0]}" # ssh/local connection
         
     | 
| 
      
 95 
     | 
    
         
            +
                        elsif args[0].is_a?(String) && args[0].match(/\Ahttp(s)?:\/\//i)
         
     | 
| 
      
 96 
     | 
    
         
            +
                          uri = URI.parse(args[0]) rescue false
         
     | 
| 
      
 97 
     | 
    
         
            +
                          tags << :"WMH-#{uri.hostname.gsub(".", "_")}" if uri # hostname from URL
         
     | 
| 
      
 98 
     | 
    
         
            +
                        end
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
      
 100 
     | 
    
         
            +
                      tags = tags.uniq
         
     | 
| 
      
 101 
     | 
    
         
            +
                      @app.tag_list.merge(tags)
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                      if only.any?
         
     | 
| 
      
 104 
     | 
    
         
            +
                        if tags.any?{|t| only.include?(t) }
         
     | 
| 
      
 105 
     | 
    
         
            +
                          if tags.any?{|t| except.include?(t) }
         
     | 
| 
      
 106 
     | 
    
         
            +
                            return @app.debug "Skipping #{meth} with #{args} and #{opts} due to tag_except filter..."
         
     | 
| 
      
 107 
     | 
    
         
            +
                          end
         
     | 
| 
      
 108 
     | 
    
         
            +
                        else
         
     | 
| 
      
 109 
     | 
    
         
            +
                          return @app.debug "Skipping #{meth} with #{args} and #{opts} due to tag_only filter..."
         
     | 
| 
      
 110 
     | 
    
         
            +
                        end
         
     | 
| 
      
 111 
     | 
    
         
            +
                      elsif tags.any?{|t| except.include?(t) }
         
     | 
| 
      
 112 
     | 
    
         
            +
                        return @app.debug "Skipping #{meth} with #{args} and #{opts} due to tag_except filter..."
         
     | 
| 
      
 113 
     | 
    
         
            +
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                      c.enqueue(*args, opts.merge(tags: tags))
         
     | 
| 
       80 
115 
     | 
    
         
             
                    else
         
     | 
| 
       81 
116 
     | 
    
         
             
                      super
         
     | 
| 
       82 
117 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1,5 +1,26 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # This is a Ruby file!
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            # =========================================
         
     | 
| 
      
 4 
     | 
    
         
            +
            # = Step 0: Tag all checkers in this file =
         
     | 
| 
      
 5 
     | 
    
         
            +
            # =========================================
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # All checkers you define after this will get these
         
     | 
| 
      
 8 
     | 
    
         
            +
            # base tags (you can pass additional ones).
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Do note that you can call this method multiple
         
     | 
| 
      
 10 
     | 
    
         
            +
            # times and it will replace your base tags for
         
     | 
| 
      
 11 
     | 
    
         
            +
            # all checkers to follow, base tags will be cleared
         
     | 
| 
      
 12 
     | 
    
         
            +
            # upon reaching the end of the file.
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            tag_all! :production, :critical
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            # You can use additional tags on any checker by passing
         
     | 
| 
      
 17 
     | 
    
         
            +
            # a `tags` option consisting of an Array of strings or symbols.
         
     | 
| 
      
 18 
     | 
    
         
            +
            #   e.g.:
         
     | 
| 
      
 19 
     | 
    
         
            +
            #     some_checker :some_target, tags: %w[critical foo bar]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       3 
24 
     | 
    
         
             
            # =================================
         
     | 
| 
       4 
25 
     | 
    
         
             
            # = Step 1: Setup SSH connections =
         
     | 
| 
       5 
26 
     | 
    
         
             
            # =================================
         
     | 
| 
         @@ -36,7 +57,7 @@ ssh_connection :my_server, host: "wheel@example.com", port: 23 # additional opti 
     | 
|
| 
       36 
57 
     | 
    
         
             
            #
         
     | 
| 
       37 
58 
     | 
    
         
             
            #    timeout    Maximum time to wait for request (default: 20 seconds)
         
     | 
| 
       38 
59 
     | 
    
         
             
            #     verify    If enabled the peer will be verified (default: true)
         
     | 
| 
       39 
     | 
    
         
            -
            #  threshold    Minimum certificate lifetime before showing warnings (default:  
     | 
| 
      
 60 
     | 
    
         
            +
            #  threshold    Minimum certificate lifetime before showing warnings (default: 28.days)
         
     | 
| 
       40 
61 
     | 
    
         
             
            #
         
     | 
| 
       41 
62 
     | 
    
         
             
            ssl_expiration "https://example.com", threshold: 3.months
         
     | 
| 
       42 
63 
     | 
    
         | 
| 
         @@ -1,6 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module WatchmonkeyCli
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Application
         
     | 
| 
       3 
3 
     | 
    
         
             
                module Core
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def filtered_threads
         
     | 
| 
      
 5 
     | 
    
         
            +
                    Thread.list.reject do |thr|
         
     | 
| 
      
 6 
     | 
    
         
            +
                      thr.backtrace[0]["gems/concurrent-ruby"] rescue false
         
     | 
| 
      
 7 
     | 
    
         
            +
                    end
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       4 
10 
     | 
    
         
             
                  # ===================
         
     | 
| 
       5 
11 
     | 
    
         
             
                  # = Signal trapping =
         
     | 
| 
       6 
12 
     | 
    
         
             
                  # ===================
         
     | 
| 
         @@ -37,10 +43,31 @@ module WatchmonkeyCli 
     | 
|
| 
       37 
43 
     | 
    
         
             
                    end
         
     | 
| 
       38 
44 
     | 
    
         
             
                  end
         
     | 
| 
       39 
45 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                  def fire which, *args
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def fire which, *args, &block
         
     | 
| 
       41 
47 
     | 
    
         
             
                    return if @disable_event_firing
         
     | 
| 
       42 
     | 
    
         
            -
                    sync { debug "[Event] Firing #{which} (#{@hooks[which].try(:length) || 0} handlers) #{args.map(&:class)}", 99 }
         
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
      
 48 
     | 
    
         
            +
                    sync { debug "[Event] Firing #{which} (#{@hooks[which].try(:length) || 0} handlers) #{args.map(&:class)}#{" HAS_BLOCK" if block}", 99 }
         
     | 
| 
      
 49 
     | 
    
         
            +
                    if block && (!@hooks[which] || @hooks[which].empty?)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      block.call
         
     | 
| 
      
 51 
     | 
    
         
            +
                    else
         
     | 
| 
      
 52 
     | 
    
         
            +
                      if @hooks[which] && @hooks[which].any?
         
     | 
| 
      
 53 
     | 
    
         
            +
                        if block
         
     | 
| 
      
 54 
     | 
    
         
            +
                          catch :abort do
         
     | 
| 
      
 55 
     | 
    
         
            +
                            _fire_around(@hooks[which], args, 0, &block)
         
     | 
| 
      
 56 
     | 
    
         
            +
                          end
         
     | 
| 
      
 57 
     | 
    
         
            +
                        else
         
     | 
| 
      
 58 
     | 
    
         
            +
                          @hooks[which].all?{|h| h.call(*args) }
         
     | 
| 
      
 59 
     | 
    
         
            +
                        end
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def _fire_around hooks, args, index = 0, &block
         
     | 
| 
      
 65 
     | 
    
         
            +
                    return block.call unless hook = hooks[index]
         
     | 
| 
      
 66 
     | 
    
         
            +
                    skip = catch(:skip) {
         
     | 
| 
      
 67 
     | 
    
         
            +
                      hook.call(*args) { _fire_around(hooks, args, index + 1, &block) }
         
     | 
| 
      
 68 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                    }
         
     | 
| 
      
 70 
     | 
    
         
            +
                    _fire_around(hooks, args, index + 1, &block) if skip
         
     | 
| 
       44 
71 
     | 
    
         
             
                  end
         
     | 
| 
       45 
72 
     | 
    
         | 
| 
       46 
73 
     | 
    
         | 
| 
         @@ -81,7 +108,12 @@ module WatchmonkeyCli 
     | 
|
| 
       81 
108 
     | 
    
         | 
| 
       82 
109 
     | 
    
         
             
                  def close_connections!
         
     | 
| 
       83 
110 
     | 
    
         
             
                    @connections.each do |type, clist|
         
     | 
| 
       84 
     | 
    
         
            -
                      clist.each 
     | 
| 
      
 111 
     | 
    
         
            +
                      clist.each do |id, con|
         
     | 
| 
      
 112 
     | 
    
         
            +
                        if con.established?
         
     | 
| 
      
 113 
     | 
    
         
            +
                          debug "[SHUTDOWN] closing #{type} connection #{id} #{con}"
         
     | 
| 
      
 114 
     | 
    
         
            +
                          con.close!
         
     | 
| 
      
 115 
     | 
    
         
            +
                        end
         
     | 
| 
      
 116 
     | 
    
         
            +
                      end
         
     | 
| 
       85 
117 
     | 
    
         
             
                    end
         
     | 
| 
       86 
118 
     | 
    
         
             
                  end
         
     | 
| 
       87 
119 
     | 
    
         | 
| 
         @@ -97,8 +129,26 @@ module WatchmonkeyCli 
     | 
|
| 
       97 
129 
     | 
    
         
             
                      @queue << [checker, a, ->(*a) {
         
     | 
| 
       98 
130 
     | 
    
         
             
                        begin
         
     | 
| 
       99 
131 
     | 
    
         
             
                          result = Checker::Result.new(checker, *a)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                          # assign tags
         
     | 
| 
      
 134 
     | 
    
         
            +
                          taskopts = a.extract_options!
         
     | 
| 
      
 135 
     | 
    
         
            +
                          result.tags = taskopts[:tags] || []
         
     | 
| 
      
 136 
     | 
    
         
            +
                          a << taskopts
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
       100 
138 
     | 
    
         
             
                          checker.debug(result.str_running)
         
     | 
| 
       101 
     | 
    
         
            -
                          checker. 
     | 
| 
      
 139 
     | 
    
         
            +
                          checker.rsafe(result) {
         
     | 
| 
      
 140 
     | 
    
         
            +
                            timeout = checker.class.maxrt.nil? ? @opts[:maxrt] : checker.class.maxrt
         
     | 
| 
      
 141 
     | 
    
         
            +
                            timeout = timeout.call(self, checker, a) if timeout.respond_to?(:call)
         
     | 
| 
      
 142 
     | 
    
         
            +
                            begin
         
     | 
| 
      
 143 
     | 
    
         
            +
                              if timeout && timeout > 0
         
     | 
| 
      
 144 
     | 
    
         
            +
                                Timeout::timeout(timeout) { cb.call(result, *a) }
         
     | 
| 
      
 145 
     | 
    
         
            +
                              else
         
     | 
| 
      
 146 
     | 
    
         
            +
                                cb.call(result, *a)
         
     | 
| 
      
 147 
     | 
    
         
            +
                              end
         
     | 
| 
      
 148 
     | 
    
         
            +
                            rescue Timeout::Error => ex
         
     | 
| 
      
 149 
     | 
    
         
            +
                              result.error! "TIMEOUT: did not finish within #{timeout} seconds, task killed!"
         
     | 
| 
      
 150 
     | 
    
         
            +
                            end
         
     | 
| 
      
 151 
     | 
    
         
            +
                          }
         
     | 
| 
       102 
152 
     | 
    
         
             
                          fire(:result_dump, result, a, checker)
         
     | 
| 
       103 
153 
     | 
    
         
             
                          result.dump!
         
     | 
| 
       104 
154 
     | 
    
         
             
                        ensure
         
     | 
| 
         @@ -3,7 +3,11 @@ module WatchmonkeyCli 
     | 
|
| 
       3 
3 
     | 
    
         
             
                module Dispatch
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def dispatch action = (@opts[:dispatch] || :help)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    if respond_to?("dispatch_#{action}")
         
     | 
| 
       6 
     | 
    
         
            -
                       
     | 
| 
      
 6 
     | 
    
         
            +
                      fire(:dispatch_before, action)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      fire(:dispatch_around, action) do
         
     | 
| 
      
 8 
     | 
    
         
            +
                        send("dispatch_#{action}")
         
     | 
| 
      
 9 
     | 
    
         
            +
                      end
         
     | 
| 
      
 10 
     | 
    
         
            +
                      fire(:dispatch_after, action)
         
     | 
| 
       7 
11 
     | 
    
         
             
                    else
         
     | 
| 
       8 
12 
     | 
    
         
             
                      abort("unknown action #{action}", 1)
         
     | 
| 
       9 
13 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -41,7 +45,7 @@ module WatchmonkeyCli 
     | 
|
| 
       41 
45 
     | 
    
         
             
                  ensure
         
     | 
| 
       42 
46 
     | 
    
         
             
                    @running = false
         
     | 
| 
       43 
47 
     | 
    
         
             
                    stop_checkers!
         
     | 
| 
       44 
     | 
    
         
            -
                    close_connections!
         
     | 
| 
      
 48 
     | 
    
         
            +
                    Timeout::timeout(@opts[:conclosewait]) { close_connections! } rescue false
         
     | 
| 
       45 
49 
     | 
    
         
             
                    release_signals
         
     | 
| 
       46 
50 
     | 
    
         
             
                  end
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module WatchmonkeyCli
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Application
         
     | 
| 
       3 
     | 
    
         
            -
                attr_reader :opts, :checkers, :connections, :threads, :queue, :hooks, :processed
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :opts, :checkers, :connections, :threads, :queue, :hooks, :processed, :tag_list
         
     | 
| 
       4 
4 
     | 
    
         
             
                include Helper
         
     | 
| 
       5 
5 
     | 
    
         
             
                include OutputHelper
         
     | 
| 
       6 
6 
     | 
    
         
             
                include Colorize
         
     | 
| 
         @@ -21,9 +21,22 @@ module WatchmonkeyCli 
     | 
|
| 
       21 
21 
     | 
    
         
             
                      app.haltpoint
         
     | 
| 
       22 
22 
     | 
    
         
             
                    rescue Interrupt
         
     | 
| 
       23 
23 
     | 
    
         
             
                      app.abort("Interrupted", 1)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    rescue SystemExit
         
     | 
| 
      
 25 
     | 
    
         
            +
                      # silence
         
     | 
| 
       24 
26 
     | 
    
         
             
                    ensure
         
     | 
| 
      
 27 
     | 
    
         
            +
                      $wm_runtime_exiting = true
         
     | 
| 
       25 
28 
     | 
    
         
             
                      app.fire(:wm_shutdown)
         
     | 
| 
       26 
     | 
    
         
            -
                      app. 
     | 
| 
      
 29 
     | 
    
         
            +
                      if app.filtered_threads.length > 1
         
     | 
| 
      
 30 
     | 
    
         
            +
                        app.error "[WARN] #{app.filtered_threads.length} threads remain (should be 1)..."
         
     | 
| 
      
 31 
     | 
    
         
            +
                        app.filtered_threads.each do |thr|
         
     | 
| 
      
 32 
     | 
    
         
            +
                          app.debug "[THR] #{Thread.main == thr ? "MAIN" : "THREAD"}\t#{thr.alive? ? "ALIVE" : "DEAD"}\t#{thr.inspect}", 10
         
     | 
| 
      
 33 
     | 
    
         
            +
                          thr.backtrace.each do |l|
         
     | 
| 
      
 34 
     | 
    
         
            +
                            app.debug "[THR]\t#{l}", 20
         
     | 
| 
      
 35 
     | 
    
         
            +
                          end
         
     | 
| 
      
 36 
     | 
    
         
            +
                        end
         
     | 
| 
      
 37 
     | 
    
         
            +
                      else
         
     | 
| 
      
 38 
     | 
    
         
            +
                        app.debug "1 thread remains..."
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
       27 
40 
     | 
    
         
             
                    end
         
     | 
| 
       28 
41 
     | 
    
         
             
                  end
         
     | 
| 
       29 
42 
     | 
    
         
             
                end
         
     | 
| 
         @@ -36,6 +49,7 @@ module WatchmonkeyCli 
     | 
|
| 
       36 
49 
     | 
    
         
             
                  @monitor = Monitor.new
         
     | 
| 
       37 
50 
     | 
    
         
             
                  @threads = []
         
     | 
| 
       38 
51 
     | 
    
         
             
                  @queue = Queue.new
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @tag_list = Set.new
         
     | 
| 
       39 
53 
     | 
    
         
             
                  @processed = 0
         
     | 
| 
       40 
54 
     | 
    
         
             
                  @running = false
         
     | 
| 
       41 
55 
     | 
    
         
             
                  @opts = {
         
     | 
| 
         @@ -45,11 +59,16 @@ module WatchmonkeyCli 
     | 
|
| 
       45 
59 
     | 
    
         
             
                    colorize: true,          # -m flag
         
     | 
| 
       46 
60 
     | 
    
         
             
                    debug: false,            # -d flag
         
     | 
| 
       47 
61 
     | 
    
         
             
                    threads: 10,             # -t flag
         
     | 
| 
      
 62 
     | 
    
         
            +
                    maxrt: 120.seconds,      # max runtime of a single task after which it will be terminated (may break SSH connection), 0/false to not limit runtime
         
     | 
| 
      
 63 
     | 
    
         
            +
                    conclosewait: 10,        # max seconds to wait for connections to be closed (may never if they got killed by maxrt)
         
     | 
| 
       48 
64 
     | 
    
         
             
                    loop_forever: false,     # (internal) loop forever (app mode)
         
     | 
| 
       49 
65 
     | 
    
         
             
                    loop_wait_empty: 1,      # (internal) time to wait in thread if queue is empty
         
     | 
| 
      
 66 
     | 
    
         
            +
                    autotag: true,           # (internal) if true checkers will get auto tags for checker name and hostname/connection
         
     | 
| 
       50 
67 
     | 
    
         
             
                    silent: false,           # -s flag
         
     | 
| 
       51 
68 
     | 
    
         
             
                    quiet: false,            # -q flag
         
     | 
| 
       52 
69 
     | 
    
         
             
                    stdout: STDOUT,          # (internal) STDOUT redirect
         
     | 
| 
      
 70 
     | 
    
         
            +
                    tag_only: [],            # -o flag
         
     | 
| 
      
 71 
     | 
    
         
            +
                    tag_except: [],          # -e flag
         
     | 
| 
       53 
72 
     | 
    
         
             
                  }
         
     | 
| 
       54 
73 
     | 
    
         
             
                  init_params
         
     | 
| 
       55 
74 
     | 
    
         
             
                  yield(self)
         
     | 
| 
         @@ -63,6 +82,8 @@ module WatchmonkeyCli 
     | 
|
| 
       63 
82 
     | 
    
         
             
                    opts.on("--generate-config [myconfig]", "Generates a example config in ~/.watchmonkey") {|s| @opts[:dispatch] = :generate_config; @opts[:config_name] = s }
         
     | 
| 
       64 
83 
     | 
    
         
             
                    opts.on("-l", "--log [file]", "Log to file, defaults to ~/.watchmonkey/logs/watchmonkey.log") {|s| @opts[:logfile] = s || logger_filename }
         
     | 
| 
       65 
84 
     | 
    
         
             
                    opts.on("-t", "--threads [NUM]", Integer, "Amount of threads to be used for checking (default: 10)") {|s| @opts[:threads] = s }
         
     | 
| 
      
 85 
     | 
    
         
            +
                    opts.on("-e", "--except tag1,tag2", Array, "Don't run tasks tagged with given tags") {|s| @opts[:tag_except] = s.map(&:to_sym) }
         
     | 
| 
      
 86 
     | 
    
         
            +
                    opts.on("-o", "--only tag1,tag2", Array, "Only run tasks tagged with given tags") {|s| @opts[:tag_only] = s.map(&:to_sym) }
         
     | 
| 
       66 
87 
     | 
    
         
             
                    opts.on("-s", "--silent", "Only print errors and infos") { @opts[:silent] = true }
         
     | 
| 
       67 
88 
     | 
    
         
             
                    opts.on("-q", "--quiet", "Only print errors") { @opts[:quiet] = true }
         
     | 
| 
       68 
89 
     | 
    
         | 
| 
         @@ -74,10 +95,15 @@ module WatchmonkeyCli 
     | 
|
| 
       74 
95 
     | 
    
         
             
                    opts.on("-z", "Do not check for updates on GitHub (with -v/--version)") { @opts[:check_for_updates] = false }
         
     | 
| 
       75 
96 
     | 
    
         
             
                    opts.on("--dump-core", "for developers") { @opts[:dump] = true }
         
     | 
| 
       76 
97 
     | 
    
         
             
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
                  fire(:optparse_init, @optparse)
         
     | 
| 
       77 
99 
     | 
    
         
             
                end
         
     | 
| 
       78 
100 
     | 
    
         | 
| 
       79 
101 
     | 
    
         
             
                def parse_params
         
     | 
| 
       80 
     | 
    
         
            -
                  @optparse 
     | 
| 
      
 102 
     | 
    
         
            +
                  fire(:optparse_parse_before, @optparse)
         
     | 
| 
      
 103 
     | 
    
         
            +
                  fire(:optparse_parse_around, @optparse) do
         
     | 
| 
      
 104 
     | 
    
         
            +
                    @optparse.parse!(@argv)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  fire(:optparse_parse_after, @optparse)
         
     | 
| 
       81 
107 
     | 
    
         
             
                rescue OptionParser::ParseError => e
         
     | 
| 
       82 
108 
     | 
    
         
             
                  abort(e.message)
         
     | 
| 
       83 
109 
     | 
    
         
             
                  dispatch(:help)
         
     | 
| 
         @@ -17,6 +17,14 @@ module WatchmonkeyCli 
     | 
|
| 
       17 
17 
     | 
    
         
             
                  @checker_name = name
         
     | 
| 
       18 
18 
     | 
    
         
             
                end
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                def self.maxrt
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @maxrt
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def self.maxrt= seconds
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @maxrt = seconds
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
       20 
28 
     | 
    
         
             
                module AppHelper
         
     | 
| 
       21 
29 
     | 
    
         
             
                  def init_checkers!
         
     | 
| 
       22 
30 
     | 
    
         
             
                    @checkers = {}
         
     | 
| 
         @@ -44,16 +52,24 @@ module WatchmonkeyCli 
     | 
|
| 
       44 
52 
     | 
    
         | 
| 
       45 
53 
     | 
    
         
             
                class Result
         
     | 
| 
       46 
54 
     | 
    
         
             
                  attr_reader :checker, :type, :args
         
     | 
| 
       47 
     | 
    
         
            -
                  attr_accessor :result, :command, :data
         
     | 
| 
      
 55 
     | 
    
         
            +
                  attr_accessor :result, :command, :data, :tags
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
       49 
57 
     | 
    
         
             
                  def initialize checker, *args
         
     | 
| 
       50 
58 
     | 
    
         
             
                    @checker = checker
         
     | 
| 
       51 
59 
     | 
    
         
             
                    @args = args
         
     | 
| 
       52 
60 
     | 
    
         
             
                    @mutex = Monitor.new
         
     | 
| 
       53 
61 
     | 
    
         
             
                    @type = :info
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @tags = []
         
     | 
| 
       54 
63 
     | 
    
         
             
                    @spool = { error: [], info: [], debug: []}
         
     | 
| 
       55 
64 
     | 
    
         
             
                  end
         
     | 
| 
       56 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
                  def uniqid additional = []
         
     | 
| 
      
 67 
     | 
    
         
            +
                    ([
         
     | 
| 
      
 68 
     | 
    
         
            +
                      self.class.name,
         
     | 
| 
      
 69 
     | 
    
         
            +
                      @args.map(&:to_s).to_s,
         
     | 
| 
      
 70 
     | 
    
         
            +
                    ] + additional).join("/")
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
       57 
73 
     | 
    
         
             
                  def sync &block
         
     | 
| 
       58 
74 
     | 
    
         
             
                    @mutex.synchronize(&block)
         
     | 
| 
       59 
75 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -147,6 +163,10 @@ module WatchmonkeyCli 
     | 
|
| 
       147 
163 
     | 
    
         
             
                  end
         
     | 
| 
       148 
164 
     | 
    
         
             
                end
         
     | 
| 
       149 
165 
     | 
    
         | 
| 
      
 166 
     | 
    
         
            +
                def blank_config tags = []
         
     | 
| 
      
 167 
     | 
    
         
            +
                  Application::Configuration.new(app, nil, tags)
         
     | 
| 
      
 168 
     | 
    
         
            +
                end
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
       150 
170 
     | 
    
         
             
                # def to_s
         
     | 
| 
       151 
171 
     | 
    
         
             
                #   string = "#<#{self.class.name}:#{self.object_id} "
         
     | 
| 
       152 
172 
     | 
    
         
             
                #   fields = self.class.inspector_fields.map{|field| "#{field}: #{self.send(field)}"}
         
     | 
| 
         @@ -168,8 +188,10 @@ module WatchmonkeyCli 
     | 
|
| 
       168 
188 
     | 
    
         
             
                        error "#{descriptor}retry #{tries} reason is `#{e.class}: #{e.message}'"
         
     | 
| 
       169 
189 
     | 
    
         
             
                        e.backtrace.each{|l| debug "\t\t#{l}" }
         
     | 
| 
       170 
190 
     | 
    
         
             
                      end
         
     | 
| 
       171 
     | 
    
         
            -
                       
     | 
| 
       172 
     | 
    
         
            -
             
     | 
| 
      
 191 
     | 
    
         
            +
                      unless $wm_runtime_exiting
         
     | 
| 
      
 192 
     | 
    
         
            +
                        sleep 1
         
     | 
| 
      
 193 
     | 
    
         
            +
                        retry
         
     | 
| 
      
 194 
     | 
    
         
            +
                      end
         
     | 
| 
       173 
195 
     | 
    
         
             
                    end
         
     | 
| 
       174 
196 
     | 
    
         
             
                    error "#{descriptor}retries exceeded"
         
     | 
| 
       175 
197 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -187,10 +209,12 @@ module WatchmonkeyCli 
     | 
|
| 
       187 
209 
     | 
    
         
             
                        e.backtrace.each{|l| resultobj.debug "\t\t#{l}" }
         
     | 
| 
       188 
210 
     | 
    
         
             
                        resultobj.dump!
         
     | 
| 
       189 
211 
     | 
    
         
             
                      end
         
     | 
| 
       190 
     | 
    
         
            -
                       
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
      
 212 
     | 
    
         
            +
                      unless $wm_runtime_exiting
         
     | 
| 
      
 213 
     | 
    
         
            +
                        sleep 1
         
     | 
| 
      
 214 
     | 
    
         
            +
                        retry
         
     | 
| 
      
 215 
     | 
    
         
            +
                      end
         
     | 
| 
       192 
216 
     | 
    
         
             
                    end
         
     | 
| 
       193 
     | 
    
         
            -
                    resultobj.error! " 
     | 
| 
      
 217 
     | 
    
         
            +
                    resultobj.error! "retries exceeded"
         
     | 
| 
       194 
218 
     | 
    
         
             
                    resultobj.dump!
         
     | 
| 
       195 
219 
     | 
    
         
             
                  end
         
     | 
| 
       196 
220 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module WatchmonkeyCli
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Checkers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DevPry < Checker
         
     | 
| 
      
 4 
     | 
    
         
            +
                  self.checker_name = "dev_pry"
         
     | 
| 
      
 5 
     | 
    
         
            +
                  self.maxrt = false
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def enqueue host, opts = {}
         
     | 
| 
      
 8 
     | 
    
         
            +
                    host = app.fetch_connection(:loopback, :local) if !host || host == :local
         
     | 
| 
      
 9 
     | 
    
         
            +
                    host = app.fetch_connection(:ssh, host) if host.is_a?(Symbol)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    app.enqueue(self, host, opts)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def check! result, host, opts = {}
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if app.opts[:threads] > 1
         
     | 
| 
      
 15 
     | 
    
         
            +
                      result.error! "pry only works properly within the main thread, run watchmonkey with `-t0`"
         
     | 
| 
      
 16 
     | 
    
         
            +
                      return
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 20 
     | 
    
         
            +
                      require "pry"
         
     | 
| 
      
 21 
     | 
    
         
            +
                      binding.pry
         
     | 
| 
      
 22 
     | 
    
         
            +
                      1+1 # pry may bug out otherwise if it's last statement
         
     | 
| 
      
 23 
     | 
    
         
            +
                    rescue LoadError => ex
         
     | 
| 
      
 24 
     | 
    
         
            +
                      result.error! "pry is required (gem install pry)! #{ex.class}: #{ex.message}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -4,7 +4,7 @@ module WatchmonkeyCli 
     | 
|
| 
       4 
4 
     | 
    
         
             
                  self.checker_name = "ssl_expiration"
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
                  def enqueue page, opts = {}
         
     | 
| 
       7 
     | 
    
         
            -
                    opts = { threshold:  
     | 
| 
      
 7 
     | 
    
         
            +
                    opts = { threshold: 28.days, verify: true, timeout: 20 }.merge(opts)
         
     | 
| 
       8 
8 
     | 
    
         
             
                    app.enqueue(self, page, opts)
         
     | 
| 
       9 
9 
     | 
    
         
             
                  end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -35,7 +35,9 @@ module WatchmonkeyCli 
     | 
|
| 
       35 
35 
     | 
    
         
             
                      #   sec.check!(result, host, opts[which])
         
     | 
| 
       36 
36 
     | 
    
         
             
                      # end
         
     | 
| 
       37 
37 
     | 
    
         
             
                      # app.enqueue_sub(self, which, host, opts[which]) if opts[which]
         
     | 
| 
       38 
     | 
    
         
            -
                      spawn_sub(which, host, opts[which].is_a?(Hash) ? opts[which] : {}) unless opts[which] == false
         
     | 
| 
      
 38 
     | 
    
         
            +
                      #spawn_sub(which, host, (opts[which].is_a?(Hash) ? opts[which] : {}).merge(tags: result.tags)) unless opts[which] == false
         
     | 
| 
      
 39 
     | 
    
         
            +
                      stags = (opts[:tags] || []).reject{|t| t.to_s.start_with?("WMC-") }
         
     | 
| 
      
 40 
     | 
    
         
            +
                      blank_config(stags).send(which, host, (opts[which].is_a?(Hash) ? opts[which] : {})) unless opts[which] == false
         
     | 
| 
       39 
41 
     | 
    
         
             
                    end
         
     | 
| 
       40 
42 
     | 
    
         
             
                  end
         
     | 
| 
       41 
43 
     | 
    
         
             
                end
         
     | 
| 
         @@ -9,7 +9,8 @@ module WatchmonkeyCli 
     | 
|
| 
       9 
9 
     | 
    
         
             
                    # if available enable ssl_expiration support
         
     | 
| 
       10 
10 
     | 
    
         
             
                    if page.start_with?("https://") && opts[:ssl_expiration] != false && !app.running?
         
     | 
| 
       11 
11 
     | 
    
         
             
                      sopts = { timeout: opts[:timeout] }.merge(opts[:ssl_expiration].is_a?(Hash) ? opts[:ssl_expiration] : {})
         
     | 
| 
       12 
     | 
    
         
            -
                       
     | 
| 
      
 12 
     | 
    
         
            +
                      stags = (opts[:tags] || []).reject{|t| t.to_s.start_with?("WMC-") }
         
     | 
| 
      
 13 
     | 
    
         
            +
                      blank_config(stags).ssl_expiration(page, sopts)
         
     | 
| 
       13 
14 
     | 
    
         
             
                    end
         
     | 
| 
       14 
15 
     | 
    
         
             
                  end
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
         @@ -71,7 +71,7 @@ module WatchmonkeyCli 
     | 
|
| 
       71 
71 
     | 
    
         
             
                                <dt>Items in Queue</dt><dd class="qlength">#{@queue.length}</dd>
         
     | 
| 
       72 
72 
     | 
    
         
             
                                <dt>Items in ReQ</dt><dd class="rqlength">#{@requeue.length}</dd>
         
     | 
| 
       73 
73 
     | 
    
         
             
                                <dt>Workers</dt><dd class="workers">#{@threads.select{|t| t[:working] }.length}/#{@threads.length} working (#{@threads.select(&:alive?).length} alive)</dd>
         
     | 
| 
       74 
     | 
    
         
            -
                                <dt>Threads</dt><dd class="tlength">#{ 
     | 
| 
      
 74 
     | 
    
         
            +
                                <dt>Threads</dt><dd class="tlength">#{filtered_threads.length}</dd>
         
     | 
| 
       75 
75 
     | 
    
         
             
                                <dt>Processed entries</dt><dd class="processed">#{@processed}</dd>
         
     | 
| 
       76 
76 
     | 
    
         
             
                                <dt>Watching since</dt><dd>#{@boot}</dd>
         
     | 
| 
       77 
77 
     | 
    
         
             
                                <dt>Last draw</dt><dd class="lastdraw">#{Time.current}</dd>
         
     | 
| 
         @@ -93,7 +93,7 @@ module WatchmonkeyCli 
     | 
|
| 
       93 
93 
     | 
    
         
             
                            $("dd.qlength").html("#{@queue.length}");
         
     | 
| 
       94 
94 
     | 
    
         
             
                            $("dd.rqlength").html("#{@requeue.length}");
         
     | 
| 
       95 
95 
     | 
    
         
             
                            $("dd.workers").html("#{@threads.select{|t| t[:working] }.length}/#{@threads.length} working#{ti}");
         
     | 
| 
       96 
     | 
    
         
            -
                            $("dd.tlength").html("#{ 
     | 
| 
      
 96 
     | 
    
         
            +
                            $("dd.tlength").html("#{filtered_threads.length}");
         
     | 
| 
       97 
97 
     | 
    
         
             
                            $("dd.processed").html("#{@processed}");
         
     | 
| 
       98 
98 
     | 
    
         
             
                            $("dd.lastdraw").html("#{Time.current}");
         
     | 
| 
       99 
99 
     | 
    
         
             
                            $("pre.lasterrors").html("#{escape_javascript @platypus_status_cache[:errors].map{|t,e| "#{t}: #{e}" }.join("\n")}");
         
     | 
| 
         @@ -37,11 +37,12 @@ module WatchmonkeyCli 
     | 
|
| 
       37 
37 
     | 
    
         
             
                          puts "     Queue: #{@queue.length}"
         
     | 
| 
       38 
38 
     | 
    
         
             
                          puts "   Requeue: #{@requeue.length}"
         
     | 
| 
       39 
39 
     | 
    
         
             
                          puts "   Workers: #{@threads.select{|t| t[:working] }.length}/#{@threads.length} working (#{@threads.select(&:alive?).length} alive)"
         
     | 
| 
       40 
     | 
    
         
            -
                          puts "   Threads: #{ 
     | 
| 
      
 40 
     | 
    
         
            +
                          puts "   Threads: #{filtered_threads.length}"
         
     | 
| 
       41 
41 
     | 
    
         
             
                          # puts "            #{@threads.select(&:alive?).length} alive"
         
     | 
| 
       42 
42 
     | 
    
         
             
                          # puts "            #{@threads.select{|t| t.status == "run" }.length} running"
         
     | 
| 
       43 
43 
     | 
    
         
             
                          # puts "            #{@threads.select{|t| t.status == "sleep" }.length} sleeping"
         
     | 
| 
       44 
44 
     | 
    
         
             
                          puts " Processed: #{@processed}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                          puts "  Promises: #{@telegram_bot_egress_promises.length}" if @telegram_bot_egress_promises
         
     | 
| 
       45 
46 
     | 
    
         
             
                          puts "========== //STATUS =========="
         
     | 
| 
       46 
47 
     | 
    
         
             
                        end
         
     | 
| 
       47 
48 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -101,6 +102,16 @@ module WatchmonkeyCli 
     | 
|
| 
       101 
102 
     | 
    
         
             
                        }]
         
     | 
| 
       102 
103 
     | 
    
         
             
                      end
         
     | 
| 
       103 
104 
     | 
    
         
             
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    def requeue_runall
         
     | 
| 
      
 107 
     | 
    
         
            +
                      return if $wm_runtime_exiting
         
     | 
| 
      
 108 
     | 
    
         
            +
                      sync do
         
     | 
| 
      
 109 
     | 
    
         
            +
                        debug "Running all queued tasks immediately!"
         
     | 
| 
      
 110 
     | 
    
         
            +
                        @requeue.each_with_index do |(run_at, callback), index|
         
     | 
| 
      
 111 
     | 
    
         
            +
                          @requeue[index][0] = Time.now
         
     | 
| 
      
 112 
     | 
    
         
            +
                        end
         
     | 
| 
      
 113 
     | 
    
         
            +
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
       104 
115 
     | 
    
         
             
                  end
         
     | 
| 
       105 
116 
     | 
    
         
             
                end
         
     | 
| 
       106 
117 
     | 
    
         
             
              end
         
     |