diff --git a/lib/hiera/scope.rb b/lib/hiera/scope.rb index 781c1eb3a..87d340157 100644 --- a/lib/hiera/scope.rb +++ b/lib/hiera/scope.rb @@ -1,60 +1,63 @@ class Hiera class Scope CALLING_CLASS = "calling_class" + CALLING_CLASS_PATH = "calling_class_path" CALLING_MODULE = "calling_module" MODULE_NAME = "module_name" attr_reader :real def initialize(real) @real = real end def [](key) if key == CALLING_CLASS ans = find_hostclass(@real) + elsif key == CALLING_CLASS_PATH + ans = find_hostclass(@real).gsub(/::/, '/') elsif key == CALLING_MODULE ans = @real.lookupvar(MODULE_NAME) else ans = @real.lookupvar(key) end if ans.nil? or ans == "" nil else ans end end def include?(key) - if key == CALLING_CLASS or key == CALLING_MODULE + if [CALLING_CLASS, CALLING_CLASS_PATH, CALLING_MODULE].include? key true else @real.lookupvar(key) != "" end end def catalog @real.catalog end def resource @real.resource end def compiler @real.compiler end def find_hostclass(scope) if scope.source and scope.source.type == :hostclass return scope.source.name.downcase elsif scope.parent return find_hostclass(scope.parent) else return nil end end private :find_hostclass end end diff --git a/spec/integration/data_binding.rb b/spec/integration/data_binding.rb index 0e8db4dfa..2cd029f3c 100644 --- a/spec/integration/data_binding.rb +++ b/spec/integration/data_binding.rb @@ -1,100 +1,104 @@ require 'spec_helper' require 'puppet_spec/compiler' describe "Data binding" do include PuppetSpec::Files include PuppetSpec::Compiler let(:dir) { tmpdir("puppetdir") } before do Puppet[:data_binding_terminus] = "hiera" Puppet[:modulepath] = dir end it "looks up data from hiera" do configure_hiera_for({ "testing::binding::value" => "the value", "testing::binding::calling_class" => "%{calling_class}", + "testing::binding::calling_class_path" => "%{calling_class_path}", "testing::binding::calling_module" => "%{calling_module}" + }) create_manifest_in_module("testing", "binding.pp", <<-MANIFEST) class testing::binding($value, $calling_class, + $calling_class_path, $calling_module) {} MANIFEST catalog = compile_to_catalog("include testing::binding") resource = catalog.resource('Class[testing::binding]') expect(resource[:value]).to eq("the value") expect(resource[:calling_class]).to eq("testing::binding") + expect(resource[:calling_class_path]).to eq("testing/binding") expect(resource[:calling_module]).to eq("testing") end it "works with the puppet backend configured, although it can't use it for lookup" do configure_hiera_for_puppet create_manifest_in_module("testing", "binding.pp", <<-MANIFEST) # lookup via the puppet backend to ensure it works class testing::binding($value = hiera('variable')) {} MANIFEST create_manifest_in_module("testing", "data.pp", <<-MANIFEST) class testing::data { $variable = "the value" } MANIFEST catalog = compile_to_catalog("include testing::binding") resource = catalog.resource('Class[testing::binding]') expect(resource[:value]).to eq("the value") end def configure_hiera_for(data) hiera_config_file = tmpfile("hiera.yaml") File.open(hiera_config_file, 'w') do |f| f.write("--- :yaml: :datadir: #{dir} :hierarchy: ['global'] :logger: 'noop' :backends: ['yaml'] ") end File.open(File.join(dir, 'global.yaml'), 'w') do |f| f.write(YAML.dump(data)) end Puppet[:hiera_config] = hiera_config_file end def configure_hiera_for_puppet hiera_config_file = tmpfile("hiera.yaml") File.open(hiera_config_file, 'w') do |f| f.write("--- :logger: 'noop' :backends: ['puppet'] ") end Puppet[:hiera_config] = hiera_config_file end def create_manifest_in_module(module_name, name, manifest) module_dir = File.join(dir, module_name, 'manifests') FileUtils.mkdir_p(module_dir) File.open(File.join(module_dir, name), 'w') do |f| f.write(manifest) end end end diff --git a/spec/unit/hiera/scope_spec.rb b/spec/unit/hiera/scope_spec.rb index d53b435ce..a18823615 100644 --- a/spec/unit/hiera/scope_spec.rb +++ b/spec/unit/hiera/scope_spec.rb @@ -1,89 +1,90 @@ require 'spec_helper' require 'hiera/scope' require 'puppet_spec/scope' describe Hiera::Scope do include PuppetSpec::Scope let(:real) { create_test_scope_for_node("test_node") } let(:scope) { Hiera::Scope.new(real) } describe "#initialize" do it "should store the supplied puppet scope" do scope.real.should == real end end describe "#[]" do it "should return nil when no value is found" do scope["foo"].should == nil end it "should treat '' as nil" do real["foo"] = "" scope["foo"].should == nil end it "should return found data" do real["foo"] = "bar" scope["foo"].should == "bar" end it "preserves the case of a string that is found" do real["foo"] = "CAPITAL!" scope["foo"].should == "CAPITAL!" end it "aliases $module_name as calling_module" do real["module_name"] = "the_module" scope["calling_module"].should == "the_module" end it "uses the name of the of the scope's class as the calling_class" do real.source = Puppet::Resource::Type.new(:hostclass, "testing", :module_name => "the_module") scope["calling_class"].should == "testing" end it "downcases the calling_class" do real.source = Puppet::Resource::Type.new(:hostclass, "UPPER CASE", :module_name => "the_module") scope["calling_class"].should == "upper case" end it "looks for the class which includes the defined type as the calling_class" do parent = create_test_scope_for_node("parent") real.parent = parent parent.source = Puppet::Resource::Type.new(:hostclass, "name_of_the_class_including_the_definition", :module_name => "class_module") real.source = Puppet::Resource::Type.new(:definition, "definition_name", :module_name => "definition_module") scope["calling_class"].should == "name_of_the_class_including_the_definition" end end describe "#include?" do it "should correctly report missing data" do real["foo"] = "" scope.include?("foo").should == false end it "should always return true for calling_class and calling_module" do scope.include?("calling_class").should == true + scope.include?("calling_class_path").should == true scope.include?("calling_module").should == true end end end