Git Product home page Git Product logo

i4w_callapi's People

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Forkers

phibos rsmuc

i4w_callapi's Issues

Cluttered stdout if REST API responds with not-whitelisted error

If a check command was not correctly whitelisted, call_api_check.exe generates stdout like

error decoding response body: invalid type: string "The command \"Invoke-IcingaCheckUsedPartitionSpace\" you are trying to execute over this REST-Api endpoint \"apichecks\" is not whitelisted for remote execution.", expected a map at line 1 column 163

It should better be

The command "Invoke-IcingaCheckUsedPartitionSpace" you are trying to execute over this REST-Api endpoint "apichecks" is not whitelisted for remote execution.

Noticed while testing against icinga-powershell-restapi v1.1.1 and icinga-powershell-apichecks v1.1.1.

Whitespace in Performance Data String missing

call_api_check.exe returns:

call_api_check.exe --insecure -c Invoke-IcingaCheckCPU -- -Warning 50 -Critical 90
[OK] CPU Load | 'total::ifw_cpu::load'=10.83043%;50;90;0;100'0::ifw_cpu::load'=10.59017%;50;90;0;100'1::ifw_cpu::load'=13.73456%;50;90;0;100'2::ifw_cpu::load'=6.521813%;50;90;0;100'3::ifw_cpu::load'=16.81004%;50;90;0;100'4::ifw_cpu::load'=11.42742%;50;90;0;100'5::ifw_cpu::load'=5.701193%;50;90;0;100'6::ifw_cpu::load'=10.92389%;50;90;0;100'7::ifw_cpu::load'=19.98314%;50;90;0;100

The whitespaces in the Perforance Data String are missing. Correct result:

call_api_check.exe --insecure -c Invoke-IcingaCheckCPU -- -Warning 50 -Critical 90
[OK] CPU Load | 'total::ifw_cpu::load'=12.0196%;50;90;0;100 '0::ifw_cpu::load'=8.363997%;50;90;0;100 '1::ifw_cpu::load'=14.61809%;50;90;0;100 '2::ifw_cpu::load'=15.7204%;50;90;0;100 '3::ifw_cpu::load'=7.820164%;50;90;0;100 '4::ifw_cpu::load'=18.41076%;50;90;0;100 '5::ifw_cpu::load'=8.620053%;50;90;0;100 '6::ifw_cpu::load'=9.70791%;50;90;0;100 '7::ifw_cpu::load'=12.69952%;50;90;0;100

Read settings from $PSScriptRoot/config/config.json?

We currently set https port and timeout either from command line arguments, or set them to default if not given.

The original Invoke-IcingaApiChecksRESTCall instead reads a config.json file from e.g. C:/Program Files/WindowsPowerShell/Modules/icinga-powershell-framework/config/config.json to determine those values.

This involves figuring out where $PSScriptRoot is, and introduces a dependency on another JSON interface, which I'd rather avoid. But if someone thinks evaluating config.json is important, leave a note here and I may consider adding it anyway.

Disk and Service check not working

Hi
first f all thanks for the effort for creating this tool. I am currently trying it out to see if this can "replace"(or better enhance) the powershell framework checks.

Second, please excuse the blant title :)

But I can't figure out how to configure the checks/check commands for the Disk and Windows Service checks to have them work correctly.
I tried configuring them close to the example with the CPU check (which worked for the memory check), but there seem to be more changes needed.

Disk Check
current output
image
executed command line
'C:\Program Files\ICINGA2\/sbin/call_api_check.exe' '--insecure' '-c' 'Invoke-IcingaCheckUsedPartitionSpace' '--' '-Warning' '85' '-Critical' '95' '-Include' '@()' '-Exclude' '@()'
configured command, basically left as it came from the PowerShell Framework basket to be imported into the Icinga Director. Only changed the -c parameter and its position.

object CheckCommand "Invoke-IcingaCheckUsedPartitionSpace_api workaround" {
    import "PowerShell Base_api workaround"

