Кукольный выдает ошибку: «Недопустимый операнд связи, не может сформировать связь со значением Undef».

#puppet

#кукольный

Вопрос:

При запуске этого:

 $ramdisk = '/never-save-to-disk'
$keyfile = "${ramdisk}/test.key"
$encryption_key = undef

file {
  [
    $ramdisk,
  ]:
  ensure => directory,
  owner  => 'root',
  group  => 'root',
}
mount { $ramdisk:
  ensure  => 'mounted',
  device  => 'null',
  fstype  => 'ramfs',
  options => 'defaults',
  dump    => 0,
  pass    => 0,
}
~> if ($encryption_key != undef) and ($encryption_key != '') {
   file { $keyfile:
    content => $encryption_key,
    path    => $keyfile,
    owner   => 'database',
    group   => 'database',
    mode    => '0600',
    require => File[$ramdisk],
  }
}
  

Кукольный выдает ошибку «Ошибка: Ошибка оценки: недопустимый операнд связи, не может сформировать связь со значением Undef. Требуется тип каталога. (файл: /tmp/test-fails.pp, строка: 22, столбец: 5) на узле instance.example.com «, где строка 22, столбец 5 — это тильда в ~> .

Ответ №1:

Проблема находится в правой части ~> оператора. В частности, поскольку if сбой создает undef значение. Исправление заключается в том, чтобы убедиться, что есть else предложение, например, для этого случая:

 ~> if ($encryption_key != undef) and ($encryption_key != '') {
   file { $keyfile:
    content => $encryption_key,
    path    => $keyfile,
    owner   => 'database',
    group   => 'database',
    mode    => '0600',
    require => File[$ramdisk],
  }
} else {
  file { $keyfile:
    ensure  => absent,
  }
}
  

Таким образом, Puppet не только не запишет файл, если ramdisk не смонтирован, он удалит любую копию, созданную другими методами.

Комментарии:

1. Предлагаемый код не выражает то, что, по-видимому, намеревается OP. Управление отсутствием файла — это совсем не то же самое, что оставить его неуправляемым.

2. TBH, мне действительно все равно, есть ли файл или нет, когда ram-диск не смонтирован. Но я не хочу, чтобы кукольный устанавливал его, если не ramdisk. Это было что-то, что нужно было сделать. Ваш другой ответ верен, но я не нашел хороших результатов Google для упомянутого сообщения об ошибке и хотел увековечить мои выводы об ошибке.

Ответ №2:

Хотя if инструкции действительно создают значения, эти значения не обязательно являются подходящими правыми операндами для ~> оператора. В частности, undef это будет значение, полученное вашим if оператором, когда его условие оценивается как false , и это не является приемлемым операндом ни для одного из операторов цепочки.

Есть несколько способов, которыми вы могли бы подойти к проблеме, некоторые из которых зависят от того, что вы действительно намереваетесь, но с точки зрения стиля, я думаю, что использовать if оператор в качестве операнда стрелки цепочки при любых обстоятельствах — плохая форма.

Если действительно вы просто хотите управлять файлом $keyfile только при выполнении условия, как вы, кажется, показываете в своем примере, то наиболее естественным решением было бы использовать соответствующий метапараметр отношения вместо стрелки цепочки:

 mount { $ramdisk:
  # ...
}
# no chaining arrow here
if ($encryption_key != undef) and ($encryption_key != '') {
   file { $keyfile:
    # ...
    require   => File[$ramdisk],
    # Like this:
    subscribe => Mount[$ramdisk],
  }
}
  

Добавление метапараметра к ресурсу, который включен только условно, дает вам связь, которая объявляется только тогда, когда этот ресурс объявлен. Кроме того, это просто и понятно.