# "Re-Declaring" I dont get it.

First I will apologize to you all. I was thrown in to Puppet last Thursday and told I will be running it from now on. I hadnt even heard of it until Thurs.
I also ask for your patience as I am just learning the ins and outs, and have spent the last 5 hours (literally) looking at the syntax for the first time.

I am attempting to remove all references of java out of the windows path variable:

• C:\Program Files\Java\jdk1.7.0_45\bin
• C:\Program Files\Java\jdk1.7.0_50\bin
• C:\Program Files\Java\jdk1.7.0_51\bin

We are using windows_path to do this.

The problem I am having is re-declaring. Typically with most languages I would just declare what I want to do on one line or loop, run it, and then declare in another loop what else I want to do, and there are no conflicts. Puppet seems different. Particularly this part of the script:

# Adds java to the path.
windows_path {'javaPath':
ensure      => present,
directory   => "C:\\Program Files\\Java\\$file\\bin",  Which indeed adds the new correct path. I also found I can change present to absent and it will remove that path location. Except I need it to remove ALL previous versions of java, not just the current we are trying to install. What I cant figure out is how to do both. If I call upon windows_path twice, once in the begining to remove and again after it to add, it just tells me I cant re-declare. So there in lies my question. How do I do both? I ask for detailed responses as this is all completely new to me. I learn fast, and will pick it up, but for now my level of puppet understanding as a whole is about 3/10. And again, I will apologize in advance for my current state of confusion. (assume its your first day learning puppet and youll know how I feel :) ) # # Installs and manages Java on Windows machines. #$source should be set to the name of the .exe that will be copied over.
# $package should be the name of the installed program. Easiest way to figure this out is to install manually, then look at installed program list. #$file should be equal to the name of the files that get created by the install, such as 'jdk1.7.0_55'. Used to set the path.
#
define windows_java::setup (
$ensure = 'present',$source        = undef,
$file = undef,$package       = undef ) {

case $::osfamily { Windows : {$supported = true }
default : { fail("The ${module_name} module is not supported on${::osfamily} based systems") }
}

# Validate parameters
if ($source == undef) { fail('source parameter must be set') } if ($file == undef) {
fail('file parameter must be set')
}

if ($package == undef) { fail('package parameter must be set') } # Validate input values for$ensure
if !($ensure in ['present', 'absent']) { fail('ensure must either be present or absent') } if ($caller_module_name == undef) {
$mod_name =$module_name
} else {
$mod_name =$caller_module_name
}

if ($ensure == 'present'){ # ensures main directory exists file {'C:\Program Files\Java': ensure => directory ... edit retag close merge delete ## 3 Answers Sort by » oldest newest most voted Welcome to puppet. As you are probably learning, puppet is not a scripting language; so you must rethink in terms of state, not procedures. The reason that you are finding that you can't redeclare windows_path {'javaPath': is because each resource in a manifest must have a unique title. (Think of each resource as an object). You can't have two windows_path objects with the same title of 'javaPath' Also as you have discovered, puppet does not do looping. See this stack overflow question for an explanation Without having experience with puppet on windows or the windows_path module, I can't tell exactly why you are getting the error you are seeing, but it looks like you aren't including the module in your manifest. Could you try adding include windows_path  Then show the exact error? more I am sorry. I should reiterate. The above code is indeed working. What my issue is, is that I can only use this: # Adds java to the path. windows_path {'javaPath': ensure => present, directory => "C:\\Program Files\\Java\\$file\\bin",
}


or this (absent):

# Adds java to the path.
windows_path {'javaPath':
ensure      => absent,
directory   => "C:\\Program Files\\Java\\$file\\bin", }  however I can not do both. I need it to first remove all instances of java from the path, then re-add the one we want to add. I attempted to do this: # Removes java from the path. windows_path {'removejavaPath': ensure => absent, directory => "C:\\Program Files\\Java\\$file\\bin",
}

