Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nickanderson/05ea1f146de1915bfb9b36ac63e3615e to your computer and use it in GitHub Desktop.
Save nickanderson/05ea1f146de1915bfb9b36ac63e3615e to your computer and use it in GitHub Desktop.
Filtering data in CFEngine policy

Say we have some JSON array of objects:

[
    { "name":"Masin", "location":"Berlin"},
    { "name":"Nick", "location":"LFK", "comment": "https://www.reddit.com/r/Lawrence/comments/13udnwx/what_does_lfk_stand_for" },
    { "name":"Ole","location":"Oslo"}
]

How can I do something like jq '.[] | select( .name=="Masin" )'? I don’t know the index, I just know the unique value of one property.

I think the most performant way to do this is to leverage jq via mapdata():

bundle agent __main__
{
  vars:
      "my_data" data => '[
    { "name":"Masin", "location":"Berlin"},
    { "name":"Nick", "location":"LFK", "comment": "https://www.reddit.com/r/Lawrence/comments/13udnwx/what_does_lfk_stand_for" },
    { "name":"Ole","location":"Oslo"}
]';

      "masin" data    => mapdata( "json_pipe", `$(def.jq) '.[] | select(.name=="Masin")`, @{my_data} );

  reports:
    "$(with)" with => storejson( masin );
}
R: [
  {
    "location": "Berlin",
    "name": "Masin"
  }
]

However, you could also achieve this naively within policy by leveraging iteration and classic associative arrays.

For example:

bundle agent __main__
{
  vars:
      "my_data" data => '[
    { "name":"Masin", "location":"Berlin"},
    { "name":"Nick", "location":"LFK", "comment": "https://www.reddit.com/r/Lawrence/comments/13udnwx/what_does_lfk_stand_for" },
    { "name":"Ole","location":"Oslo"}
]';

      "i" slist => getindices( my_data );

      "masin[name]" string => "$(my_data[$(i)][name])", if => strcmp( "$(my_data[$(i)][name])", "Masin" );
      "masin[location]" string => "$(my_data[$(i)][location])", if => strcmp( "$(my_data[$(i)][name])", "Masin" );

  reports:
      "$(with)" with => storejson( masin );
}
R: {
  "location": "Berlin",
  "name": "Masin"
}

We could be a bit dynamic:

bundle agent __main__
{
  vars:
      "my_data" data => '[
    { "name":"Masin", "location":"Berlin"},
    { "name":"Nick", "location":"LFK", "comment": "https://www.reddit.com/r/Lawrence/comments/13udnwx/what_does_lfk_stand_for" },
    { "name":"Ole","location":"Oslo"}
]';

      "i" slist => getindices( my_data );

      "$(my_data[$(i)][name])[name]" string => "$(my_data[$(i)][name])", if => strcmp( "$(my_data[$(i)][name])", "Masin" );
      "$(my_data[$(i)][name])[location]" string => "$(my_data[$(i)][location])", if => strcmp( "$(my_data[$(i)][name])", "Masin" );

  reports:
      "$(with)" with => storejson( Masin );
}
R: {
  "location": "Berlin",
  "name": "Masin"
}

Or do some munging ....

bundle agent __main__
{
  vars:
      "my_data" data => '[
    { "name":"Masin", "location":"Berlin"},
    { "name":"Nick", "location":"LFK", "comment": "https://www.reddit.com/r/Lawrence/comments/13udnwx/what_does_lfk_stand_for" },
    { "name":"Ole","location":"Oslo"}
]';

      "i" slist => getindices( my_data );

      "$(with)[name]"
        string => "$(my_data[$(i)][name])",
        if => strcmp( "$(my_data[$(i)][name])", "Masin" ),
        with => string_downcase( canonify( "$(my_data[$(i)][name])" ) );

      "$(with)[location]"
        string => "$(my_data[$(i)][location])",
        if => strcmp( "$(my_data[$(i)][name])", "Masin" ),
        with => string_downcase( canonify( "$(my_data[$(i)][name])" ) );

  reports:
      "$(with)" with => storejson( masin );
}
R: {
  "location": "Berlin",
  "name": "Masin"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment