- Puppet 5 Essentials(Third Edition)
- Martin Alfke Felix Frank
- 440字
- 2021-07-02 18:22:23
Avoiding circular dependencies
Before you learn about another way in which resources can interrelate, there is an issue that you should be aware of: dependencies must not form circles. Let's visualize this in an example:
file { '/etc/haproxy':
ensure => 'directory',
owner => 'root',
group => 'root',
mode => '0644',
}
file { '/etc/haproxy/haproxy.cfg':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/haproxy/etc/haproxy/haproxy.cfg',
}
service { 'haproxy':
ensure => 'running',
require => File['/etc/haproxy/haproxy.cfg'],
before => File['/etc/haproxy'],
}
The dependency circle in this manifest is somewhat hidden (as will likely be the case for many such circles that you will encounter during regular use of Puppet).
It is formed by the following relations:
- The File['/etc/haproxy/haproxy.cfg'] auto-requires the parent directory, File['/etc/haproxy']. This is an implicit, built-in dependency
- The parent directory, File['/etc/haproxy'], requires Service['haproxy'] due to its before metaparameter
- The Service['haproxy'] service requires the File['/etc/haproxy/haproxy.cfg'] config
Implicit dependencies exist for the following resource combinations, among others:
- If a directory and a file inside the directory are declared, Puppet will first create the directory and then the file
- If a user and his/her primary group is declared, Puppet will first create the group and then the user
- If a file and the owner (user) are declared, Puppet will first create the user and then the file
Granted, the preceding example is contrived-it will not make sense to manage the service before the configuration directory. Nevertheless, even a manifest design that is apparently sound can result in circular dependencies. This is how Puppet will react to such a design:
root@puppetmaster:~# puppet apply circle.pp
Notice: Compiled catalog for puppetmaster.example.net in environment production in 0.62 seconds
Error: Failed to apply catalog: Found 1 dependency cycle:
(File[/etc/haproxy/haproxy.cfg] =>
Service[haproxy] =>
File[/etc/haproxy] => File[/etc/haproxy/haproxy.cfg])
Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz
The output helps you locate the offending relation(s). For very wide dependency circles with lots of involved resources, the textual rendering is difficult to analyze. Therefore, Puppet also gives you the opportunity to get a graphical representation of the dependency graph through the --graph option.
If you do this, Puppet will include the full path to the newly created .dot file in its output. Its content looks similar to Puppet's output:
digraph Resource_Cycles {
label = "Resource Cycles"
"File[/etc/haproxy/haproxy.cfg]" ->"Service[haproxy]" ->"File[/etc/haproxy]" ->"File[/etc/haproxy/haproxy.cfg]"
}
This is not helpful by itself, but it can be fed directly into tools such as dotty to produce an actual diagram.
To summarize, resource dependencies are helpful in keeping Puppet from acting upon resources in unexpected or uncontrolled situations. They are also useful in restricting the order of resource evaluation.