Учитывая структуру данных вроде

$local_users => {
  "user" => {
    "ssh" => {
      "config_entries" => [
        { "host" => "dummyhost",
          "lines" => [
            "ProxyCommand /usr/bin/corkscrew proxy.example.net 8080 %h %p"
          ]
        }
      ]
    }
  }
}

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

$require_corkscrew = $local_users.reduce(false) |$memo, $user| {
  $memo or dig44($user[1], ['ssh', 'config_entries'], []).reduce |$memo, $entry| {
    $memo or $entry['lines'].reduce |$memo, $line| {
      $memo or $line.match(/ProxyCommand.*corkscrew/)
    }
  }
}

if $require_corkscrew {
  $corkscrew_ensure = 'present'
} else {
  $corkscrew_ensure = 'absent'
}

package {'corkscrew':
  ensure => $corkscrew_ensure,
}
1
dbailey 7 Мар 2019 в 21:27

1 ответ

Лучший ответ

интересно, есть ли в марионетке лучшие шаблоны для извлечения данных, чтобы определить, требуется ли что-то или нет.

Есть несколько возможных улучшений в том, как вы структурируете свои данные:

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

Что касается вычислительных паттернов,

  • рассмотрите возможность использования функции any() при анализе коллекции для вычислить логическое свойство, так как это даст вам добросовестное короткое замыкание.

  • не упускайте из виду функции keys() и values() для анализа хэшей, поскольку они могут, по крайней мере, уменьшить когнитивную нагрузку на ваш код при обработке сложных структур данных.

  • рассмотрите возможность использования функций и вариантов функций, которые работают непосредственно с коллекциями, вместо повторения коллекций и использования скалярных функций для элементов. Например, match() полезен для массивов.

Вот подход, который мне нравится немного больше, чем ваш исходный код. Вместо вложенных редукций он использует вложенные вычисления any() и версию функции match в виде массива. Он основан на том факте, что undef ложен, и использует dig() и then() для работы с необязательными хэш-ключами. В целом, я думаю, что это более понятно и немного легче, но вы можете сделать лишь так много, чтобы получить простой код для анализа сложных данных.

$require_corkscrew = $local_users.values.any |$user| {
  $user.dig('ssh', 'config_entries').then |$entries| {
    $entries.any |$entry| {
      $entry.dig('lines').then |$lines| {
        ! empty($lines.match(/ProxyCommand.*corkscrew/))
      }
    }
  }
}

Можно было бы заменить массив match() другим any(), обернутым вокруг скаляра match(), но хотя он имеет потенциал для короткого замыкания немного раньше в поэлементном В смысле, это должно быть сопоставлено с (вероятным) повышением эффективности за счет уменьшения количества вызовов функций и повторения внутри функции, а не на уровне DSL.

1
John Bollinger 7 Мар 2019 в 21:21