résoudre une dépendance cyclique dans la marionnette lors de la notification d’une ressource dans une autre classe

J’ai écrit une classe Apache qui installe apache2 et configure ssl, puis lance le service apache. J’écris une sous-classe qui va configurer un hôte virtuel puis redémarrer le service apache. Je reçois une erreur de dépendance cyclique car j’essaie de notifier le service apache2 une fois que l’hôte virtuel a été ajouté.

J’ai résolu cette erreur en changeant obliger à inclure mais cela signifie-t-il que les ressources de la classe Apache s’exécuteront avant apache :: no?

Sinon, comment résoudre cette erreur de dépendance?

Est-ce une bonne pratique de notifier les ressources dans un autre cours?

Error: Failed to apply catalog: Found 1 dependency cycle: (Exec[no] => Service[apache2] => Class[Apache] => Class[Apache::No] => Exec[no]) Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz 

apache.pp

 class apache { $listen_port="8181" $no_port="4143" #file { '/etc/apache2/ports.conf' : #ensure => present , #content => template("apache/ports.conf.erb"), #require => Package['apache2'], #notify => Service['apache2'], #}-> case $facts['osfamily'] { /^(Debian|Ubuntu)$/: { file { '/etc/apache2/sites-available/000-default.conf' : ensure => present , content => template("apache/000-default.conf.erb"), require => Package['apache2'], notify => Service['apache2'], noop => true, } file { '/etc/apache2/sites-available/default-ssl.conf': ensure => present , content => template("apache/default-ssl.conf.erb"), require => Package['apache2'], notify => Service['apache2'], #noop => true, } file { ['/etc','/etc/apache2','/etc/apache2/ssl'] : ensure => directory, require => Package['apache2'], } package { 'apache2' : ensure => latest, notify => Exec['ssl'] } -> augeas { 'no' : context => "/files/etc/apache2/ports.conf", changes => [ "set /files/etc/apache2/sites-available/default-ssl.conf/IfModule/VirtualHost/directive[2]/arg localhost", "set /files/etc/apache2/sites-available/default-ssl.conf/IfModule/VirtualHost/directive[8]/arg /etc/apache2/ssl/apache.key", "set /files/etc/apache2/sites-available/default-ssl.conf/IfModule/VirtualHost/directive[7]/arg /etc/apache2/ssl/apache.crt", "set /files/etc/apache2/ports.conf/IfModule[2]/directive/arg $$no_port", "set /files/etc/apache2/ports.conf/IfModule[1]/directive/arg $no_port", "set /files/etc/apache2/ports.conf/directive/arg 8181", "set /files/etc/apache2/sites-available/000-default.conf/VirtualHost/arg *:8181", "set /files/etc/apache2/sites-available/default-ssl.conf/IfModule/VirtualHost/arg *:$no_port", ], require => Package['apache2'], } -> service { 'apache2' : ensure => running } package { 'openssl' : ensure => latest } -> exec { 'ssl' : path => ["/usr/local/sbin","/usr/local/bin","/usr/sbin","/usr/bin","/sbin","/bin"], command => 'openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt -subj "/C=GB/ST=London/L=London/O=Global Security/OU=IT Department/CN=example.com" ; a2enmod ssl ; a2ensite default-ssl ', notify => Service['apache2'], require => Augeas['no'], refreshonly => true, } } } 

no.pp

 class apache::no { require ::apache $listen_port="8181" file { 'no' : ensure => present, path => '/etc/apache2/sites-available/no.conf', content => template("apache/no.conf.erb"), notify => Exec['no'], } Exec { 'no' : path => ["/usr/local/sbin","/usr/local/bin","/sbin","/bin","/usr/sbin","/usr/bin","/root/bin"], command => 'a2ensite no.conf', notify => Service['apache2'], refreshonly => true, } #Service { 'apache2' : #ensure => running, #} } 

Merci

Votre code est en effet incohérent. Par …

 require ::apache 

… il insiste sur le fait que tout ce qui est géré via class ::apache soit géré avant tout ce qui est déclaré dans la classe actuelle, mais …

 Exec { 'no' : # ... notify => Service['apache2'], # ... } 

… nécessite que Exec['no'] soit géré avant Service['apache2'] , qui est géré par class ::apache2 . Vous ne pouvez pas avoir les deux.

Le problème provient du mélange des niveaux d’abstraction. À un endroit, vous exprimez des relations avec toute une classe et ailleurs, vous exprimez une relation avec une seule partie de cette classe. Il existe deux approches de base pour résoudre ce problème: soit créer des éléments séparés pour classer vos relations, soit établir directement toutes les relations nécessaires avec les ressources appropriées (un Package et un Service dans ce cas). Ce dernier est acceptable uniquement parce que vous travaillez dans le même module, mais même ainsi, le premier est probablement meilleur. Cela pourrait ressembler à ceci:

 class apache { # declare variables ... include '::apache::software' include '::apache::config' include '::apache::service' Class['::apache::software'] -> Class['::apache::config'] Class['::apache::config'] ~> Class['::apache::service'] } # ... class apache::software manages ensuring the package is installed # ... class apache::config manages the configuration file # ... class apache::service manages the httpd service class apache::no { require 'apache::config' # ... Exec { 'no' : # ... notify => Class['apache::service'] } }