jq - дублирующий объект в списке при объединении произвольного числа массивов json из файлов - PullRequest
1 голос
/ 23 января 2020

Я настраиваю журналы агента cloudwatch, используя солончак (вот почему существует какой-то странный синтаксис). Я пытаюсь объединить произвольное количество файлов, содержащих идентичные схемы, но разные данные, в один файл.

Файл 1

{
  "logs": {
    "logs_collected": {
      "files":{
        "collect_list": [
          {
            "file_name": "/var/log/suricata/eve-ips.json",
            "log_group_name": "{{grains.environment_full}}SuricataIPS",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%f+0000"
          }
        ]
      }
    }
  }
}

Файл 2

{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_name": "/var/log/company/company-json.log",
            "log_group_name": "{{grains.environment_full}}Play",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
          },
          {
            "file_name": "/var/log/company/company-notifications.log",
            "log_group_name": "{{grains.environment_full}}Notifications",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
          }
        ]
      }
    }
  }
}

Файл 3

{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_name": "/var/ossec/logs/alerts/alerts.json",
            "log_group_name": "{{grains.environment_full}}OSSEC",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%d %H:%M:%S"
          }
        ]
      }
    }
  }
}

JQ-запрос (на основании некоторой справки SO)

jq  -s '.[0].logs.logs_collected.files.collect_list += [.[].logs.logs_collected.files.collect_list | add] | unique| .[0]' web.json suricata.json wazuh-agent.json

Выходные данные

{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_name": "/var/log/company/company-json.log",
            "log_group_name": "{{grains.environment_full}}Play",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
          },
          {
            "file_name": "/var/log/company/company-notifications.log",
            "log_group_name": "{{grains.environment_full}}Notifications",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
          },
          {
            "file_name": "/var/log/company/company-notifications.log",
            "log_group_name": "{{grains.environment_full}}Notifications",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%fZ"
          },
          {
            "file_name": "/var/log/suricata/eve-ips.json",
            "log_group_name": "{{grains.environment_full}}SuricataIPS",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%dT%H:%M:%S.%f+0000"
          },
          {
            "file_name": "/var/ossec/logs/alerts/alerts.json",
            "log_group_name": "{{grains['environment_full']}}OSSEC",
            "log_stream_name": "{{grains.id}}",
            "timezone": "UTC",
            "timestamp_format": "%Y-%m-%d %H:%M:%S"
          }
        ]
      }
    }
  }
}

Если вы прошли так далеко, спасибо. Еще одно замечание: если я меняю порядок файлов, первый индекс collect_list всегда дублируется, а если web.json последний (единственный с длиной 2), второй файл журнала не группа.

Ответы [ 2 ]

2 голосов
/ 24 января 2020

У вас есть пара неверных шагов в рамках вашей попытки. Во-первых, чтобы преобразовать массив всех массивов "list"

[.[].logs.logs_collected.files.collect_list] 

в один отдельный массив, вам нужно использовать add, но способ его вызова был неверным. Добавление принимает входные данные в виде массива объектов и создает в качестве выходных данных элементы массива, добавленные вместе. Таким образом, это должно было быть

[.[].logs.logs_collected.files.collect_list] | add

, за которым следует функция unique, которая снова принимает в качестве входных данных массив и создает массив из тех же элементов в отсортированном порядке, с удалением дубликатов.

[.[].logs.logs_collected.files.collect_list] | add | unique

Что касается дублирования первых элементов, то это потому, что вы использовали операцию добавления += вместо присваивания =. Поскольку код в правой части оператора группирует записи из всех объектов, с помощью добавления просто добавляет значение в первый объект, а остальные объекты объединяются вместе.

Также сгруппируйте функции вместе с (..) перед доступом к .[0] из результирующего объекта. Поэтому его сборка будет работать, как и ожидалось, независимо от порядка файлов.

jq -s '.[0].logs.logs_collected.files.collect_list = ([.[].logs.logs_collected.files.collect_list]|add|unique)|.[0]' 

Другой вариант, использующий reduce без необходимости использования slurp mode -s, а скорее работающий на inputs т.е. содержимое всех файлов доступно через стандартный ввод

jq -n 'reduce inputs.logs.logs_collected.files.collect_list as $d (.; .logs.logs_collected.files.collect_list += $d)'
1 голос
/ 23 января 2020

Следующая информация выводит правильную информацию (без дубликатов) независимо от порядка файлов

jq -s 'reduce .[] as $dot ({}; .logs.logs_collected.files.collect_list += $dot.logs.logs_collected.files.collect_list)' web.json wazuh-agent.json suricata.json

Если кто-нибудь знает, почему дубликат встречается в моей другой команде, хотел бы знать это. Хотя я думаю, reduce - лучшее решение.

...