Ask Your Question
1

Virtual resources and redeclaration error

asked 2014-10-30 14:57:55 -0500

Glueon gravatar image

Puppet's documentation states that:

A virtual resource declaration specifies a desired state for a resource without adding it to the catalog

So in my understanding that means that if i write something like this:

class a {
   @user { 'test' : ensure => present }
}

class b {
    @user { 'test' : ensure => present }
}

node default {
    include a
    include b
}

I should get a working manifest. But actually this gives a redeclaration error. I clearly understand that this shouldn't work if I remove "@" and make them non-virtual - then both user resources appear in the same scope and cause redeclaration error to rise. But if a virtual resource isn't added to the catalog in case it hasn't been realized why do I get a compilation error?

Maybe actually resource IS added to the catalog but agent ignores it unless it's realized or it's somehow removed after the compilation? Otherwise I am a little confused what compilation stage or any other phase in does the redeclaration error occur.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2014-10-30 16:52:46 -0500

cbarbour gravatar image

updated 2014-10-31 17:39:16 -0500

A virtual resource can only be declared once, however it can be realized multiple times.

The following is not legal:

@user { 'test' : ensure => present }
@user { 'test' : ensure => present }
realize User['test']

The following is valid:

@user { 'test' : ensure => present }
realize User['test']
realize User['test']

Let's re-write your example to use virtual resources:

class a {
  realize User['test']
}

class b {
  realize User['test']
}

class c {
  @user { 'test' : ensure => present }
}

node default {
  include a
  include b
  include c
}

Note that virtual resources do not have to be declared or realized in any particular order; so long as they are declared, they can be realized anywhere. They are parse order independent.

Edit: The original posted asked this question:

What I want to understand is WHY it's not legal. If I use non-virtual resources it's pretty clear why do I get an error during catalog compilation. But if it's virtual and isn't added to the catalog then who raises this error?

It's illegal to declare a virtual resource more than once, because otherwise the following could happen:

@user { 'test' : ensure => 'present' }
@user { 'test' : ensure => 'absent' }
realize User['test']

Duplicate declaration errors happen when resources are declared, not when they are applied or realized. That's why you are seeing this error, even when your specific application may not create a conflict. Again, the purpose is to ensure that if one contributor steps on another contributors toes, you know about it before unexpected things happen.

Edit 2: The original poster asks:

No, I understand all the reasoning why it gives an error. I am curious just about catalog compilation process. If virtual resource isn't realized it's not added to the catalog. So when does it get excluded? I thought it's being wiped out from manifest, but then the error shouldn't appear.

Resource Declaration: The server models the catalog before sending it to the client. Virtual resources are added as soon as they are declared, whether or not they are realized. This is where the duplicate resource error is raised.

The Collector: When resources are realized, a collector searches the catalog for any objects matching the collection criteria, and marks them as not virtual.

Virtual Resources are discarded: The compiler iterates through the catalog discarding any non-realized virtual resources.

The result is sent to the client.

edit flag offensive delete link more

Comments

I understand that and know how to solve that. What I want to understand is WHY it's not legal. If I use non-virtual resources it's pretty clear why do I get an error during catalog compilation. But if it's virtual and isn't added to the catalog then who raises this error?

Glueon gravatar imageGlueon ( 2014-10-30 17:08:38 -0500 )edit

Virtual resources do not change the rules of resource declaration. https://docs.puppetlabs.com/puppet/latest/reference/lang_resources.html#uniqueness A virtual resource is still only declared once. You are simply realizing it multiple times. It's the same as class { 'foo': } vs include 'foo'

cbarbour gravatar imagecbarbour ( 2014-10-30 18:36:41 -0500 )edit

I edited my original post to answer your question. You can work around this restriction using the stdlib ensure_resource() function, but I honestly advise strongly against using ensure_resource() across modules. It has no benefits over using virtual resources, and is parse order dependent.

cbarbour gravatar imagecbarbour ( 2014-10-30 18:42:21 -0500 )edit

No, I understand all the reasoning why it gives an error. I am curious just about catalog compilation process. If virtual resource isn't realized it's not added to the catalog. So when does it get excluded? I thought it's being wiped out from manifest, but then the error shouldn't appear.

Glueon gravatar imageGlueon ( 2014-10-31 05:37:39 -0500 )edit

I wanted to known what is really going on on a lower level. While applying manifest puppet takes all resources within the visibility scope into the set, verifies if they are unique, excludes unrealized virtual ones and only then compiles the catalog? Then it makes sense.

Glueon gravatar imageGlueon ( 2014-10-31 05:41:55 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2014-10-30 14:57:55 -0500

Seen: 471 times

Last updated: Oct 31 '14