"unepexted keyword argument" in Python script

Hello,

We were in need of a way to check for shards growing above 50gb, found this Nagios plugin => https://github.com/DennyZhang/elasticsearch-cli-tool/blob/master/monitoring/check_elasticsearch_shard.py

But it didn't use the Elasticsearch Python client and it had no options to authenticate. So I made some changes:

import argparse
import logging
import re
import requests
import socket
import sys
from elasticsearch import Elasticsearch
from ssl import create_default_context

logger = logging.getLogger('check_elasticsearch_shards')
#logging.basicConfig(level=logging.DEBUG)

NAGIOS_OK=0
NAGIOS_WARNING=1
NAGIOS_CRITICAL=2
NAGIOS_UNKNOWN=3

def get_gb_size_from_string(string):
    # 10.5gb ->   10.5
    # 1.2tb  -> 1200
    val = 0
    if string.endswith("gb"):
        val = float(string.replace("gb", ""))
    elif string.endswith("tb"):
        val = float(string.replace("tb", "")) * 1000
    elif string.endswith("mb"):
        val = float(string.replace("mb", "")) * 0.001
    elif string.endswith("kb"):
        val = float(string.replace("kb", "")) * 0.001 * 0.001
    elif string.endswith("b"):
        val = float(string.replace("b", "")) * 0.001 * 0.001 * 0.001
    else:
        print("ERROR: unexpected. size string: %s" % (string))
        sys.exit(NAGIOS_CRITICAL)
    return val

def parse_index_info(es_index_info):
    index_list = []
    for line in es_index_info.split("\n"):
        if line == '' or " index " in line  or " close " in line:
            continue
        else:
            line = " ".join(line.split())
            l = line.split()
            index = l[2]
            pri = l[3]
            pri_store_size = l[7]
            index_list.append([index, pri, pri_store_size])
    return index_list

def confirm_es_shard_count(es_host, es_port, es_index_list, min_shard_count):
    failed_index_list = []
    for l in es_index_list:
        index_name = l[0]
        number_of_shards = int(l[1])
        if number_of_shards < min_shard_count:
            print("CRITICAL: Index(%s) only has %d shards, less than %d." \
                % (index_name, number_of_shards, min_shard_count))
            failed_index_list.append(index_name)
    return failed_index_list

def confirm_es_shard_size(es_host, es_port, es_index_list, max_shard_size):
    failed_index_list = []
    for i in es_index_list:
        index_name = i[0]
        number_of_shards = int(i[1])
        pri_store_size = i[2]
        avg_shard_size_gb = get_gb_size_from_string(pri_store_size)/number_of_shards
        if avg_shard_size_gb > max_shard_size:
            failed_index_list.append(index_name)
    return failed_index_list

def parse_args():
    parser = argparse.ArgumentParser(description="Check Elasticsearch Shards")
    parser.add_argument('--es_host', required=True, help="ES ip or hostname", type=str)
    parser.add_argument('--es_port', default='9200', required=False, help="ES port", type=str)
    parser.add_argument('--es_user', default='monitoring_user', required=True, help="ES user", type=str)
    parser.add_argument('--es_pass', default='', required=True, help="ES password for user", type=str)
    parser.add_argument('--es_index', required=False, default='', help="ES index name", type=str)
    parser.add_argument('--ca_file', required=False, default='', help="CA certificate file", type=str)
    parser.add_argument('--min_shard_count', default='3', required=False, help='minimal shards', type=str)
    parser.add_argument('--max_shard_size', default='50gb', required=False, help='maximum shards size', type=str)
    return parser.parse_args()

if __name__ == '__main__': 
    l = parse_args()
    es_host = l.es_host
    es_port = l.es_port
    es_user = l.es_user
    es_pass = l.es_pass
    es_index = l.es_index
    ca_file = l.ca_file
    min_shard_count = int(l.min_shard_count)
    max_shard_size = get_gb_size_from_string(l.max_shard_size)
    context = create_default_context(cafile=str(ca_file))
    es = Elasticsearch(
        [str(es_host)],
        http_auth = (str(es_user), str(es_pass)),
        scheme = "https",
        port = int(es_port),
        ssl_context = context
    )
    es_index_cat_raw = es.cat.indices(es_index, h=("h","s","i","p","r","dc","ss","pri.store.size","creation.date.string"), s="i")
    es_index_cat_list = parse_index_info(es_index_cat_raw)

    failed_index_list = confirm_es_shard_size(es_host, es_port, es_index_cat_list, max_shard_size)
    if len(failed_index_list) != 0:
        if len(failed_index_list) == 1:
            print("CRITICAL: Index %s has shards bigger than %s GB!" % (failed_index_list[0], max_shard_size))
        elif len(failed_index_list) > 1:
            index_string = "%s indices" % (len(failed_index_list))       
            print("CRITICAL: %s indices have shards bigger than %s GB!\n%s" % (len(failed_index_list), max_shard_size, ", ".join(failed_index_list)))
        es.transport.close()
        sys.exit(NAGIOS_CRITICAL)
    else:
        print("OK: All shards for indices (pattern \"%s\") are less then %s GB." % (es_index, max_shard_size))
        es.transport.close()
        sys.exit(NAGIOS_OK)

But for some reason I get a pylint error on the es object:

Anyone an idea why I get 'unepexted keyword argument h & v ? The plugin works fine, but this syntax error is working on my nerves.. :slight_smile:

(disclaimer: only started learning Python this weekend)

Grtz

Willem