alignak_backend_client/backend_client.py
def create_update_resource(self, resource_name, name, update=False):
        # pylint: disable=too-many-return-statements, too-many-locals
        # pylint: disable=too-many-nested-blocks
        """Create or update a specific resource

        :param resource_name: backend resource endpoint (eg. host, user, ...)
        :param name: name of the resource to create/update
        :param update: True to update an existing resource, else will try to create
        :return:
        """
        if self.data is None:
            self.data = {}

        # If some data are provided, try to get them
        json_data = None
        if self.data:
            try:
                # Data may be provided on the command line or from a file
                if self.data == 'stdin':
                    input_file = sys.stdin
                else:
                    path = os.path.join(self.folder or os.getcwd(), self.data)
                    input_file = open(path)

                json_data = json.load(input_file)
                logger.info("Got provided data: %s", json_data)
                if input_file is not sys.stdin:
                    input_file.close()
            except IOError:
                logger.error("Error reading data file: %s", path)
                return False
            except ValueError:
                logger.error("Error malformed data file: %s", path)
                return False

        if name is None and json_data is None:
            logger.error("-> can not add/update a %s without a name and/or data!", resource_name)
            return False

        # Manage provided templates
        used_templates = []
        if self.templates is not None:
            logger.info("Searching the %s template(s): %s",
                        resource_name, self.templates)
            for template in self.templates:
                response = self.backend.get(
                    resource_name, params={'where': json.dumps({'name': template,
                                                                '_is_template': True})})
                if response['_items']:
                    used_templates.append(response['_items'][0]['_id'])

                    logger.info("-> found %s template '%s': %s",
                                resource_name, template, response['_items'][0]['_id'])
                else:
                    logger.error("-> %s required template not found '%s'", resource_name, template)
                    return False

        try:
            if json_data is None:
                json_data = {'name': name}

            if not isinstance(json_data, list):
                json_data = [json_data]

            logger.info("Got %d %ss", len(json_data), resource_name)
            count = 0
            for json_item in json_data:
                logger.info("-> json item: %s", json_item)
                if resource_name not in ['history', 'userrestrictrole', 'logcheckresult'] \
                        and name is None and ('name' not in json_item or not json_item['name']):
                    logger.warning("-> unnamed '%s'!", resource_name)
                    continue

                # Manage resource name
                item_name = name
                if 'name' in json_item:
                    item_name = json_item['name']

                # Got the item name
                params = {'name': item_name}

                if resource_name == 'service' and 'host' in json_item:
                    # Get host from name
                    host_search = {'name': json_item['host']}
                    if '_is_template' in json_item:
                        host_search.update({'_is_template': json_item['_is_template']})
                    logger.info("Host search: %s", host_search)
                    resp_host = self.backend.get(
                        'host', params={'where': json.dumps(host_search)})
                    if resp_host['_items']:
                        host = resp_host['_items'][0]
                        logger.info("Got host '%s' for the service '%s'", host['name'], item_name)
                    else:
                        logger.warning("Host not found: '%s' for the service: %s!",
                                       json_item['host'], item_name)
                        continue

                    params = {'name': item_name, 'host': host['_id']}

                if resource_name == 'service' and '/' in item_name:
                    splitted_name = item_name.split('/')

                    # Get host from name
                    host_search = {'name': splitted_name[0]}
                    if '_is_template' in json_item:
                        host_search.update({'_is_template': json_item['_is_template']})
                    resp_host = self.backend.get(
                        'host', params={'where': json.dumps(host_search)})
                    if resp_host['_items']:
                        host = resp_host['_items'][0]
                        logger.info("Got host '%s' for the service '%s'",
                                    splitted_name[0], splitted_name[1])
                    else:
                        logger.warning("Host not found: '%s' for the service: %s!",
                                       splitted_name[0], item_name)
                        continue

                    item_name = splitted_name[1]
                    params = {'name': item_name, 'host': host['_id']}

                if '_is_template' in json_item:
                    params.update({'_is_template': json_item['_is_template']})

                params = {'where': json.dumps(params)}

                if name:
                    logger.info("Trying to get %s: '%s', params: %s",
                                resource_name, item_name, params)
                    response = self.backend.get(resource_name, params=params)
                    if response['_items']:
                        found_item = response['_items'][0]
                        found_id = found_item['_id']
                        found_etag = found_item['_etag']
                        logger.info("-> found %s '%s': %s", resource_name, item_name, found_id)

                        if not update:
                            logger.warning("-> '%s' %s cannot be created because it already "
                                           "exists!", resource_name, item_name)
                            continue
                    else:
                        if update:
                            logger.warning("-> '%s' %s cannot be updated because it does not "
                                           "exist!", resource_name, item_name)
                            continue

                # Item data updated with provided information if some

                # Data to update
                item_data = {}
                if self.include_read_data:
                    # Include read data if required
                    item_data = found_item

                # Json provided data update existing data
                item_data.update(json_item)
                # Name is also updated (eg. for a service...)
                item_data['name'] = item_name
                # Template information if templating is required
                if used_templates:
                    item_data.update({'_templates': used_templates,
                                      '_templates_with_services': True})

                for field in item_data.copy():
                    logger.debug("Field: %s = %s", field, item_data[field])
                    # Filter Eve extra fields
                    if field in ['_created', '_updated', '_etag', '_links', '_status']:
                        item_data.pop(field)
                        continue
                    # Filter specific backend inner computed fields
                    # pylint: disable=fixme
                    # todo: list to be completed!
                    if field in ['_overall_state_id']:
                        item_data.pop(field)
                        continue

                    # Manage potential object link fields
                    if field not in ['realm', '_realm', '_templates',
                                     'command', 'host', 'service',
                                     'escalation_period', 'maintenance_period',
                                     'snapshot_period', 'check_period', 'dependency_period',
                                     'notification_period', 'host_notification_period',
                                     'escalation_period', 'service_notification_period',
                                     'host_notification_commands', 'service_notification_commands',
                                     'service_dependencies', 'users', 'usergroups',
                                     'check_command', 'event_handler', 'grafana', 'statsd']:
                        continue

                    field_values = item_data[field]
                    if not isinstance(item_data[field], list):
                        field_values = [item_data[field]]

                    found = None
                    for value in field_values:
                        logger.debug(" - %s, single value: %s", field, value)
                        try:
                            int(value, 16)
                            logger.debug(" - %s, uuid value: %s", field, value)

                            if not isinstance(item_data[field], list):
                                found = value
                            else:
                                if found is None:
                                    found = []
                                found.append(value)
                        except TypeError:
                            pass
                        except ValueError:
                            # Not an integer, consider an item name
                            field_params = {'where': json.dumps({'name': value})}
                            logger.debug(" - %s, params: %s", field, field_params)
                            if field in ['escalation_period', 'maintenance_period',
                                         'snapshot_period', 'check_period',
                                         'dependency_period', 'notification_period',
                                         'host_notification_period',
                                         'service_notification_period']:
                                response2 = self.backend.get('timeperiod', params=field_params)
                            elif field in ['_realm']:
                                response2 = self.backend.get('realm', params=field_params)
                            elif field in ['service_dependencies']:
                                response2 = self.backend.get('service', params=field_params)
                            elif field in ['users']:
                                response2 = self.backend.get('user', params=field_params)
                            elif field in ['usergroups']:
                                response2 = self.backend.get('usergroup', params=field_params)
                            elif field in ['check_command', 'event_handler',
                                           'service_notification_commands',
                                           'host_notification_commands']:
                                response2 = self.backend.get('command', params=field_params)
                            elif field in ['_templates']:
                                field_params = {'where': json.dumps({'name': value,
                                                                     '_is_template': True})}
                                response2 = self.backend.get(resource_name, params=field_params)
                            else:
                                response2 = self.backend.get(field, params=field_params)

                            if response2['_items']:
                                response2 = response2['_items'][0]
                                logger.info("Replaced %s = %s with found item _id",
                                            field, value)
                                if not isinstance(item_data[field], list):
                                    found = response2['_id']
                                else:
                                    if found is None:
                                        found = []
                                    found.append(response2['_id'])

                    if found is None:
                        logger.warning("Not found %s = %s, removing field!", field, field_values)
                        item_data.pop(field)
                    else:
                        item_data[field] = found

                if resource_name not in ['realm'] and '_realm' not in item_data:
                    logger.info("add default realm to the data")
                    item_data.update({'_realm': self.default_realm})

                if resource_name in ['realm'] and '_realm' not in item_data:
                    logger.info("add parent realm to the data")
                    item_data.update({'_parent': self.default_realm})

                if '_id' in item_data:
                    item_data.pop('_id')

                if not update:
                    # Trying to create a new element
                    if not item_data['name']:
                        item_data.pop('name')
                    logger.info("-> trying to create the %s: %s.", resource_name, item_name)
                    logger.debug("-> with: %s.", item_data)
                    if not self.dry_run:
                        try:
                            response = self.backend.post(resource_name, item_data, headers=None)
                        except BackendException as exp:
                            self.item = item_name
                            logger.error("Exception: %s", exp)
                            # logger.error("Response: %s", exp.response)
                            continue
                    else:
                        response = {'_status': 'OK', '_id': '_fake', '_etag': '_fake'}
                else:
                    if not name:
                        logger.warning("-> can not update '%s' with no name!", resource_name)
                        continue

                    # Trying to update an element
                    logger.info("-> trying to update the %s: %s.", resource_name, item_name)
                    logger.debug("-> with: %s.", item_data)
                    if not self.dry_run:
                        try:
                            headers = {'Content-Type': 'application/json', 'If-Match': found_etag}
                            response = self.backend.patch(resource_name + '/' + found_id,
                                                          item_data, headers=headers,
                                                          inception=True)
                        except BackendException as exp:
                            self.item = item_name
                            logger.exception("Exception: %s", exp)
                            # logger.error("Response: %s", exp.response)
                            continue
                    else:
                        response = {'_status': 'OK', '_id': '_fake', '_etag': '_fake'}

                if response['_status'] == 'ERR':
                    logger.warning("Response: %s", response)
                    return False

                if not update:
                    # Created a new element
                    if not self.dry_run:
                        logger.info("-> created: '%s': %s", resource_name, response['_id'])
                    else:
                        logger.info("Dry-run mode: should have created an %s '%s'",
                                    resource_name, name)
                else:
                    # Updated an element
                    if not self.dry_run:
                        logger.info("-> updated: '%s': %s", resource_name, response['_id'])
                    else:
                        logger.info("Dry-run mode: should have updated an %s '%s'",
                                    resource_name, name)
                count = count + 1

        except BackendException as exp:  # pragma: no cover, should never happen
            logger.exception("Exception: %s", exp)
            logger.error("Response: %s", exp.response)
            print("Creation/update error for  '%s' : %s" % (resource_name, name))
            print("~~~~~~~~~~~~~~~~~~~~~~~~~~")
            print("Exiting with error code: 5")
            return False

        if count == len(json_data):
            return True
        return False
