atc0005 / check-statuspage

Go-based tooling to interact with status page APIs hosted by Atlassian Statuspage; NOT affiliated with or endorsed by Atlassian.
MIT License
5 stars 0 forks source link

Create prototype plugin #1

Closed atc0005 closed 2 years ago

atc0005 commented 2 years ago

I noticed in our Nagios XI instance today that an older shell script (text pattern matching) is no longer reliably matching on the status details available on Box.com's status page.

Instead of trying to update the shell script, I'm interested in trying to develop a prototype plugin that can parse the public API (JSON) instead.

atc0005 commented 2 years ago

Note: After the plugin works, it should be usable on nearly any status page hosted by Atlassian Statuspage.

I plan to offer a --components flag to allow specifying which components to monitor instead of hard-coding specific values in the plugin.

atc0005 commented 2 years ago

Note: After the plugin works, it should be usable on nearly any status page hosted by Atlassian Statuspage.

I plan to offer a --components flag to allow specifying which components to monitor instead of hard-coding specific values in the plugin.

To aid in that, I can use a few other status pages to confirm functionality:

Both of those offer services spread geographically, so there should be plenty of sample data to test against between the three status pages.

atc0005 commented 2 years ago

The Box.com https://status.linode.com/api/v2/components.json URL provides a listing of components, but seems to duplicate many of the entries. I can tell that they're grouped, but I don't yet see why there are multiple groups with a component within each of the same name.

I looked at the Linode status page components.json file and it doesn't have the same duplication of entries:

$ curl --silent https://status.linode.com/api/v2/components.json | jq '.components[] | .name'
"US-East (Newark) Backups"
"US-East (Newark) NodeBalancers"
"Linode.com"
"US-East (Newark) Object Storage"
"US-East (Newark)"
"US-East (Newark) Linode Kubernetes Engine"
"US-East (Newark) Block Storage"
"US-Central (Dallas)"
"US-Central (Dallas) Linode Kubernetes Engine"
"US-Central (Dallas) Block Storage"
"US-Central (Dallas) Backups"
"EU-Central (Frankfurt) Object Storage"
"Linode Manager and API"
"US-Central (Dallas) NodeBalancers"
"US-West (Fremont) Block Storage"
"US-West (Fremont)"
"US-West (Fremont) NodeBalancers"
"US-West (Fremont) Linode Kubernetes Engine"
"Hosted DNS Service"
"AP-South (Singapore) Object Storage"
"US-West (Fremont) Backups"
"CA-Central (Toronto) Linode Kubernetes Engine"
"US-Southeast (Atlanta)"
"US-Southeast (Atlanta) Backups"
"US-Southeast (Atlanta) Object Storage"
"Longview"
"US-Southeast (Atlanta) NodeBalancers"
"CA-Central (Toronto) Block Storage"
"CA-Central (Toronto)"
"Regions"
"EU-West (London) Block Storage"
"CA-Central (Toronto) Backups"
"EU-West (London) Linode Kubernetes Engine"
"CA-Central (Toronto) NodeBalancers"
"EU-West (London)"
"EU-West (London) NodeBalancers"
"Backups"
"EU-Central (Frankfurt) Linode Kubernetes Engine"
"EU-West (London) Backups"
"EU-Central (Frankfurt) Block Storage"
"AP-South (Singapore) Linode Kubernetes Engine"
"EU-Central (Frankfurt)  NodeBalancers"
"AP-South (Singapore) Block Storage"
"EU-Central (Frankfurt) Backups"
"Block Storage"
"EU-Central (Frankfurt)"
"AP-Northeast-2 (Tokyo 2) Linode Kubernetes Engine"
"AP-South (Singapore)"
"AP-South (Singapore) Backups"
"AP-Northeast-2 (Tokyo 2) Block Storage"
"NodeBalancers"
"AP-South (Singapore) NodeBalancers"
"AP-West (Mumbai) Linode Kubernetes Engine"
"Object Storage"
"AP-West (Mumbai) Block Storage"
"AP-Northeast-2 (Tokyo 2) NodeBalancers"
"AP-Southeast (Sydney) Linode Kubernetes Engine"
"AP-Northeast-2 (Tokyo 2) Backups"
"AP-Southeast (Sydney) Block Storage"
"AP-Northeast-2 (Tokyo 2)"
"Linode Kubernetes Engine"
"AP-West (Mumbai) NodeBalancers"
"AP-West (Mumbai) Backups"
"US-Southeast (Atlanta) Block Storage"
"AP-West (Mumbai)"
"AP-Southeast (Sydney) NodeBalancers"
"AP-Southeast (Sydney) Backups"
"AP-Southeast (Sydney)"
atc0005 commented 2 years ago

Ah, I see now.

As indicated, there are groupings of components based on a top-level service, which happens to share similar functionality across services (e.g., Login/SSO):

image

The Linode groupings are setup so that sub-components are named explicitly based on the parent component name (NodeBalancers > US-East (Newark) NodeBalancers) instead of as a bare sub-component name (NodeBalancers > US-East (Newark)):

image

This will make having one plugin handle both pages a little more tricky, but I'm still optimistic that it can be done. I'll know more once I dig into this further.

atc0005 commented 2 years ago

Proposed type generated by https://github.com/marhaupe/json2struct:

$ ./json2struct -f components.json

type JSONToStruct struct {
        Components []struct {
                Components            []string    `json:"components"`
                Created_at            string      `json:"created_at"`
                Description           interface{} `json:"description"`
                Group                 bool        `json:"group"`
                Group_id              string      `json:"group_id"`
                Id                    string      `json:"id"`
                Name                  string      `json:"name"`
                Only_show_if_degraded bool        `json:"only_show_if_degraded"`
                Page_id               string      `json:"page_id"`
                Position              int         `json:"position"`
                Showcase              bool        `json:"showcase"`
                Start_date            interface{} `json:"start_date"`
                Status                string      `json:"status"`
                Updated_at            string      `json:"updated_at"`
        } `json:"components"`
        Page struct {
                Id         string `json:"id"`
                Name       string `json:"name"`
                Time_zone  string `json:"time_zone"`
                Updated_at string `json:"updated_at"`
                Url        string `json:"url"`
        } `json:"page"`
}

I've not compared it to the results from parsing the component JSON feeds from Linode, Qualys, etc.

atc0005 commented 2 years ago

I vaguely recall that the stdlib json package will handle parsing JSON to a map. If that can be easily done, it may be worth going that route here.

Some scratch notes for later review:

parse json feed fetch group_id values for components look for name based on given exact value match (top-level) fetch all other components with same group_id value check status of all of these fetched components emit plugin determination

probably best to create a map of values instead of trying to create a specific type / "schema" for each probably worth creating a component type however

...

parse json feed fetch components without a group_id value and with a components array look for name based on given exact value match (top-level) fetch all child components from the components sub-array check status of all of these fetched components emit plugin determination

atc0005 commented 2 years ago

Wrapping up work on the initial version of the plugin. It's got a ways to go (particularly output), but I think it's ready for some real world testing.