    arguments += {
        "-Critical" = {
            order = 3
            value = "$IcingaCheckUsedPartitionSpace_Object_Critical$"
        }
        "-Exclude" = {
            order = 5
            value = {{
                var arr = macro("$IcingaCheckUsedPartitionSpace_Array_Exclude$");
                if (len(arr) == 0) {
                    return "@()";
                }
                return arr.map(
                    x => if (typeof(x) == String) {
                        var argLen = len(x);
                        if (argLen != 0 && x.substr(0,1) == "'" && x.substr(argLen - 1, argLen) == "'") {
                            x;
                        } else {
                            "'" + x + "'";
                        }
                    } else {
                        x;
                    }
                ).join(",");
            }}
        }
        "-IgnoreEmptyChecks" = {
            order = 99
            set_if = "$IcingaCheckUsedPartitionSpace_Switchparameter_IgnoreEmptyChecks$"
        }
        "-Include" = {
            order = 4
            value = {{
                var arr = macro("$IcingaCheckUsedPartitionSpace_Array_Include$");
                if (len(arr) == 0) {
                    return "@()";
                }
                return arr.map(
                    x => if (typeof(x) == String) {
                        var argLen = len(x);
                        if (argLen != 0 && x.substr(0,1) == "'" && x.substr(argLen - 1, argLen) == "'") {
                            x;
                        } else {
                            "'" + x + "'";
                        }
                    } else {
                        x;
                    }
                ).join(",");
            }}
        }
        "-NoPerfData" = {
            order = 99
            set_if = "$IcingaCheckUsedPartitionSpace_Switchparameter_NoPerfData$"
        }
        "-SkipUnknown" = {
            order = 99
            set_if = "$IcingaCheckUsedPartitionSpace_Switchparameter_SkipUnknown$"
        }
        "-Verbosity" = {
            order = 6
            value = "$IcingaCheckUsedPartitionSpace_Int32_Verbosity$"
        }
        "-Warning" = {
            order = 2
            value = "$IcingaCheckUsedPartitionSpace_Object_Warning$"
        }
        "-c" = {
            order = -2
            value = "Invoke-IcingaCheckUsedPartitionSpace"
        }
    }
    vars.IcingaCheckUsedPartitionSpace_Switchparameter_IgnoreEmptyChecks = false
    vars.IcingaCheckUsedPartitionSpace_Switchparameter_NoPerfData = false
    vars.IcingaCheckUsedPartitionSpace_Switchparameter_SkipUnknown = false
}

As the description for the "Include" parameter field states that "Used to specify an array of partitions to be included. If not set, the check expects that all not excluded partitions should be checked. e.g. 'C:','D:'" I assumed/hoped that this would still work.

Adding a single partition to the check changes the command executed, but not the outcome
'C:\Program Files\ICINGA2\/sbin/call_api_check.exe' '--insecure' '-c' 'Invoke-IcingaCheckUsedPartitionSpace' '--' '-Warning' '85' '-Critical' '95' '-Include' ''\''C:\'\''' '-Exclude' '@()'

Services Check
There might be something similar happening to the services check, because the output is as follows:
image
while the command executed is
'C:\Program Files\ICINGA2\/sbin/call_api_check.exe' '--insecure' '-c' 'Invoke-IcingaCheckService' '--' '-Service' ''\''DcomLaunch'\''' '-Exclude' '@()' '-NoPerfData'
command definition

object CheckCommand "Invoke-IcingaCheckService_api workaround" {
    import "PowerShell Base_api workaround"

    arguments += {
        "-Exclude" = {
            order = 3
            value = {{
                var arr = macro("$IcingaCheckService_Array_Exclude$");
                if (len(arr) == 0) {
                    return "@()";
                }
                return arr.map(
                    x => if (typeof(x) == String) {
                        var argLen = len(x);
                        if (argLen != 0 && x.substr(0,1) == "'" && x.substr(argLen - 1, argLen) == "'") {
                            x;
                        } else {
                            "'" + x + "'";
                        }
                    } else {
                        x;
                    }
                ).join(",");
            }}
        }
        "-NoPerfData" = {
            order = 99
            set_if = "$IcingaCheckService_Switchparameter_NoPerfData$"
        }
        "-Service" = {
            order = 2
            value = {{
                var arr = macro("$IcingaCheckService_Array_Service$");
                if (len(arr) == 0) {
                    return "@()";
                }
                return arr.map(
                    x => if (typeof(x) == String) {
                        var argLen = len(x);
                        if (argLen != 0 && x.substr(0,1) == "'" && x.substr(argLen - 1, argLen) == "'") {
                            x;
                        } else {
                            "'" + x + "'";
                        }
                    } else {
                        x;
                    }
                ).join(",");
            }}
        }
        "-Status" = {
            order = 4
            value = "$IcingaCheckService_String_Status$"
        }
        "-Verbosity" = {
            order = 5
            value = "$IcingaCheckService_Int32_Verbosity$"
        }
        "-c" = {
            order = -2
            value = "Invoke-IcingaCheckService"
        }
    }
    vars.IcingaCheckService_Switchparameter_NoPerfData = false
}

