为什么“require”模块中的变量并不总是可用?

为什么“require”模块中的变量并不总是可用?

我有三个位于单独文件中的模块清单(精简到只剩基本内容):

class users {
  $user = 'foo'

  user { $user:
    ensure => present;
  }
}

class dvcs_cli {
  require users

  file { "/home/${::users::user}/.gitconfig":
    ensure => present,
    source => 'puppet:///modules/dvcs_cli/.gitconfig';
  }
}

class shell {
  require users

  file { "/home/${::users::user}/.bash_aliases":
    ensure => present,
    source => 'puppet:///modules/shell/bash_aliases.sh';
  }
}

.gitconfig/home/foo是按预期创建的,但是.bash_aliases创建于/home

$ sudo /usr/bin/puppet apply --modulepath modules --detailed-exitcodes --hiera_config=hieradata/hiera.yaml manifests/host.pp || [ $? -eq 2 ]
[…]
Notice: /Stage[main]/Shell/File[/home//.bash_aliases]/ensure: defined content as '{md5}[…]'
Notice: /Stage[main]/Shell/File[/home/foo/.gitconfig]/ensure: defined content as '{md5}[…]'

就好像${::users::user}在一个模块中计算为空字符串,但在另一个模块中则不然。这怎么可能?


运行--debug揭示了一个可能的问题:User[foo]是自动必需的dvcs_cli,但不是shell

$ grep 'Adding autorequire relationship with User' puppet.log | grep -i -e dvcs_cli -e shell
Debug: /Stage[main]/Dvcs_cli/File[/home/pair/.gitconfig]: Adding autorequire relationship with User[pair]

这与手动的,其中说:

如果 Puppet 正在管理拥有文件的用户或组,则文件资源将自动需要它们。

这可能与“Autorequire 关系是不透明的”,由于两个文件位于同一目录中而导致?既然两个模块都明确表示,那么 autorequires 不应该是无关紧要的吗require users


跑步

$ puppet --version
4.2.1

$ cat /etc/redhat-release 
Fedora release 24 (Twenty Four)

答案1

我在一个奇怪的情况下遇到了这个,对我来说,这是 Puppet 默默地打破了一个循环,但不是以可预测的方式(也不是在--debug输出中)。我以前见过一次这种行为,但在其他一些变化之后它就“消失了”,所以我从来没有真正理解过。

设想:

class a {
  include b

  $foo = 'quick'
  $bar = $b::baz
}

class b {
  include a

  $baz = 'brown'

  if ($hostname == $baz) {
    $qux = $a::foo
  }
}

$bar是在改变了包含和有条件的undef类之后的情况- 但两者都没有受到影响。这似乎是不正确的行为。cabab

解决方法是:

class b {
  $baz = 'brown'

  if ($hostname == $baz) {
    include a
    $qux = $a::foo
  }

}

然后$bar又被定义了。有一种方法可以用点文件可视化循环,但我还没有深入研究它。

Puppet 5.5.22(Debian 稳定版)

相关内容