summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThom May <thom@may.lt>2017-02-01 18:57:59 +0000
committerGitHub <noreply@github.com>2017-02-01 18:57:59 +0000
commitf02de3d8c6769dfb50f1a9429d71d007254d7572 (patch)
tree055aa8beb04654e53dd1035830acd59cd284521b
parentb711d550ec398865965ab2fd0d76fe605ff2721d (diff)
parentb752f7c2d00346a2c48b82abf49348ad0dfc4c5e (diff)
downloadchef-f02de3d8c6769dfb50f1a9429d71d007254d7572.tar.gz
Merge pull request #5765 from mal/systemd-unit-verify
Verify systemd_unit file with custom verifier
-rw-r--r--lib/chef/provider/systemd_unit.rb2
-rw-r--r--lib/chef/resource/file/verification/systemd_unit.rb67
-rw-r--r--spec/unit/resource/file/verification/systemd_unit_spec.rb103
3 files changed, 172 insertions, 0 deletions
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index a656fbbf80..5175dc6be9 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -20,6 +20,7 @@ require "chef/provider"
require "chef/mixin/which"
require "chef/mixin/shell_out"
require "chef/resource/file"
+require "chef/resource/file/verification/systemd_unit"
require "iniparse"
class Chef
@@ -193,6 +194,7 @@ class Chef
f.group "root"
f.mode "0644"
f.content new_resource.to_ini
+ f.verify :systemd_unit
end.run_action(action)
end
diff --git a/lib/chef/resource/file/verification/systemd_unit.rb b/lib/chef/resource/file/verification/systemd_unit.rb
new file mode 100644
index 0000000000..b492b32d39
--- /dev/null
+++ b/lib/chef/resource/file/verification/systemd_unit.rb
@@ -0,0 +1,67 @@
+#
+# Author:: Mal Graty (<mal.graty@googlemail.com>)
+# Copyright:: Copyright 2013-2017, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/mixin/which"
+
+class Chef
+ class Resource
+ class File
+ class Verification
+
+ #
+ # Systemd provides a binary for verifying the correctness of
+ # unit files. Unfortunately some units have constraints on the
+ # filename meaning that normal verification against temp files
+ # won't work.
+ #
+ # Working around that requires placing a copy of the temp file
+ # in a temp directory, under its real name and running the
+ # verification tool against that file.
+ #
+
+ class SystemdUnit < Chef::Resource::File::Verification
+ include Chef::Mixin::Which
+
+ provides :systemd_unit
+
+ def initialize(parent_resource, command, opts, &block)
+ super
+ @command = systemd_analyze_cmd
+ end
+
+ def verify(path, opts = {})
+ return true unless systemd_analyze_path
+ Dir.mktmpdir("chef-systemd-unit") do |dir|
+ temp = "#{dir}/#{::File.basename(@parent_resource.path)}"
+ ::FileUtils.cp(path, temp)
+ verify_command(temp, opts)
+ end
+ end
+
+ def systemd_analyze_cmd
+ @systemd_analyze_cmd ||= "#{systemd_analyze_path} verify %{path}"
+ end
+
+ def systemd_analyze_path
+ @systemd_analyze_path ||= which("systemd-analyze")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/resource/file/verification/systemd_unit_spec.rb b/spec/unit/resource/file/verification/systemd_unit_spec.rb
new file mode 100644
index 0000000000..8a3d849582
--- /dev/null
+++ b/spec/unit/resource/file/verification/systemd_unit_spec.rb
@@ -0,0 +1,103 @@
+#
+# Author:: Mal Graty (<mal.graty@googlemail.com>)
+# Copyright:: Copyright 2014-2017, Chef Software, Inc
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::File::Verification::SystemdUnit do
+ let(:command) { "#{systemd_analyze_path} verify %{path}" }
+ let(:opts) { { :future => true } }
+ let(:parent_resource) { Chef::Resource.new("llama") }
+ let(:systemd_analyze_path) { "/usr/bin/systemd-analyze" }
+ let(:systemd_dir) { "/etc/systemd/system" }
+ let(:temp_path) { "/tmp" }
+ let(:unit_name) { "sysstat-collect.timer" }
+ let(:unit_path) { "#{systemd_dir}/#{unit_name}" }
+ let(:unit_temp_path) { "#{systemd_dir}/.chef-#{unit_name}" }
+ let(:unit_test_path) { "#{temp_path}/#{unit_name}" }
+
+ describe "verification registration" do
+ it "registers itself for later use" do
+ expect(Chef::Resource::File::Verification.lookup(:systemd_unit)).to eq(Chef::Resource::File::Verification::SystemdUnit)
+ end
+ end
+
+ describe "#initialize" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(systemd_analyze_path)
+ end
+
+ it "overwrites the @command variable with the verification command" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+ expect(v.instance_variable_get(:@command)).to eql(command)
+ end
+ end
+
+ describe "#verify" do
+ context "with the systemd-analyze binary available" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(systemd_analyze_path)
+
+ allow(parent_resource).to receive(:path)
+ .and_return(unit_path)
+ allow(Dir).to receive(:mktmpdir)
+ .with("chef-systemd-unit") { |&b| b.call temp_path }
+ allow(FileUtils).to receive(:cp)
+ .with(unit_temp_path, unit_test_path)
+ end
+
+ it "copies the temp file to secondary location under correct name" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(FileUtils).to receive(:cp).with(unit_temp_path, unit_test_path)
+ expect(v).to receive(:verify_command).with(unit_test_path, opts)
+
+ v.verify(unit_temp_path, opts)
+ end
+
+ it "returns the value given by #verify_command" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(v).to receive(:verify_command)
+ .with(unit_test_path, opts)
+ .and_return("foo")
+
+ expect(v.verify(unit_temp_path, opts)).to eql("foo")
+ end
+ end
+
+ context "with the systemd-analyze binary unavailable" do
+ before(:each) do
+ allow_any_instance_of(Chef::Resource::File::Verification::SystemdUnit).to receive(:which)
+ .with("systemd-analyze")
+ .and_return(false)
+ end
+
+ it "skips verification" do
+ v = Chef::Resource::File::Verification::SystemdUnit.new(parent_resource, :systemd_unit, {})
+
+ expect(v).to_not receive(:verify_command)
+
+ expect(v.verify(unit_temp_path)).to eq(true)
+ end
+ end
+ end
+end