Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Puppet issue with apt::source and stages

I have a local Puppet installation on which I've done:

# puppet module install puppetlabs/apt  
Preparing to install into /etc/puppet/modules ...            
Downloading from http://forge.puppetlabs.com ...             
Installing -- do not interrupt ...                           
/etc/puppet/modules                                          
└─┬ puppetlabs-apt (v1.1.0)                                  
  └── puppetlabs-stdlib (v3.2.0)                             

I also have the following nodes.pp which I want to apply:

node default {                                                              
    include stdlib                                                      

    class {'apt':
            always_apt_update => true,
            disable_keys => true,
            stage => 'setup'
    }
    ->
    apt::source { "cassandra":
            location => "http://debian.datastax.com/community",
            release => "stable",
            repos => "main",
            key => "B999A372",
            key_source => "http://debian.datastax.com/debian/repo_key", 
            include_src => false
    }
}

When I try to apply it, I get:

# puppet apply nodes.pp
err: Could not apply complete catalog: Found 1 dependency cycle:
(Anchor[apt::key B999A372 present] => Apt::Key[Add key: B999A372 from Apt::Source cassandra] => File[cassandra.list] => Exec[apt_update] => Class[Apt::Update] => Stage[setup] => Stage[main] => Class[Main] => Node[default] => Apt::Source[cassandra] => File[cassandra.list])
Try the '--graph' option and opening the resulting '.dot' file in OmniGraffle or GraphViz
notice: Finished catalog run in 0.12 seconds

The problem seems to lay in the stage => 'setup' parameter, but I'd like to understand what's going on and what can I do to solve this issue (I've inherited a large puppet codebase - the above is just a proof of concept - which uses the stage thing and I don't want to remove it just yet, as I don't get Puppet's inner workings very well atm).

Update #1

Tried moving the apt::source step to the setup stage, like this:

class cassandra {
     apt::source { "cassandra":                                               
        location => "http://debian.datastax.com/community",              
        release => "stable",                                             
        repos => "main",                                                 
        key => "B999A372",                                               
        key_source => "http://debian.datastax.com/debian/repo_key",      
        include_src => false                                             
    }                                                                        
}                                                                           

node default {                                                               
    include stdlib                                                           

    class {'apt':                                                            
        always_apt_update => true,                                       
        disable_keys => true,
        stage => setup
    }                                                                        
    ->                                                                       
    class {'cassandra': stage => setup}
}

However, this doesn't solve the problem, just generates another dependency cycle.

err: Could not apply complete catalog: Found 1 dependency cycle:
(Anchor[apt::key B999A372 present] => Apt::Key[Add key: B999A372 from Apt::Source cassandra] => File[cassandra.list] => Exec[apt_update] => Class[Apt::Update] => Anchor[apt::update] => Class[Apt] => Class[Cassandra] => Apt::Source[cassandra] => File[cassandra.list])

Full debug output here. The dependency graph is this

So it seems to me that trying to enforce the order of operations in a "natural" way (via the -> operator) leads to this weird dependency cycle.

like image 487
Unknown Avatar asked Mar 13 '13 12:03

Unknown


1 Answers

Basically it looks like your apt::source specifies a key. The apt::source declaration of the apt::key states that apt::key needs to be processed before the file cassandra.list is added. This makes sense right?

But then the cassandra file resource has a notify for Exec['apt_update'], which exists in apt::update. It's a refreshonly package and is only triggered by the cassandra file resource being executed and notifying it.

That Exec['apt_update'] is inside apt::update, therefore it needs to be processed for the Class['apt::update'] to be deemed processed.

Now the actual problem occurs from the apt declaration. You've declared apt (the init manifest of the apt module) with the metaparameter stage => 'setup'. You'll find that apt actually includes apt::update, which is fine - but it also defines an anchor 'apt::update' which requires the class apt::update. Because of apt's dependency on apt::update we now have an implicit dependency on apt::update from the setup stage too.

The main stage depends on the setup stage and anything that's not given a stage automatically picks up the main stage - hence the File['cassandra.list'] is a main stage resource too (but needs to happen before apt::update which is implicitly a setup stage resource!)

I hope that helps, it can seem quite complex - especially with anchors.

like image 189
Sekm Avatar answered Nov 07 '22 13:11

Sekm