Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(#14529) Add registry::value defined type #16

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Modulefile
Expand Up @@ -8,4 +8,4 @@ description 'This module provides a native type and provider to manage keys and
project_page 'http://links.puppetlabs.com/registry-module'

## Add dependencies, if any:
# dependency 'username/name', '>= 1.2.0'
dependency 'puppetlabs/stdlib', '>= 2.3.0'
17 changes: 17 additions & 0 deletions README.markdown
Expand Up @@ -50,6 +50,23 @@ The `registry_key` and `registry_value` types are provided by this module.
data => "The Puppet Agent service periodically manages your configuration",
}

The `registry::value` defined resource type provides a convenient way to manage
values and the parent key:

registry::value { 'MyApp Setting1':
key => 'HKLM\Software\Vendor\PuppetLabs',
value => setting1,
data => 'Hello World!'
}

With this single resource declaration both the `registry_key` of
`HKLM\Software\Vendor\PuppetLabs` and the `registry_value` of
`HKLM\Software\Vendor\PuppetLabs\setting` will be managed.

The `registry::value` defined type only managed keys and values in the system
native architecture. That is to say, the 32 bit keys won't be managed by this
defined type on a 64 bit OS.

Purge Values Example
--------------------

Expand Down
2 changes: 1 addition & 1 deletion acceptance/lib/systest/util/registry.rb
Expand Up @@ -138,7 +138,7 @@ def setup_master(master_manifest_content="# Intentionally Blank\n")
masters.each do |host|
moddir = get_test_file_path(host, master_module_dir)
mkdirs(host, moddir)
on host, "ln -s /opt/puppet-git-repos/registry \"#{moddir}/registry\""
on host, "ln -s /opt/puppet-git-repos/stdlib \"#{moddir}/stdlib\"; ln -s /opt/puppet-git-repos/registry \"#{moddir}/registry\""
end
end
end
Expand Down
105 changes: 105 additions & 0 deletions acceptance/tests/resource/registry/should_have_defined_type.rb
@@ -0,0 +1,105 @@
require 'pathname'
require Pathname.new(__FILE__).dirname.dirname.dirname.dirname + 'lib/systest/util/registry'
# Include our utility methods in the singleton class of the test case instance.
class << self
include Systest::Util::Registry
end

test_name "registry::value defined type"

# Generate a unique key name
keyname = "PuppetLabsTest_MixedCase_#{randomstring(8)}"
# This is the keypath we'll use for this entire test. We will actually create this key and delete it.
vendor_path = "HKLM\\Software\\Vendor"
keypath = "#{vendor_path}\\#{keyname}"

master_manifest_content = <<HERE
notify { fact_phase: message => "fact_phase: $fact_phase" }

registry_key { '#{vendor_path}': ensure => present }

class phase1 {
registry::value { 'Setting1':
key => '#{keypath}',
value => 'Setting1',
data => "fact_phase=${fact_phase}",
}
registry::value { 'Setting2':
key => '#{keypath}',
data => "fact_phase=${fact_phase}",
}
registry::value { 'Setting3':
key => '#{keypath}',
value => 'Setting3',
data => "fact_phase=${fact_phase}",
}
registry::value { 'Setting0':
key => '#{keypath}',
value => '(default)',
data => "fact_phase=${fact_phase}",
}
}

case $fact_phase {
default: { include phase1 }
}
HERE

# Setup the master to use the modules specified in the --modules option
setup_master master_manifest_content

step "Start the master" do
with_master_running_on(master, master_options) do
# A set of keys we expect Puppet to create
phase1_resources_created = [
/Registry_key\[HKLM.Software.Vendor.PuppetLabsTest\w+\].ensure: created/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\\].ensure: created/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting1\].ensure: created/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting2\].ensure: created/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting3\].ensure: created/,
]

phase2_resources_changed = [
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\\].data: data changed 'fact_phase=1' to 'fact_phase=2'/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting1\].data: data changed 'fact_phase=1' to 'fact_phase=2'/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting2\].data: data changed 'fact_phase=1' to 'fact_phase=2'/,
/Registry_value\[HKLM.Software.Vendor.PuppetLabsTest\w+\\Setting3\].data: data changed 'fact_phase=1' to 'fact_phase=2'/,
]

