From e20824b7c213ce9ffaf86340b1594dd23dbb2897 Mon Sep 17 00:00:00 2001 From: Xabier de Zuazo Date: Thu, 17 Sep 2015 22:55:04 +0200 Subject: [PATCH] Move the ruby_block[apply config] logic to a library, including tests --- libraries/cookbook_helpers.rb | 62 +++++++ recipes/default.rb | 27 +-- test/unit/libraries/cookbook_helpers.rb | 208 ++++++++++++++++++++++++ test/unit/support/fake_recipe.rb | 35 ++++ 4 files changed, 307 insertions(+), 25 deletions(-) create mode 100644 libraries/cookbook_helpers.rb create mode 100644 test/unit/libraries/cookbook_helpers.rb create mode 100644 test/unit/support/fake_recipe.rb diff --git a/libraries/cookbook_helpers.rb b/libraries/cookbook_helpers.rb new file mode 100644 index 0000000..00bbb9c --- /dev/null +++ b/libraries/cookbook_helpers.rb @@ -0,0 +1,62 @@ +# `owncloud` cookbook internal classes. +module OwncloudCookbook + # Some helpers to use from `owncloud` cookbook recipes or resources. + module CookbookHelpers + def owncloud_config_file + ::File.join(node['owncloud']['dir'], 'config', 'config.php') + end + + def owncloud_config + @owncloud_config ||= OwncloudCookbook::Config.new(owncloud_config_file) + end + + def owncloud_cookbook_config + @owncloud_cookbook_config ||= node['owncloud']['config'].to_hash + end + + def owncloud_trusted_domains + [ + node['owncloud']['server_name'], node['owncloud']['server_aliases'] + ].flatten + end + + # Add server name and server aliases to trusted_domains config option. + def calculate_trusted_domains + unless owncloud_cookbook_config.key?('trusted_domains') + owncloud_cookbook_config['trusted_domains'] = [] + end + owncloud_trusted_domains.each do |domain| + next if owncloud_cookbook_config['trusted_domains'].include?(domain) + owncloud_cookbook_config['trusted_domains'] << domain + end + end + + def calculate_dbhost + owncloud_cookbook_config['dbhost'] = + [ + owncloud_cookbook_config['dbhost'], owncloud_cookbook_config['dbport'] + ].join(':') + end + + def owncloud_config_update + owncloud_config.merge(owncloud_cookbook_config) + owncloud_config.write + owncloud_config + end + + # Store important options that where generated automatically by the setup. + def save_owncloud_node_configuration + return if Chef::Config[:solo] + %w(passwordsalt instanceid).each do |value| + node.set_unless['owncloud']['config'][value] = owncloud_config[value] + end + end + + def apply_owncloud_configuration + calculate_trusted_domains + calculate_dbhost + owncloud_config_update + save_owncloud_node_configuration + end + end +end diff --git a/recipes/default.rb b/recipes/default.rb index 5d0eb51..5bd7c24 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -388,31 +388,8 @@ # Apply the configuration on attributes to config.php ruby_block 'apply config' do block do - config_file = ::File.join(node['owncloud']['dir'], 'config', 'config.php') - config = OwncloudCookbook::Config.new(config_file) - cookbook_config = node['owncloud']['config'].to_hash - # Add server name and server aliases to trusted_domains config option - unless cookbook_config.key?('trusted_domains') - cookbook_config['trusted_domains'] = [] - end - [ - node['owncloud']['server_name'], node['owncloud']['server_aliases'] - ].flatten.each do |domain| - next if cookbook_config['trusted_domains'].include?(domain) - cookbook_config['trusted_domains'] << domain - end - cookbook_config['dbhost'] = - "#{cookbook_config['dbhost']}:#{cookbook_config['dbport']}" - config.merge(cookbook_config) - config.write - unless Chef::Config[:solo] - # store important options that where generated automatically by the setup - node.set_unless['owncloud']['config']['passwordsalt'] = - config['passwordsalt'] - node.set_unless['owncloud']['config']['instanceid'] = - config['instanceid'] - node.save - end + self.class.send(:include, OwncloudCookbook::CookbookHelpers) + apply_owncloud_configuration end only_if do ::File.exist?(::File.join(node['owncloud']['dir'], 'config', 'config.php')) diff --git a/test/unit/libraries/cookbook_helpers.rb b/test/unit/libraries/cookbook_helpers.rb new file mode 100644 index 0000000..75b7751 --- /dev/null +++ b/test/unit/libraries/cookbook_helpers.rb @@ -0,0 +1,208 @@ +# encoding: UTF-8 +# +# Author:: Xabier de Zuazo () +# Copyright:: Copyright (c) 2015 Xabier de Zuazo +# 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_relative '../spec_helper' +require_relative '../support/fake_recipe' +require 'cookbook_helpers' +require 'config' + +describe OwncloudCookbook::CookbookHelpers, order: :random do + subject { FakeRecipe.new } + let(:node) { subject.node } + let(:config_file) { '/var/www/owncloud/config/config.php' } + before do + node.set['owncloud']['dir'] = '/var/www/owncloud' + allow(::File).to receive(:exist?).and_call_original + allow(::File).to receive(:exist?).with(config_file).and_return(false) + end + + context '#owncloud_config_file' do + it 'returns ownCloud configuration file' do + expect(subject.owncloud_config_file).to eq(config_file) + end + end + + context '#owncloud_config' do + it 'returns an OwncloudCookbook::Config instance' do + expect(::File).to receive(:exist?).with(config_file).and_return(false) + expect(subject.owncloud_config).to be_a(OwncloudCookbook::Config) + end + + it 'passes the file path to OwncloudCookbook::Config' do + expect(OwncloudCookbook::Config) + .to receive(:new).once.and_return(config_file) + subject.owncloud_config + end + end + + context '#owncloud_cookbook_config' do + it 'returns a hash' do + expect(subject.owncloud_cookbook_config).to be_instance_of(Hash) + end + + it 'does not return a mash' do + expect(subject.owncloud_cookbook_config).to_not be_instance_of(Mash) + end + + it 'has the same value as node["owncloud"]["config"]' do + expect(subject.owncloud_cookbook_config).to eq(node['owncloud']['config']) + end + + it 'is not the same hash as node["owncloud"]["config"]' do + expect(subject.owncloud_cookbook_config) + .to_not equal(node['owncloud']['config']) + end + end # context #owncloud_cookbook_config + + context '#owncloud_trusted_domains' do + let(:server_name) { 'servername1' } + let(:server_aliases) { %w(serveralias1 serveralias2) } + before do + node.set['owncloud']['server_name'] = server_name + node.set['owncloud']['server_aliases'] = server_aliases + end + + it 'returns server name and server aliases' do + expect(subject.owncloud_trusted_domains) + .to eq(%w(servername1 serveralias1 serveralias2)) + end + end + + context '#calculate_trusted_domains' do + let(:server_name) { 'servername1' } + let(:server_aliases) { %w(serveralias1 serveralias2) } + before do + node.set['owncloud']['server_name'] = server_name + node.set['owncloud']['server_aliases'] = server_aliases + end + + it 'sets owncloud trusted_domains configuration' do + subject.calculate_trusted_domains + expect(subject.owncloud_cookbook_config['trusted_domains'].sort) + .to eq(%w(servername1 serveralias1 serveralias2).sort) + end + + it 'does not duplicate domains' do + node.set['owncloud']['config']['trusted_domains'] = [server_aliases[0]] + subject.calculate_trusted_domains + expect(subject.owncloud_cookbook_config['trusted_domains'].sort) + .to eq(%w(servername1 serveralias1 serveralias2).sort) + end + end # context #calculate_trusted_domains + + context '#calculate_dbhost' do + let(:dbhost) { 'mydbhost' } + let(:dbport) { 'mydbport' } + before do + node.set['owncloud']['config']['dbhost'] = dbhost + node.set['owncloud']['config']['dbport'] = dbport + end + + it 'returns database address' do + expect(subject.calculate_dbhost).to eq("#{dbhost}:#{dbport}") + end + end + + context '#owncloud_config_update' do + let(:owncloud_config) { instance_double('OwncloudCookbook::Config') } + before do + allow(OwncloudCookbook::Config) + .to receive(:new).and_return(owncloud_config) + allow(owncloud_config).to receive(:merge) + allow(owncloud_config).to receive(:write) + end + + it 'merges the configuration' do + expect(owncloud_config) + .to receive(:merge).with(subject.owncloud_cookbook_config).once + subject.owncloud_config_update + end + + it 'writes the configuration' do + expect(owncloud_config).to receive(:write).with(no_args).once + subject.owncloud_config_update + end + + it 'returns the owncloud configuration' do + expect(subject.owncloud_config_update).to equal(owncloud_config) + end + end # context #owncloud_config_update + + context '#save_owncloud_node_configuration' do + let(:salt) { 'salt1' } + let(:id) { 'id1' } + let(:owncloud_config) { instance_double('OwncloudCookbook::Config') } + before do + allow(OwncloudCookbook::Config) + .to receive(:new).and_return(owncloud_config) + allow(owncloud_config) + .to receive(:[]).with('passwordsalt').and_return(salt) + allow(owncloud_config).to receive(:[]).with('instanceid').and_return(id) + end + + context 'in Chef Solo' do + before { Chef::Config[:solo] = true } + + it 'does not save the password salt' do + subject.save_owncloud_node_configuration + expect(node['owncloud']['config']['passwordsalt']).to_not eq(salt) + end + + it 'does not save the instance id' do + subject.save_owncloud_node_configuration + expect(node['owncloud']['config']['instanceid']).to_not eq(id) + end + end + + context 'in Chef Server' do + before { Chef::Config[:solo] = false } + + it 'saves the password salt' do + subject.save_owncloud_node_configuration + expect(node['owncloud']['config']['passwordsalt']).to eq(salt) + end + + it 'does not save the instance id' do + subject.save_owncloud_node_configuration + expect(node['owncloud']['config']['instanceid']).to eq(id) + end + end + end # context #save_owncloud_node_configuration + + context '#apply_owncloud_configuration' do + methods = %w( + calculate_trusted_domains + calculate_dbhost + owncloud_config_update + save_owncloud_node_configuration + ) + before do + methods.each do |meth| + allow(subject).to receive(meth).with(no_args) + end + end + after { subject.apply_owncloud_configuration } + + methods.each do |meth| + it "calls ##{meth} method" do + expect(subject).to receive(meth).with(no_args).once + end + end + end +end diff --git a/test/unit/support/fake_recipe.rb b/test/unit/support/fake_recipe.rb new file mode 100644 index 0000000..1d23c15 --- /dev/null +++ b/test/unit/support/fake_recipe.rb @@ -0,0 +1,35 @@ +# encoding: UTF-8 +# +# Author:: Xabier de Zuazo () +# Copyright:: Copyright (c) 2015 Xabier de Zuazo +# 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/node' +require 'cookbook_helpers' + +# Class to emulate the current recipe with some helpers. +class FakeRecipe < ::Chef::Node + include ::OwncloudCookbook::CookbookHelpers + + def initialize + super + name('node001') + node = self + Dir.glob("#{::File.dirname(__FILE__)}/../../../attributes/*.rb") do |f| + node.from_file(f) + end + end +end