используя .map(или другую функцию stdlib) для создания хэша, а не массива

Я пытаюсь настроить таргетинг на серверы JMS в облаке, кукольный модуль init.pp должен добавить ключ к хэшу.

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

сервис.yaml

jms_subdeployment_instances:
   'BPMJMSModuleUDDs:BPMJMSSubDM':
      ensure:     'present'
      target:
       - 'BPMJMSServer_auto_1'
       - "BPMJMSServer_auto_%{::ec2_tag_name}"
      targettype:
        - 'JMSServer'
        - 'JMSServer'      

init.pp

  $jms_subdeployments = lookup('jms_subdeployment_instances', $default_params)
  $jms_target_args = $jms_subdeployments.map |$subdep, $value| {
    $jms_short_name = $subdep[0, 3]
    $jms_subdeployment_inst = $array_domain_jmsserver_addresses.map |$index, $server| {
      "${jms_short_name}JMSServer_auto_${server}"

      if defined('$jms_subdeployment_inst') {
        $jmsTargetArg = {
          "${subdep}" => {
            'target' => $jms_subdeployment_inst
          }
        }
      }
    }

  $merge_subdeployment_targets = merge($jms_subdeployments, $jms_target_args)



```Output
New JMS targets are : [{BPMJMSModuleUDDs:BPMJMSSubDM => {target => [BPMJMSServer_auto_server101, BPMJMSServer_auto_server102]}}]

Окружающие [ ] вызывают у меня проблемы. Насколько я понимаю, в puppet .to_h тоже не работает

Спасибо

Обновление от 22.07.2019:

Спасибо за ответ, мне пришлось немного подправить его, потому что puppet выдавал ошибку «Ошибка сервера: ошибка оценки: ошибка при оценке вызова метода, параметр 'values' 'hsh' ожидает хеш-значение, получил Tuple"

  $array_domain_jmsserver_addresses = 
  any2array(hiera('pdb_domain_msserver_addresses'))
  $array_domain_jmsserver_addresses.sort()
  $jms_subdeployments = lookup('jms_subdeployment_instances', $default_params)
  $hash_domain_jmsserver_addresses = Hash($array_domain_jmsserver_addresses)

  if $hash_domain_jmsserver_addresses.length > 0 {
      $jms_target_arg_tuples = $jms_subdeployments.keys.map |$subdep| {
      $jms_short_name = $subdep[0, 3]
      $jms_subdeployment_inst = regsubst(
          $hash_domain_jmsserver_addresses.values, /^/, "${jms_short_name}JMSServer_auto_")

  # the (key, value) tuple to which this element maps
  [ $subdep, { 'target' => $jms_subdeployment_inst } ]
}

$jms_target_args = Hash($jms_target_arg_tuples)
} else {
$jms_target_args = {}
}

notify{"Normal array is : ${jms_subdeployments}": }
notify{"Second array is : ${jms_target_args}": }  

$merge_subdeployment_targets = deep_merge($jms_subdeployments, $jms_target_args)
notify{"Merged array is : ${merge_subdeployment_targets}": }

Обычно это: {BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => присутствует, target => [BPMJMSServer_auto_1, BPMJMSServer_auto_server1], targettype => [JMSServer, JMSServer]},

Во-вторых: {BPMJMSModuleUDDs:BPMJMSSubDM => {target => [BPMJMSServer_auto_server2]}

Объединено: {BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => присутствует, target => [BPMJMSServer_auto_server2], targettype => [JMSServer, JMSServer]}

Желаемый вывод:

{BPMJMSModuleUDDs:BPMJMSSubDM => {ensure => present, target => [BPMJMSServer_auto_1, BPMJMSServer_auto_server1, BPMJMSServer_auto_server2], targettype => [JMSServer, JMSServer, JMSServer]}


person Dave Shaw    schedule 19.07.2019    source источник
comment
В вашем коде несбалансированные скобки. Думаю, я понял, что вы имеете в виду, но если это так, то ваш код также имеет несогласованные отступы.   -  person John Bollinger    schedule 19.07.2019
comment
Если (другая) версия в моем ответе не решает проблему, то как насчет приближения к минимально воспроизводимому примеру заменив все вызовы lookup() литералами. Код, который я представил в своем ответе, является адаптацией вашего исходного кода, но если он не совсем подходит для фактических данных, то у нас недостаточно информации, чтобы привести вас туда, где вы хотите быть.   -  person John Bollinger    schedule 23.07.2019


Ответы (1)


когда я попробовал deep_merge, я обнаружил, что .map выводится как массив.

Да, это задокументированное поведение. map() следует рассматривать как функцию элементов коллекции, а не всей коллекции, и результаты всегда предоставляются в виде массива.

Вероятно, было бы полезно просмотреть альтернативы для преобразование значений в хэши. Особенно привлекателен вот этот:

  • Array, соответствующее Array[Tuple[Any,Any], 1], преобразуется в хеш, где каждый кортеж описывает запись типа ключ/значение.

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

if $array_domain_jmsserver_addresses.length > 0 {
  $jms_target_arg_tuples = $jms_subdeployments.keys.map |$subdep| {
    $jms_short_name = $subdep[0, 3]
    $jms_subdeployment_inst = regsubst(
        $array_domain_jmsserver_addresses.sort, /^/, "${jms_short_name}JMSServer_auto_")

    # the (key, value) tuple to which this element maps
    [ $subdep, { 'target' => $jms_subdeployment_inst } ]
  }

  $jms_target_args = Hash($jms_target_arg_tuples)
} else {
  $jms_target_args = {}
}

$merge_subdeployment_targets = merge($jms_subdeployments, $jms_target_args)

Обратите внимание: поскольку вы не используете значения $jms_subdeployments, я взял на себя смелость несколько упростить ваш код, применив к нему функцию keys(). Я также использовал regsubst() вместо map() для формирования целевых имен из элементов $array_domain_jmsserver_addresses, что я лично считаю более читаемым в этом случае, тем более что вы не использовали индексы.

Я также сделал вывод о том, что, по моему мнению, вы имели в виду для выполнения теста if defined(), и заменил его самым внешним тестом длины массива $array_domain_jmsserver_addresses. Можно было бы также написать его в несколько более функциональной форме, построив хеш независимо от того, есть ли какие-либо цели, а затем filter()ing его после, но это кажется расточительным, потому что кажется, что либо все записи будут иметь (одинаковые) цели, либо никто не будет.

person John Bollinger    schedule 19.07.2019
comment
Спасибо за быстрый и подробный ответ, я обновил исходный вопрос. Интересно, что слияние еще не совсем работает - person Dave Shaw; 22.07.2019
comment
@DaveShaw, я изменил код в этом ответе так, чтобы $array_domain_jmsserver_addresses был массивом, а не хэшем. - person John Bollinger; 23.07.2019