0

I don't appear to understand how to change the content of a file resource a different points in the application of Puppet manifests. I'm using this with Vagrant to set up a dev environment.

I want to install oh-my-zshell, which provides a template for the .zshrc file. oh-myzshell has the concept of plugins, so I choose which plugins I'd like, add them to the template and make it a template for a puppet manifest:

class oh_my_zshell {
  include git
  include zsh

  $oh_my_zshell_dir = "${vagrant_home_dir}/.oh-my-zsh"
  $plugins          = "command-not-found common-aliases sudo"
  $theme            = "ys"
  $zshrc            = "${vagrant_home_dir}/.zshrc"
  $backup           = "${zshrc}.orig"

  @file { "zshrc":
    path    =>  $zshrc,
    ensure  =>  file,
    content =>  template("oh_my_zshell/zshrc.erb"),
  }

  realize( File["zshrc"],Package["zsh"] )

snip!

and in the template:

# Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*)
# Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
plugins=(<%= @plugins %>)

That works fine.

Later, I decide that I'd like to install chruby. There is an oh-my-zshell plugin for chruby, so I want to reapply the template with new values for the plugin:

class chruby {
  include apt_update
  include oh_my_zshell
  include stdlib
  $plugins        = "${oh_my_zshell::plugins} chruby"
  $theme          = $oh_my_zshell::theme

snip!

  realize(File["zshrc"])

  file_line {"chruby set default ruby":
    path    =>  $oh_my_zshell::zshrc,
    line    =>  'chruby ruby-2.1.2',
    require =>  File["zshrc"],
  }

This, however, does not change the file at all - there is no chruby in the plugins statement, and there is no line to set the default ruby.

It makes sense to me that as different things are installed they change a file to meet its requirements, and that at each point of the installation process the file is left in a state that is workable. The oh_my_zshell class shouldn't need to know about the chruby class or any other thing that may be installed later.

Is there something I should be doing to make this work, or am I working against the way Puppet should be used? The alternative I can see is to take the writing of the file out of the classes and finalize it in the main manifest, waiting until all variables have been filled.

I'm new to Puppet, so any help or insight will be much appreciated.

  • To be clear, you're really trying to add to "plugins" and add additional lines to a single file, not to re-use the same template with different files and different variables? – freiheit Jun 16 '14 at 23:51
  • @freiheit Yes, that's right. – Iain Jun 17 '14 at 0:17
3

You shouldn't use a virtual resource (@file and realize) for this. The variables for the template will be from the original scope that it's defined in (where the @file) is, not where it's realized.

What you want is a define.

define thingy(
  $path,
  $plugins) {

  file { '$path':
    content => template("oh_my_zshell/zshrc.erb"),
  }
}

And if you want to add lines, you should add an optional parameter to the define and use that conditionally in the template. Defining a file with a content or source and then trying to edit the contents of that file in another resource will not do what you want.

Alternately, it might instead make sense to have oh_my_zshell be a class that takes parameters and pass an "additional_plugins" variable...

# declare class with param
class oh_my_zshell($additional_plugins = '') {
  # put it into the other variable or use in the template or whatever
}

# instead of the include/require
class { 'oh_my_zshell':
  additional_plugins = 'chruby',
}
  • Thanks for this. I'll give the define a try and see how it goes. – Iain Jun 17 '14 at 0:18
  • 1
    Note that this scheme still will not allow for class chruby to amend your state "after the fact" and independently of other pieces of the manifest. If you don't want to go the Hiera route (which is almost always ideal), you'd need to add class inheritance to the mix and override the define's parameter values. – Felix Frank Jun 17 '14 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.