nagios-http-json icon indicating copy to clipboard operation
nagios-http-json copied to clipboard

Multiple keys equals not working when passed as string

Open Napsty opened this issue 1 year ago • 6 comments

The plugin works when multiple keys and their equals lookup values are passed as stdin:

$ ./check_http_json.py -H api.example.com -s -p "health.json" -q service1.status,True service2.status,True service3.status,True
OK: Status OK.

The plugin seems to parse each input argument. Which is fine.

But if the keys are defined in a string and given to the plugin, it will fail:

$ ./check_http_json.py -H api.example.com -s -p "health.json" -q "service1.status,True service2.status,True service3.status,True"
Traceback (most recent call last):
  File "/home/ckadm/Git/nagios-http-json/./check_http_json.py", line 672, in <module>
    main(sys.argv[1:])
  File "/home/ckadm/Git/nagios-http-json/./check_http_json.py", line 660, in main
    nagios.append_message(WARNING_CODE, processor.checkWarning())
  File "/home/ckadm/Git/nagios-http-json/./check_http_json.py", line 338, in checkWarning
    failure += self.checkEquality(self.key_value_list)
  File "/home/ckadm/Git/nagios-http-json/./check_http_json.py", line 267, in checkEquality
    k, v = kv.split(',')
ValueError: too many values to unpack (expected 2)

Why is this important? Because it breaks the plugin under Icinga2 (and maybe on different monitoring core software, too), as the input/variable vars.http_json_key_equals is handed over to the plugin as string (see https://github.com/drewkerrigan/nagios-http-json/blob/master/contrib/icinga2_check_command_definition.conf#L81).

Napsty avatar Jul 17 '24 13:07 Napsty

Interesting, I'll have a look at it

martialblog avatar Jul 22 '24 07:07 martialblog

Had a quick look.

First, yeah we should do something about that ugly error. I'll try to have a cleaner solution.

Second,

-q service1.status,True service2.status,True and -q "service1.status,True service2.status,True" are not the same semantically. -q service1.status,True service2.status,True means two values for the -q flag, -q "service1.status,True service2.status,True" means one value for the -q flag.

Similar with other CLI tools:

touch foo bar
touch "foo bar foo"

ls -l
total 0

bar
foo
'foo bar foo'

I'm sure you can tell your monitoring tool to pass multiple string values to flag, like so:

-q "service1.status,True" "service2.status,True" "service3.status,True"

martialblog avatar Jul 29 '24 07:07 martialblog

I'm sure you can tell your monitoring tool to pass multiple string values to flag, like so

will have to look into this, but I don't think the current CheckCommand definition covers this.

Napsty avatar Jul 29 '24 07:07 Napsty

Not an CheckCommand expert myself, but maybe like this? [ "exclude=sppsvc", "exclude=ShellHWDetection" ]

Copied from here: https://icinga.com/docs/icinga-2/latest/doc/03-monitoring-basics/#command-arguments

martialblog avatar Jul 29 '24 08:07 martialblog

I'm aware of the array handling of arguments in Icinga2, but, AFAIK, this requires the repeat_key parameter set to true, which is not the case in the current CheckCommand (that's what I meant with my previous comment).

https://github.com/drewkerrigan/nagios-http-json/blob/master/contrib/icinga2_check_command_definition.conf#L84

Napsty avatar Jul 29 '24 09:07 Napsty

Asked around... someone suggested:

    arguments += {
        "(no key)" = {
            order = 21
            skip_key = true
            value = "$sth_2$"
        }

        "(no key.2)" = {
            order = 22
            skip_key = true
            value = "$sth_3$"
        }
        "-q" = {
            order = 20
            value = "$sth_1$"
        }
    }

martialblog avatar Jul 29 '24 09:07 martialblog

Is there an eta for version 2.3.0? We are also struggling with this issue.

K0nne avatar Jan 09 '25 09:01 K0nne

We have the 'same' problem. We use Icinga and I found no way to change the behavour. Icinga puts single quotes around the arguments e,g you will have something like '-w' 'key1,10000 key2,45' '-c' 'key1,~: key2,50' on the command line. I made a pach-version that handles this, but only for the arguments -c and -w where I split the argumentvalues for key_threshold_critical and key_threshold_warning after they are red by the argument parser. Will the next version of the check solve this generally for all arguments with this problem? Should I add my patch?

mdicss avatar Mar 27 '25 11:03 mdicss

Did some more testing the following data:

{
  "service1": {
    "status": true
  },
  "service2": {
    "status": true,
    "meta": {
      "res": "PONG"
    }
  },
  "service3": {
    "status": true,
    "meta": {
      "status": "notok"
    }
  },
  "service4": {
    "status": true,
    "meta": {
      "status": "ok"
    }
  }
}

Once with multiple -q flags:

python check_http_json.py -H localhost:8080 -p data5.json -q service1.status,True -q service2.status,True -q service3.status,True 
OK: Status OK.

python check_http_json.py -H localhost:8080 -p data5.json -q service1.status,True -q service2.status,True -q service3.status,False
WARNING: Status WARNING. Key service3.status mismatch. False != True

Once with a single -q flag with multiple parameters:

python check_http_json.py -H localhost:8080 -p data5.json -q "service1.status,True" "service2.status,True" "service3.status,True"
OK: Status OK.

python check_http_json.py -H localhost:8080 -p data5.json -q "service1.status,True" "service2.status,True" "service3.status,False"
WARNING: Status WARNING. Key service3.status mismatch. False != True

Then I tried to wrap this into an Icinga2 config:

object Host "ExempliGratia" {
  import "generic-host"

  address = "127.0.0.1"
  address6 = "::1"

  vars.http_json_address = "192.168.178.1"
  vars.http_json_port = "8080"
  vars.http_json_path = "data5.json"
  vars.http_json_key_equals = ["service1.status,True", "service2.status,True", "service3.status,False"]
}

apply Service "httpjson" {
  import "generic-service"

  check_command = "http_json"

  assign where host.name == "ExempliGratia"
}

object CheckCommand "http_json" {
		import "plugin-check-command"

		command = [ PluginDir + "/check_http_json.py" ]

		arguments = {
		"--host" = {
			value = "$http_json_address$"
			description = "Hostname or address of the interface to query"
			required = true
		}
		"--port" = {
			value = "$http_json_port$"
			description = "TCP port number"
		}
		"--path" = {
			value = "$http_json_path$"
			description = "URL path to query (i.e.: /v1/service/xyz)"
		}
		"--key_equals" = {
			value = "$http_json_key_equals$"
                        repeat_key = true
		}
	}
}

Results in:

'/usr/lib/nagios/plugins/check_http_json.py' '--host' '192.168.178.1' '--key_equals' 'service1.status,True' '--key_equals' 'service2.status,True' '--key_equals' 'service3.status,False' '--path' 'data5.json' '--port' '8080'

So, code does what it supposed to do and an Icinga configuration should be possible.

I'll try to update the contrib/ example.

martialblog avatar Apr 11 '25 13:04 martialblog