def create_update_resource(self, resource_name, name, update=False):
        # pylint: disable=too-many-return-statements, too-many-locals
        # pylint: disable=too-many-nested-blocks
        """Create or update a specific resource

        :param resource_name: backend resource endpoint (eg. host, user, ...)
        :param name: name of the resource to create/update
        :param update: True to update an existing resource, else will try to create
        :return:
        """
        if self.data is None:
            self.data = {}

        # If some data are provided, try to get them
        json_data = None
        if self.data:
            try:
                # Data may be provided on the command line or from a file
                if self.data == 'stdin':
                    input_file = sys.stdin
                else:
                    path = os.path.join(self.folder or os.getcwd(), self.data)
                    input_file = open(path)

                json_data = json.load(input_file)
                logger.info("Got provided data: %s", json_data)
                if input_file is not sys.stdin:
                    input_file.close()
            except IOError:
                logger.error("Error reading data file: %s", path)
                return False
            except ValueError:
                logger.error("Error malformed data file: %s", path)
                return False

        if name is None and json_data is None:
            logger.error("-> can not add/update a %s without a name and/or data!", resource_name)
            return False

        # Manage provided templates
        used_templates = []
        if self.templates is not None:
            logger.info("Searching the %s template(s): %s",
                        resource_name, self.templates)
            for template in self.templates:
                response = self.backend.get(
                    resource_name, params={'where': json.dumps({'name': template,
                                                                '_is_template': True})})
                if response['_items']:
                    used_templates.append(response['_items'][0]['_id'])

                    logger.info("-> found %s template '%s': %s",
                                resource_name, template, response['_items'][0]['_id'])
                else:
                    logger.error("-> %s required template not found '%s'", resource_name, template)
                    return False

        try:
            if json_data is None:
                json_data = {'name': name}

            if not isinstance(json_data, list):
                json_data = [json_data]

            logger.info("Got %d %ss", len(json_data), resource_name)
            count = 0
            for json_item in json_data:
                logger.info("-> json item: %s", json_item)
                if resource_name not in ['history', 'userrestrictrole', 'logcheckresult'] \
                        and name is None and ('name' not in json_item or not json_item['name']):
                    logger.warning("-> unnamed '%s'!", resource_name)
                    continue

                # Manage resource name
                item_name = name
                if 'name' in json_item:
                    item_name = json_item['name']

                # Got the item name
                params = {'name': item_name}

                if resource_name == 'service' and 'host' in json_item:
                    # Get host from name
                    host_search = {'name': json_item['host']}
                    if '_is_template' in json_item:
                        host_search.update({'_is_template': json_item['_is_template']})
                    logger.info("Host search: %s", host_search)
                    resp_host = self.backend.get(
                        'host', params={'where': json.dumps(host_search)})
                    if resp_host['_items']:
                        host = resp_host['_items'][0]
                        logger.info("Got host '%s' for the service '%s'", host['name'], item_name)
                    else:
                        logger.warning("Host not found: '%s' for the service: %s!",
                                       json_item['host'], item_name)
                        continue

                    params = {'name': item_name, 'host': host['_id']}

                if resource_name == 'service' and '/' in item_name:
                    splitted_name = item_name.split('/')

                    # Get host from name
                    host_search = {'name': splitted_name[0]}
                    if '_is_template' in json_item:
                        host_search.update({'_is_template': json_item['_is_template']})
                    resp_host = self.backend.get(
                        'host', params={'where': json.dumps(host_search)})
                    if resp_host['_items']:
                        host = resp_host['_items'][0]
                        logger.info("Got host '%s' for the service '%s'",
                                    splitted_name[0], splitted_name[1])
                    else:
                        logger.warning("Host not found: '%s' for the service: %s!",
                                       splitted_name[0], item_name)
                        continue

                    item_name = splitted_name[1]
                    params = {'name': item_name, 'host': host['_id']}

                if '_is_template' in json_item:
                    params.update({'_is_template': json_item['_is_template']})

                params = {'where': json.dumps(params)}

                if name:
                    logger.info("Trying to get %s: '%s', params: %s",
                                resource_name, item_name, params)
                    response = self.backend.get(resource_name, params=params)
                    if response['_items']:
                        found_item = response['_items'][0]
                        found_id = found_item['_id']
                        found_etag = found_item['_etag']
                        logger.info("-> found %s '%s': %s", resource_name, item_name, found_id)

                        if not update:
                            logger.warning("-> '%s' %s cannot be created because it already "
                                           "exists!", resource_name, item_name)
                            continue
                    else:
                        if update:
                            logger.warning("-> '%s' %s cannot be updated because it does not "
                                           "exist!", resource_name, item_name)
                            continue

                # Item data updated with provided information if some

                # Data to update
                item_data = {}
                if self.include_read_data:
                    # Include read data if required
                    item_data = found_item

                # Json provided data update existing data
                item_data.update(json_item)
                # Name is also updated (eg. for a service...)
                item_data['name'] = item_name
                # Template information if templating is required
                if used_templates:
                    item_data.update({'_templates': used_templates,
                                      '_templates_with_services': True})

                for field in item_data.copy():
                    logger.debug("Field: %s = %s", field, item_data[field])
                    # Filter Eve extra fields
                    if field in ['_created', '_updated', '_etag', '_links', '_status']:
                        item_data.pop(field)
                        continue
                    # Filter specific backend inner computed fields
                    # pylint: disable=fixme
                    # todo: list to be completed!
                    if field in ['_overall_state_id']:
                        item_data.pop(field)
                        continue

                    # Manage potential object link fields
                    if field not in ['realm', '_realm', '_templates',
                                     'command', 'host', 'service',
                                     'escalation_period', 'maintenance_period',
                                     'snapshot_period', 'check_period', 'dependency_period',
                                     'notification_period', 'host_notification_period',
                                     'escalation_period', 'service_notification_period',
                                     'host_notification_commands', 'service_notification_commands',
                                     'service_dependencies', 'users', 'usergroups',
                                     'check_command', 'event_handler', 'grafana', 'statsd']:
                        continue

                    field_values = item_data[field]
                    if not isinstance(item_data[field], list):
                        field_values = [item_data[field]]

                    found = None
                    for value in field_values:
                        logger.debug(" - %s, single value: %s", field, value)
                        try:
                            int(value, 16)
                            logger.debug(" - %s, uuid value: %s", field, value)

                            if not isinstance(item_data[field], list):
                                found = value
                            else:
                                if found is None:
                                    found = []
                                found.append(value)
                        except TypeError:
                            pass
                        except ValueError:
                            # Not an integer, consider an item name
                            field_params = {'where': json.dumps({'name': value})}
                            logger.debug(" - %s, params: %s", field, field_params)
                            if field in ['escalation_period', 'maintenance_period',
                                         'snapshot_period', 'check_period',
                                         'dependency_period', 'notification_period',
                                         'host_notification_period',
                                         'service_notification_period']:
                                response2 = self.backend.get('timeperiod', params=field_params)
                            elif field in ['_realm']:
                                response2 = self.backend.get('realm', params=field_params)
                            elif field in ['service_dependencies']:
                                response2 = self.backend.get('service', params=field_params)
                            elif field in ['users']:
                                response2 = self.backend.get('user', params=field_params)
                            elif field in ['usergroups']:
                                response2 = self.backend.get('usergroup', params=field_params)
                            elif field in ['check_command', 'event_handler',
                                           'service_notification_commands',
                                           'host_notification_commands']:
                                response2 = self.backend.get('command', params=field_params)
                            elif field in ['_templates']:
                                field_params = {'where': json.dumps({'name': value,
                                                                     '_is_template': True})}
                                response2 = self.backend.get(resource_name, params=field_params)
                            else:
                                response2 = self.backend.get(field, params=field_params)

                            if response2['_items']:
                                response2 = response2['_items'][0]
                                logger.info("Replaced %s = %s with found item _id",
                                            field, value)
                                if not isinstance(item_data[field], list):
                                    found = response2['_id']
                                else:
                                    if found is None:
                                        found = []
                                    found.append(response2['_id'])

                    if found is None:
                        logger.warning("Not found %s = %s, removing field!", field, field_values)
                        item_data.pop(field)
                    else:
                        item_data[field] = found

                if resource_name not in ['realm'] and '_realm' not in item_data:
                    logger.info("add default realm to the data")
                    item_data.update({'_realm': self.default_realm})

                if resource_name in ['realm'] and '_realm' not in item_data:
                    logger.info("add parent realm to the data")
                    item_data.update({'_parent': self.default_realm})

                if '_id' in item_data:
                    item_data.pop('_id')

                if not update:
                    # Trying to create a new element
                    if not item_data['name']:
                        item_data.pop('name')
                    logger.info("-> trying to create the %s: %s.", resource_name, item_name)
                    logger.debug("-> with: %s.", item_data)
                    if not self.dry_run:
                        try:
                            response = self.backend.post(resource_name, item_data, headers=None)
                        except BackendException as exp:
                            self.item = item_name
                            logger.error("Exception: %s", exp)
                            # logger.error("Response: %s", exp.response)
                            continue
                    else:
                        response = {'_status': 'OK', '_id': '_fake', '_etag': '_fake'}
                else:
                    if not name:
                        logger.warning("-> can not update '%s' with no name!", resource_name)
                        continue

                    # Trying to update an element
                    logger.info("-> trying to update the %s: %s.", resource_name, item_name)
                    logger.debug("-> with: %s.", item_data)
                    if not self.dry_run:
                        try:
                            headers = {'Content-Type': 'application/json', 'If-Match': found_etag}
                            response = self.backend.patch(resource_name + '/' + found_id,
                                                          item_data, headers=headers,
                                                          inception=True)
                        except BackendException as exp:
                            self.item = item_name
                            logger.exception("Exception: %s", exp)
                            # logger.error("Response: %s", exp.response)
                            continue
                    else:
                        response = {'_status': 'OK', '_id': '_fake', '_etag': '_fake'}

                if response['_status'] == 'ERR':
                    logger.warning("Response: %s", response)
                    return False

                if not update:
                    # Created a new element
                    if not self.dry_run:
                        logger.info("-> created: '%s': %s", resource_name, response['_id'])
                    else:
                        logger.info("Dry-run mode: should have created an %s '%s'",
                                    resource_name, name)
                else:
                    # Updated an element
                    if not self.dry_run:
                        logger.info("-> updated: '%s': %s", resource_name, response['_id'])
                    else:
                        logger.info("Dry-run mode: should have updated an %s '%s'",
                                    resource_name, name)
                count = count + 1

        except BackendException as exp:  # pragma: no cover, should never happen
            logger.exception("Exception: %s", exp)
            logger.error("Response: %s", exp.response)
            print("Creation/update error for  '%s' : %s" % (resource_name, name))
            print("~~~~~~~~~~~~~~~~~~~~~~~~~~")
            print("Exiting with error code: 5")
            return False

        if count == len(json_data):
            return True
        return False
