How do Sensu handler notification plugins determine the path of their JSON config files? So, we're transitioning from Slack to MSTeams. I'm tasked with updating our Sensu configuration so that alerts get sent to MSTeams channels instead of Slack channels.

In the /etc/sensu/conf.d/handlers.json, we have Slack notifications configured as follows:

...
"slack" : {
    "type": "pipe",
    "command": "handler-slack.rb -j slack",
    "filters": [
        "occurrences"
    ]
},
....


That -j slack tells the handler to load a JSON config file which is located at /etc/sensu/conf.d/slack.d/slack.json.

The Teams handler is configured similarly:

...
"microsoft-teams" : {
    "type": "pipe",
    "command": "handler-microsoft-teams.rb -j microsoft-teams",
    "filters": [
        "occurrences"
    ]
},
...


But when Sensu tries to pass a notification to the Teams handler, I get an error that leads me to believe that the JSON config wasn't loaded:

/opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugins-microsoft-teams-2.0.0/bin/handler-microsoft-teams.rb:104:in `get_setting': undefined method `[]' for nil:NilClass (NoMethodError)
    from /opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugins-microsoft-teams-2.0.0/bin/handler-microsoft-teams.rb:28:in `payload_template'
    from /opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugins-microsoft-teams-2.0.0/bin/handler-microsoft-teams.rb:108:in `handle'
    from /opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugin-2.7.1/lib/sensu-handler.rb:89:in `block in &lt;class:Handler&gt;'


payload_template is the first setting that handler-microsoft-teams.rb attempts to load. It is not specified in my JSON, and the code is written to treat it as optional. 

So, my question is this: how does the Slack plugin go from the string passed to the -j argument (slack) to the path /etc/sensu/conf.d/slack.d/slack.json? And how do I determine the equivalent path magic for the Teams plugin? I don't know if this magic is inherent in Ruby (in which I'm a non-expert), Sensu, sensu-plugins, or something else. I've been digging in code for a while now and I'm coming up empty.

(Yes, I'm aware of Sensu Go and would like to upgrade; that's not an option on my current timeline.)
Okay, so it turns out this wasn't my problem, but I know the answer to the question I asked:

The file /opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugins-microsoft-teams-2.0.0/bin/handler-microsoft-teams.rb defines a function get_setting, which looks like this:

def get_setting(name)
  settings[config[:json_config]][name]
end


config[:json_config] is the string passed with the -j switch.

On to config: the file /opt/sensu/embedded/lib/ruby/gems/2.4.0/gems/sensu-plugin-2.7.1/lib/sensu-handler.rb requires sensu-plugin/utils, which defines the following:

module Sensu
  module Plugin
    module Utils # rubocop:disable Metrics/ModuleLength
      def config_files
        if ENV['SENSU_LOADED_TEMPFILE'] &amp;&amp; File.file?(ENV['SENSU_LOADED_TEMPFILE'])
          IO.read(ENV['SENSU_LOADED_TEMPFILE']).split(':')
        elsif ENV['SENSU_CONFIG_FILES']
          ENV['SENSU_CONFIG_FILES'].split(':')
        else
          ['/etc/sensu/config.json'] + Dir['/etc/sensu/conf.d/**/*.json']
        end
      end

      def load_config(filename)
        JSON.parse(File.open(filename, 'r').read)
      rescue
        {}
      end

      def settings
        @settings ||= config_files.map { |f| load_config(f) }.reduce { |a, b| deep_merge(a, b) }
      end
...


So settings is going to load all JSON files nested anywhere under /etc/sensu/conf.d/ and deep-merge them. Beyond that, the path is not relevant to Sensu's ability to load it using the string slack; that's the name of the entry in the JSON payload. This mechanism is common to all Sensu config, not just handler plugins. Documentation is here: https://docs.sensu.io/sensu-core/1.8/reference/configuration/.

I looked at my log files, and it does seem to be finding and loading the files I had optimistically placed under /etc/sensu/conf.d/teams.d/, but it's not working.

Before I found the answer documented here, I took a stab and renamed the directory from teams.d to microsoft-teams.d, and the configuration object defined within from teams to microsoft-teams. I don't know why that would have had any effect, but it's working now. Maybe I had fat-fingered or copypasta'd something and resolved that inadvertently in the process of adding the microsoft prefix.