jq query returning too many records (unwanted permutations)

余生长醉 提交于 2021-01-28 11:31:40

问题


I have a complex JSON file and I am trying to get the below result using JQ.

Expected Result:

{
  "Host": "Test.example.com",
  "Title": "Ensure message of the day is configured properly",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure bond0 is present",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure the SELinux state is disabled",
  "Status": "passed"
}

Below is the JSON file that I get as a result of running an Chef Inspec profile.

JSON FILE:

{
  "platform": {
    "name": "redhat",
    "release": "7.7",
    "target_id": "Test.example.com"
  },
  "profiles": [
    {
      "name": "my-test",
      "version": "0.1.0",
      "sha256": "6fea36d6c12b21cd51274774edb4200d983db45c4cfa8172eebb897b6f3db8fe",
      "title": "InSpec Profile",
      "maintainer": "The Authors",
      "summary": "An InSpec Compliance Profile",
      "license": "Apache-2.0",
      "copyright": "The Authors",
      "copyright_email": "you@example.com",
      "supports": [
        {
          "platform": "os"
        }
      ],
      "attributes": [],
      "groups": [
        {
          "id": "controls/1_motd.rb",
          "controls": [
            "1.1 motd check"
          ],
          "title": "Warning Banners"
        },
        {
          "id": "controls/6_network.rb",
          "controls": [
            "6.1 Bonding"
          ]
        },
        {
          "id": "controls/12_selinux.rb",
          "controls": [
            "Selinux Config"
          ]
        }
      ],
      "controls": [
        {
          "id": "1.1 motd check",
          "title": "Ensure message of the day is configured properly",
          "desc": "Ensure message of the day is configured properly",
          "descriptions": [
            {
              "label": "default",
              "data": "Ensure message of the day is configured properly"
            }
          ],
          "impact": 1,
          "refs": [],
          "tags": {},
          "code": "control '1.1 motd check' do\n  title 'Ensure message of the day is configured properly'\n  desc  \"The contents of the /etc/motd file are displayed to users after login and function as a message of the day for authenticated users.\"\n  desc \"Ensure message of the day is configured properly\"\n  impact 1.0\n  \n  describe file('/etc/motd') do\n    its('content') { should_not be_empty }\n  end\nend\n",
          "source_location": {
            "line": 3,
            "ref": "my-test/controls/1_motd.rb"
          },
          "waiver_data": {},
          "results": [
            {
              "status": "passed",
              "code_desc": "File /etc/motd content should not be empty",
              "run_time": 0.099938054,
              "start_time": "2020-02-07T11:31:47+11:00"
            }
          ]
        },
        {
          "id": "6.1 Bonding",
          "title": "Ensure bond0 is present",
          "desc": "Check bonding is present",
          "descriptions": [
            {
              "label": "default",
              "data": "Check bonding is present"
            }
          ],
          "impact": 1,
          "refs": [],
          "tags": {},
          "code": "control '6.1 Bonding' do\n  title 'Ensure bond0 is present'\n  desc  \"Check bonding is present\"\n  impact 1.0\n  \n  only_if { sys_info.manufacturer != \"VMware, Inc.\" } \n\n  describe bond('bond0') do\n    it { should exist }\n    its('mode') { should eq 'IEEE 802.3ad Dynamic link aggregation' }\n  end\nend\n",
          "source_location": {
            "line": 1,
            "ref": "my-test/controls/6_network.rb"
          },
          "waiver_data": {},
          "results": [
            {
              "status": "skipped",
              "code_desc": "No-op",
              "run_time": 9.02e-06,
              "start_time": "2020-02-07T11:31:47+11:00",
              "resource": "No-op",
              "skip_message": "Skipped control due to only_if condition."
            }
          ]
        },
        {
          "id": "Selinux Config",
          "title": "Ensure the SELinux state is disabled",
          "desc": "Set SELinux to diabled",
          "descriptions": [
            {
              "label": "default",
              "data": "Set SELinux to diabled"
            }
          ],
          "impact": 1,
          "refs": [],
          "tags": {},
          "code": "control 'Selinux Config' do\n  title 'Ensure the SELinux state is disabled'\n  desc  \"Set SELinux to diabled\"\n  impact 1.0\n\n    describe file('/etc/selinux/config') do\n    its(:content) { should match(/^SELINUX=disabled\\s*(?:#.*)?$/) }\n  end\nend\n",
          "source_location": {
            "line": 1,
            "ref": "my-test/controls/12_selinux.rb"
          },
          "waiver_data": {},
          "results": [
            {
              "status": "passed",
              "code_desc": "File /etc/selinux/config content should match /^SELINUX=disabled\\s*(?:#.*)?$/",
              "run_time": 0.120881444,
              "start_time": "2020-02-07T11:31:47+11:00"
            }
          ]
        }
      ],
      "status": "loaded"
    }
  ],
  "statistics": {
    "duration": 0.223533139
  },
  "version": "4.18.24"
}

I used the following JQ code to extract the fields , but the extracted values are repeating.

JQ Code:

jq  '{Host: .platform.target_id,Title: .profiles[].controls[].title,Status: .profiles[].controls[].results[].status}'

The result which I got from above JQ filter

Actual Result:

{
  "Host": "Test.example.com",
  "Title": "Ensure message of the day is configured properly",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure message of the day is configured properly",
  "Status": "skipped"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure message of the day is configured properly",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure bond0 is present",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure bond0 is present",
  "Status": "skipped"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure bond0 is present",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure the SELinux state is disabled",
  "Status": "passed"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure the SELinux state is disabled",
  "Status": "skipped"
}
{
  "Host": "Test.example.com",
  "Title": "Ensure the SELinux state is disabled",
  "Status": "passed"
}

How can I get the expected results. Any help would be appreciated.


回答1:


Because you're iterating over profiles[] more than once, you're combining the results of one such iteration with the results of another. To avoid that, iterate only once, and get both title and results from the same controls list entry.

jq  '
.platform.target_id as $target |
.profiles[].controls[] |
{ Host: $target,
  Title: .title,
  Status: .results[].status }
'

See this running against your input data at https://jqplay.org/s/_6KVDfIn3m



来源:https://stackoverflow.com/questions/60105691/jq-query-returning-too-many-records-unwanted-permutations

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!