Could both be related to the Icinga Directors way of escaping stuff.
For the services check it looks to me like that the single quotes framing the service name would have to be omitted.
But I don't know how/where to implement a solution for both problems, so sorry for just saying "i doesn't work" :/

Negative numbers and thresholds wrongly interpreted as switch arguments

Icinga for Windows plugins expect warning and critical thresholds in nagios threshold format by convention. These command lines all give valid range values for a parameter named Warning: -Warning -123, -Warning '@:123, -Warning -123:123. However, call_api_check detects -123 and -123:123 as switch parameter.

We don't have access to the params statement from the Cmdlet, which would indicate the parameter names and types (e.g. [switch]). Without, it's difficult to disambiguate. By trial, I've found that powershell.exe always interprets dash followed by digit as value and doesn't bind it to variables. This should help to detect above cases successfully.

Test API availability and fallback to local execution?

We currently execute check commands unconditionally over REST API.

The original Invoke-IcingaApiChecksRESTCall performs some additional runtime tests during each execution

  • is the PS framework running as daemon?
  • is the API forward feature enabled?
  • is the Icinga for Windows service installed and running?
  • is one of icinga-powershell-restapi, icinga-powershell-apichecks installed?
  • has a valid HTTP response been received?

If one fails, the check command is executed locally, i.e. as child process of the agent.

My personal opinion is, all these tests are useful for diagnostics, but they don't have to run with each command execution. If using REST API is configured by object CheckCommand, then they're supposed to work. If something doesn't work, it's a bug in software or in configuration and the bug needs to be fixed. Fallbacks hide such bugs.

If you thinks such runtime tests are important, leave a note here.

No output generated if REST API responds with incomplete JSON

For certain execution errors at the API side, the REST API may respond with a JSON like

{"Invoke-IcingaCheckService" :{"exitcode":{}, "checkresult": "", "perfdata": {}}}

call_api_check.exe currently handles the case by returning an empty string and exit code 3 = unknown.

Exit code = unknown is correct (we can't know what the real result would have been), but we should additionally print a message that can be displayed as summary. Maybe something like "Incomplete API response for Invoke-IcingaCheckService".

Implement a PowerShell-like CLI parsing mode

As learned from Icinga/icinga-powershell-apichecks/issues/3, we (the API client) must analyze the CLI input and build the check arguments as structured JSON types. It's not sufficient to just forward the CLI args as JSON strings.

For those using the Icinga Director it's most convenient to expect the input as PowerShell arguments, because that's what we get from the Icinga PS config generator. I.e., we have to parse and deserialize a subset of PowerShell argument mode syntax.

This is absolutely not about being fully PS syntax compliant, that would almost be impossible to achieve. On the other hand, I want to support a bit more grammar rules than the current Icinga generator relies on, to be future proof, and because it's an nice exercise.

Examples

PS CLI Arg (as in argv) JSON structure Remark
-MyArg {"MyArg": true} Switch without argument means the parameter is JSON bool true.
-MyArg foo {"MyArg": "foo"} If it looks like a string, turn it into JSON string.
-MyArg "foo" {"MyArg": "foo"} Make explicit string by enclosing in double quotes.
-MyArg 123 {"MyArg": 123} If it looks like a number, turn it into a JSON number.
-MyArg foo,123 {"MyArg": ["foo", 123]} Literal comma produces array...
-MyArg "foo,123" {"MyArg": "foo,123"} ...except where enclosed in quotes.
-MyArg ["foo",123] {"MyArg": ["foo", 123]} Another way to write an array is using square brackets.
-MyArg @("foo",123) {"MyArg": ["foo", 123]} Yet another way to write an array is using @().
-MyArg [ foo , [ 123 , 456 ] ] {"MyArg": ["foo", [123, 456]]} Arrays can be nested. Whitespaces outside quotes are ignored.
-MyArg $False,$True {"MyArg": [false, true]} These special variables are turned into JSON bool.
-MyArg '"hello, world"' {"MyArg": "\"hello, world\""} Enclosing in single quotes prevents control character handling (except for backtick)
-MyArg "literal `" doublequote" {"MyArg": "literal \" doublequote"} backticks can be used to escape control characters, except if inside single quotes.
-MyArg (ConvertTo-IcingaSecureString 'my string') {"MyArg": "(ConvertTo-IcingaSecureString 'my string')"} Pass as string, the API will internally decide on what to do.

Once done, this should fix #4.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.