windows_agents.each do |agent|
this_agent_args = agent_args % get_test_file_path(agent, agent_lib_dir)

step "Phase 1.a - Create some values"
on agent, puppet_agent(this_agent_args, :environment => { 'FACTER_FACT_PHASE' => '1' }), :acceptable_exit_codes => agent_exit_codes do
phase1_resources_created.each do |val_re|
assert_match(val_re, result.stdout, "Expected output to contain #{val_re.inspect}.")
end
assert_no_match(/err:/, result.stdout, "Expected no error messages.")
end

step "Phase 1.b - Make sure Puppet is idempotent"
on agent, puppet_agent(this_agent_args, :environment => { 'FACTER_FACT_PHASE' => '1' }), :acceptable_exit_codes => agent_exit_codes do
phase1_resources_created.each do |val_re|
assert_no_match(val_re, result.stdout, "Expected output not to contain #{val_re.inspect}.")
end
assert_no_match(/err:/, result.stdout, "Expected no error messages.")
end

step "Phase 2.a - Change some values"
on agent, puppet_agent(this_agent_args, :environment => { 'FACTER_FACT_PHASE' => '2' }), :acceptable_exit_codes => agent_exit_codes do
phase2_resources_changed.each do |val_re|
assert_match(val_re, result.stdout, "Expected output to contain #{val_re.inspect}.")
end
assert_no_match(/err:/, result.stdout, "Expected no error messages.")
end

step "Phase 2.b - Make sure Puppet is idempotent"
on agent, puppet_agent(this_agent_args, :environment => { 'FACTER_FACT_PHASE' => '2' }), :acceptable_exit_codes => agent_exit_codes do
(phase1_resources_created + phase2_resources_changed).each do |val_re|
assert_no_match(val_re, result.stdout, "Expected output not to contain #{val_re.inspect}.")
end
assert_no_match(/err:/, result.stdout, "Expected no error messages.")
end
end
end
end
68 changes: 68 additions & 0 deletions manifests/value.pp
@@ -0,0 +1,68 @@
# = Define: registry::value
#
# This defined resource type provides a higher level of abstraction on top of
# the registry_key and registry_value resources. Using this defined resource
# type, you do not need to explicitly manage the parent key for a particular
# value. Puppet will automatically manage the parent key for you.
#
# == Parameters:
#
# key:: The path of key the value will placed inside.
#
# value:: The name of the registry value to manage. This will be copied from
# the resource title if not specified. The special value of
# '(default)' may be used to manage the default value of the key.
#
# type:: The type the registry value. Defaults to 'string'. See the output of
# `puppet describe registry_value` for a list of supported types in the
# "type" parameter.
#
# data:: The data to place inside the registry value.
#
# == Actions:
# - Manage the parent key if not already managed.
# - Manage the value
#
# == Requires:
# - Registry Module
# - Stdlib Module
#
# == Sample Usage:
#
# This example will automatically manage the key. It will also create a value
# named 'puppetmaster' inside this key.
#
# class myapp {
# registry::value { 'puppetmaster':
# key => 'HKLM\Software\Vendor\PuppetLabs',
# data => 'puppet.puppetlabs.com',
# }
# }
#
define registry::value($key, $value=undef, $type='string', $data=undef) {
# validate our inputs.
validate_re($key, '^\w+', "key parameter must not be empty but it is key => '$key'")
validate_re($type, '^\w+', "type parameter must not be empty but it is type => '$type'")

$value_real = $value ? {
undef => $name,
'(default)' => '',
default => $value,
}

# Resource defaults.
Registry_key { ensure => present }
Registry_value { ensure => present }

if !defined(Registry_key["${key}"]) {
registry_key { "${key}": }
}

# If value_real is an empty string then the default value of the key will be
# managed.
registry_value { "${key}\\${value_real}":
type => $type,
data => $data,
}
}