def create_update_resource ( self , resource_name , name , update = False ) : # pylint: disable=too-many-return-statements, too-many-locals # pylint: disable=too-many-nested-blocks if self . data is None : self . data = { } # If some data are provided, try to get them json_data = None if self . data : try : # Data may be provided on the command line or from a file if self . data == 'stdin' : input_file = sys . stdin else : path = os . path . join ( self . folder or os . getcwd ( ) , self . data ) input_file = open ( path ) json_data = json . load ( input_file ) logger . info ( "Got provided data: %s" , json_data ) if input_file is not sys . stdin : input_file . close ( ) except IOError : logger . error ( "Error reading data file: %s" , path ) return False except ValueError : logger . error ( "Error malformed data file: %s" , path ) return False if name is None and json_data is None : logger . error ( "-> can not add/update a %s without a name and/or data!" , resource_name ) return False # Manage provided templates used_templates = [ ] if self . templates is not None : logger . info ( "Searching the %s template(s): %s" , resource_name , self . templates ) for template in self . templates : response = self . backend . get ( resource_name , params = { 'where' : json . dumps ( { 'name' : template , '_is_template' : True } ) } ) if response [ '_items' ] : used_templates . append ( response [ '_items' ] [ 0 ] [ '_id' ] ) logger . info ( "-> found %s template '%s': %s" , resource_name , template , response [ '_items' ] [ 0 ] [ '_id' ] ) else : logger . error ( "-> %s required template not found '%s'" , resource_name , template ) return False try : if json_data is None : json_data = { 'name' : name } if not isinstance ( json_data , list ) : json_data = [ json_data ] logger . info ( "Got %d %ss" , len ( json_data ) , resource_name ) count = 0 for json_item in json_data : logger . info ( "-> json item: %s" , json_item ) if resource_name not in [ 'history' , 'userrestrictrole' , 'logcheckresult' ] and name is None and ( 'name' not in json_item or not json_item [ 'name' ] ) : logger . warning ( "-> unnamed '%s'!" , resource_name ) continue # Manage resource name item_name = name if 'name' in json_item : item_name = json_item [ 'name' ] # Got the item name params = { 'name' : item_name } if resource_name == 'service' and 'host' in json_item : # Get host from name host_search = { 'name' : json_item [ 'host' ] } if '_is_template' in json_item : host_search . update ( { '_is_template' : json_item [ '_is_template' ] } ) logger . info ( "Host search: %s" , host_search ) resp_host = self . backend . get ( 'host' , params = { 'where' : json . dumps ( host_search ) } ) if resp_host [ '_items' ] : host = resp_host [ '_items' ] [ 0 ] logger . info ( "Got host '%s' for the service '%s'" , host [ 'name' ] , item_name ) else : logger . warning ( "Host not found: '%s' for the service: %s!" , json_item [ 'host' ] , item_name ) continue params = { 'name' : item_name , 'host' : host [ '_id' ] } if resource_name == 'service' and '/' in item_name : splitted_name = item_name . split ( '/' ) # Get host from name host_search = { 'name' : splitted_name [ 0 ] } if '_is_template' in json_item : host_search . update ( { '_is_template' : json_item [ '_is_template' ] } ) resp_host = self . backend . get ( 'host' , params = { 'where' : json . dumps ( host_search ) } ) if resp_host [ '_items' ] : host = resp_host [ '_items' ] [ 0 ] logger . info ( "Got host '%s' for the service '%s'" , splitted_name [ 0 ] , splitted_name [ 1 ] ) else : logger . warning ( "Host not found: '%s' for the service: %s!" , splitted_name [ 0 ] , item_name ) continue item_name = splitted_name [ 1 ] params = { 'name' : item_name , 'host' : host [ '_id' ] } if '_is_template' in json_item : params . update ( { '_is_template' : json_item [ '_is_template' ] } ) params = { 'where' : json . dumps ( params ) } if name : logger . info ( "Trying to get %s: '%s', params: %s" , resource_name , item_name , params ) response = self . backend . get ( resource_name , params = params ) if response [ '_items' ] : found_item = response [ '_items' ] [ 0 ] found_id = found_item [ '_id' ] found_etag = found_item [ '_etag' ] logger . info ( "-> found %s '%s': %s" , resource_name , item_name , found_id ) if not update : logger . warning ( "-> '%s' %s cannot be created because it already " "exists!" , resource_name , item_name ) continue else : if update : logger . warning ( "-> '%s' %s cannot be updated because it does not " "exist!" , resource_name , item_name ) continue # Item data updated with provided information if some # Data to update item_data = { } if self . include_read_data : # Include read data if required item_data = found_item # Json provided data update existing data item_data . update ( json_item ) # Name is also updated (eg. for a service...) item_data [ 'name' ] = item_name # Template information if templating is required if used_templates : item_data . update ( { '_templates' : used_templates , '_templates_with_services' : True } ) for field in item_data . copy ( ) : logger . debug ( "Field: %s = %s" , field , item_data [ field ] ) # Filter Eve extra fields if field in [ '_created' , '_updated' , '_etag' , '_links' , '_status' ] : item_data . pop ( field ) continue # Filter specific backend inner computed fields # pylint: disable=fixme # todo: list to be completed! if field in [ '_overall_state_id' ] : item_data . pop ( field ) continue # Manage potential object link fields if field not in [ 'realm' , '_realm' , '_templates' , 'command' , 'host' , 'service' , 'escalation_period' , 'maintenance_period' , 'snapshot_period' , 'check_period' , 'dependency_period' , 'notification_period' , 'host_notification_period' , 'escalation_period' , 'service_notification_period' , 'host_notification_commands' , 'service_notification_commands' , 'service_dependencies' , 'users' , 'usergroups' , 'check_command' , 'event_handler' , 'grafana' , 'statsd' ] : continue field_values = item_data [ field ] if not isinstance ( item_data [ field ] , list ) : field_values = [ item_data [ field ] ] found = None for value in field_values : logger . debug ( " - %s, single value: %s" , field , value ) try : int ( value , 16 ) logger . debug ( " - %s, uuid value: %s" , field , value ) if not isinstance ( item_data [ field ] , list ) : found = value else : if found is None : found = [ ] found . append ( value ) except TypeError : pass except ValueError : # Not an integer, consider an item name field_params = { 'where' : json . dumps ( { 'name' : value } ) } logger . debug ( " - %s, params: %s" , field , field_params ) if field in [ 'escalation_period' , 'maintenance_period' , 'snapshot_period' , 'check_period' , 'dependency_period' , 'notification_period' , 'host_notification_period' , 'service_notification_period' ] : response2 = self . backend . get ( 'timeperiod' , params = field_params ) elif field in [ '_realm' ] : response2 = self . backend . get ( 'realm' , params = field_params ) elif field in [ 'service_dependencies' ] : response2 = self . backend . get ( 'service' , params = field_params ) elif field in [ 'users' ] : response2 = self . backend . get ( 'user' , params = field_params ) elif field in [ 'usergroups' ] : response2 = self . backend . get ( 'usergroup' , params = field_params ) elif field in [ 'check_command' , 'event_handler' , 'service_notification_commands' , 'host_notification_commands' ] : response2 = self . backend . get ( 'command' , params = field_params ) elif field in [ '_templates' ] : field_params = { 'where' : json . dumps ( { 'name' : value , '_is_template' : True } ) } response2 = self . backend . get ( resource_name , params = field_params ) else : response2 = self . backend . get ( field , params = field_params ) if response2 [ '_items' ] : response2 = response2 [ '_items' ] [ 0 ] logger . info ( "Replaced %s = %s with found item _id" , field , value ) if not isinstance ( item_data [ field ] , list ) : found = response2 [ '_id' ] else : if found is None : found = [ ] found . append ( response2 [ '_id' ] ) if found is None : logger . warning ( "Not found %s = %s, removing field!" , field , field_values ) item_data . pop ( field ) else : item_data [ field ] = found if resource_name not in [ 'realm' ] and '_realm' not in item_data : logger . info ( "add default realm to the data" ) item_data . update ( { '_realm' : self . default_realm } ) if resource_name in [ 'realm' ] and '_realm' not in item_data : logger . info ( "add parent realm to the data" ) item_data . update ( { '_parent' : self . default_realm } ) if '_id' in item_data : item_data . pop ( '_id' ) if not update : # Trying to create a new element if not item_data [ 'name' ] : item_data . pop ( 'name' ) logger . info ( "-> trying to create the %s: %s." , resource_name , item_name ) logger . debug ( "-> with: %s." , item_data ) if not self . dry_run : try : response = self . backend . post ( resource_name , item_data , headers = None ) except BackendException as exp : self . item = item_name logger . error ( "Exception: %s" , exp ) # logger.error("Response: %s", exp.response) continue else : response = { '_status' : 'OK' , '_id' : '_fake' , '_etag' : '_fake' } else : if not name : logger . warning ( "-> can not update '%s' with no name!" , resource_name ) continue # Trying to update an element logger . info ( "-> trying to update the %s: %s." , resource_name , item_name ) logger . debug ( "-> with: %s." , item_data ) if not self . dry_run : try : headers = { 'Content-Type' : 'application/json' , 'If-Match' : found_etag } response = self . backend . patch ( resource_name + '/' + found_id , item_data , headers = headers , inception = True ) except BackendException as exp : self . item = item_name logger . exception ( "Exception: %s" , exp ) # logger.error("Response: %s", exp.response) continue else : response = { '_status' : 'OK' , '_id' : '_fake' , '_etag' : '_fake' } if response [ '_status' ] == 'ERR' : logger . warning ( "Response: %s" , response ) return False if not update : # Created a new element if not self . dry_run : logger . info ( "-> created: '%s': %s" , resource_name , response [ '_id' ] ) else : logger . info ( "Dry-run mode: should have created an %s '%s'" , resource_name , name ) else : # Updated an element if not self . dry_run : logger . info ( "-> updated: '%s': %s" , resource_name , response [ '_id' ] ) else : logger . info ( "Dry-run mode: should have updated an %s '%s'" , resource_name , name ) count = count + 1 except BackendException as exp : # pragma: no cover, should never happen logger . exception ( "Exception: %s" , exp ) logger . error ( "Response: %s" , exp . response ) print ( "Creation/update error for  '%s' : %s" % ( resource_name , name ) ) print ( "~~~~~~~~~~~~~~~~~~~~~~~~~~" ) print ( "Exiting with error code: 5" ) return False if count == len ( json_data ) : return True return False
Create or update a specific resource

        :param resource_name: backend resource endpoint (eg. host, user, ...)
        :param name: name of the resource to create/update
        :param update: True to update an existing resource, else will try to create
        :return:
Create or update a specific resource