# Adds java to the path.
windows_path {'javaPath':
ensure      => present,
directory   => "C:\\Program Files\\Java\\$file\\bin", }  Edit: New Code with 'removejavapath' # # Installs and manages Java on Windows machines. #$source should be set to the name of the .exe that will be copied over.
# $package should be the name of the installed program. Easiest way to figure this out is to install manually, then look at installed program list. #$file should be equal to the name of the files that get created by the install, such as 'jdk1.7.0_55'. Used to set the path.
#
include windows_path

define windows_java::setup (
$ensure = 'present',$source        = undef,
$file = undef,$package       = undef ) {

case $::osfamily { Windows : {$supported = true }
default : { fail("The ${module_name} module is not supported on${::osfamily} based systems") }
}

# Validate parameters
if ($source == undef) { fail('source parameter must be set') } if ($file == undef) {
fail('file parameter must be set')
}

if ($package == undef) { fail('package parameter must be set') } # Validate input values for$ensure
if !($ensure in ['present', 'absent']) { fail('ensure must either be present or absent') } if ($caller_module_name == undef) {
$mod_name =$module_name
} else {
$mod_name =$caller_module_name
}

if ($ensure == 'present'){ # ensures main directory exists file {'C:\Program Files\Java': ensure => directory, } # copies source executable over file { "C:\\Program Files\\Java\\$source":
ensure             => present,
source             => "puppet:///extra_files/java/windows/$source", before => Package["$package"],
source_permissions => ignore,
}

# Name of package must match name when installed
package { "$package": ensure => installed, source => "C:\\Program Files\\java\\$source",
install_options    => '/s',
}

# sets JAVA_HOME. If already existant, replaces it.
windows_env { "JAVA_HOME=C:\\Program Files\\Java\\$file": mergemode => clobber, } # removes previous Java from path windows_path {'removejavapath': ensure => absent, directory => "C:\\Program Files\\Java\\jdk1.7.0_51\\bin" } # Adds java to the path. windows_path {'javaPath': ensure => present, directory => "C:\\Program Files\\Java\\$file\\bin",
}
} else {

package { 'remove-package':
name   => "$package", ensure => absent, } windows_env { 'JAVA_HOME': ensure => 'absent', mergemode => clobber, } windows_path {'remove_java_path': ensure => absent, directory => "C:\\Program Files\\Java\\$file\\bin",
}
}
}


Edit: output

C:\Windows\system32>puppet agent --test
Info: Retrieving pluginfacts
Warning: Copying owner/mode/group from the source file on Windows is deprecated; use source_permissions => ignore.
(at C:/Program Files (x86)/Puppet Labs/Puppet/puppet/lib/puppet/type/file/source.rb:120:in each')
Info: Retrieving plugin
'lspci' is not recognized as an internal or external command,
operable program or batch file.
Info: Loading facts in C:/ProgramData/PuppetLabs/puppet ...
more

Puppet uses the manifests to create a dependency graph for all the nodes. Each node must exist once, but can of course have multiple relationships. As Spuder said, Puppet is not a scripting language.

( 2014-08-15 00:00:11 -0500 )edit

What other answers are pointing out is that a resource with a given name can only exist once. This is defined by resource type (windows_path) and title ('javaPath'). So windows_path{'javaPath':} needs to point to only ONE resource ever.

( 2014-09-15 10:19:37 -0500 )edit

I'm quite new to Puppet myself, so I know exactly how you feel :)

Had a quick look at your snippet - please keep in mind that Puppet does not execute serially. Rather, it uses internal ordering - which is random, unless you specifically set dependencies between your resources. Example:

#removes previous Java from path
windows_path {'removejavapath':
ensure      => absent,
directory   => "C:\\Program Files\\Java\\jdk1.7.0_51\\bin"
}
windows_path {'javaPath':
ensure      => present,
directory   => "C:\\Program Files\\Java\\\$file\\bin",
require => Window_path['removejavapath'],
}
`

Puppet will now know to execute removal before attempting to re-add the path.

more