├── .gitignore ├── .kitchen.yml ├── .rubocop.yml ├── .ruby-version ├── .travis.yml ├── Berksfile ├── Gemfile ├── LICENSE.md ├── README.md ├── Rakefile ├── Thorfile ├── files └── default │ ├── testing.tar │ └── testing.tgz ├── libraries └── matchers.rb ├── metadata.rb ├── providers └── x.rb ├── recipes ├── default.rb └── test.rb ├── resources └── x.rb ├── spec ├── spec_helper.rb └── test_spec.rb └── test └── integration ├── .rubocop.yml └── default └── serverspec └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .kitchen.local.yml 2 | .kitchen/ 3 | .rspec 4 | .vagrant 5 | Berksfile.lock 6 | Gemfile.lock 7 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | suites: 6 | - name: default 7 | run_list: 8 | - recipe[tarball::test] 9 | attributes: 10 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | Exclude: 3 | - 'Thorfile' 4 | - 'metadata.rb' 5 | 6 | FileName: 7 | Enabled: false 8 | 9 | AbcSize: 10 | Max: 40 11 | 12 | MethodLength: 13 | Max: 50 14 | 15 | Style/ClassAndModuleChildren: 16 | Enabled: false 17 | 18 | CyclomaticComplexity: 19 | Max: 12 20 | 21 | PerceivedComplexity: 22 | Max: 8 23 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.1.2 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.1.2 4 | script: 5 | - bundle exec rake style --trace 6 | - bundle exec rake spec --trace 7 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.getchef.com' 2 | 3 | metadata 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :test do 4 | # Berkshelf requirements 5 | gem 'berkshelf' 6 | gem 'thor' 7 | 8 | # Test kitchen requirements 9 | gem 'test-kitchen' 10 | gem 'kitchen-vagrant' 11 | gem 'serverspec' 12 | gem 'busser' 13 | gem 'busser-serverspec' 14 | 15 | # Chefspec 16 | gem 'chefspec' 17 | 18 | # Other required tests 19 | gem 'rubocop' 20 | gem 'foodcritic' 21 | end 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ooyala, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tarball 2 | ======= 3 | 4 | Description: tar file extraction resource provider. 5 | 6 | [![Build Status](https://travis-ci.org/ooyala/tarball-chef-cookbook.svg?branch=master)](https://travis-ci.org/ooyala/tarball-chef-cookbook) 7 | 8 | [Source on GitHub](https://github.com/ooyala/tarball-chef-cookbook) 9 | 10 | Features 11 | -------- 12 | * Does not rely on system tar (ruby only!) 13 | * Automatically handles gzipped archives 14 | * Can change mode/ownership 15 | * Can select specific files only 16 | * Can handle: 17 | * regular files 18 | * directories 19 | * symbolic links 20 | * hard links (provided the source file already exists; otherwise the 21 | hard link creation is skipped) 22 | 23 | Supported tar formats 24 | --------------------- 25 | * POSIX 26 | * Some GNU tar extensions (LONGNAME, LONGLINK) 27 | * Other tar formats will probably extract files without issue, but some 28 | metadata may not be handled as expected. If needed, please give a 29 | sample tar file and the tar program, version, and OS used to create 30 | archive, if possible, when requesting support. 31 | 32 | Limitations 33 | ----------- 34 | * Ignores FIFOs, block devices, etc. 35 | * Compressions other than zlib/gzip not currently supported 36 | * May or may not correctly handle non-standard blocksizes 37 | 38 | Recipes 39 | ------- 40 | * default.rb - to pull in resource provider for use in other cookbooks 41 | * test.rb - recipe to use for testing only 42 | 43 | Usage 44 | ----- 45 | ``` 46 | include_recipe 'tarball::default' 47 | 48 | # Fetch the tarball if it's not a local file 49 | remote_file '/tmp/some_archive.tgz' do 50 | source 'http://example.com/some_archive.tgz' 51 | end 52 | 53 | # I can also use tarball_x "file" do ... 54 | tarball '/tmp/some_archive.tgz' do 55 | destination '/opt/my_app_path' # Will be created if missing 56 | owner 'root' 57 | group 'root' 58 | extract_list [ '*.conf' ] 59 | umask 002 # Will be applied to perms in archive 60 | action :extract 61 | end 62 | ``` 63 | 64 | It will throw exceptions derived form StandardError in most cases 65 | (permissions errors, etc.), so you may want to wrap the block in a 66 | begin/rescue. 67 | 68 | ``` 69 | begin 70 | tarball '/tarball_path.tgz/' do 71 | ... 72 | end 73 | rescue StandardError => e 74 | log e.message 75 | ... 76 | end 77 | ``` 78 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | require 'rspec/core/rake_task' 15 | require 'rubocop/rake_task' 16 | require 'foodcritic' 17 | require 'kitchen' 18 | 19 | # Style tests. Rubocop and Foodcritic 20 | namespace :style do 21 | desc 'Run Ruby style checks' 22 | RuboCop::RakeTask.new(:ruby) 23 | 24 | desc 'Run Chef style checks' 25 | FoodCritic::Rake::LintTask.new(:chef) do |t| 26 | t.options = { 27 | fail_tags: ['any'], 28 | tags: ['~FC005'] 29 | } 30 | end 31 | end 32 | 33 | desc 'Run all style checks' 34 | task style: ['style:chef', 'style:ruby'] 35 | 36 | # Rspec and ChefSpec 37 | desc 'Run ChefSpec examples' 38 | RSpec::Core::RakeTask.new(:spec) do |r| 39 | r.pattern = 'spec/*_spec.rb' 40 | end 41 | 42 | # Integration tests. Kitchen.ci 43 | namespace :integration do 44 | desc 'Run Test Kitchen with Vagrant' 45 | task :vagrant do 46 | Kitchen.logger = Kitchen.default_file_logger 47 | Kitchen::Config.new.instances.each do |instance| 48 | instance.test(:always) 49 | end 50 | end 51 | end 52 | 53 | # Default 54 | task default: ['style', 'spec', 'integration:vagrant'] 55 | -------------------------------------------------------------------------------- /Thorfile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'bundler' 4 | require 'bundler/setup' 5 | require 'berkshelf/thor' 6 | 7 | begin 8 | require 'kitchen/thor_tasks' 9 | Kitchen::ThorTasks.new 10 | rescue LoadError 11 | puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] 12 | end 13 | -------------------------------------------------------------------------------- /files/default/testing.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ooyala/tarball-chef-cookbook/f83bed678bbde4997958d5de1093c65105a13118/files/default/testing.tar -------------------------------------------------------------------------------- /files/default/testing.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ooyala/tarball-chef-cookbook/f83bed678bbde4997958d5de1093c65105a13118/files/default/testing.tgz -------------------------------------------------------------------------------- /libraries/matchers.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | # Custom ChefSpec::Matchers for tarball LWRP 15 | 16 | if defined?(ChefSpec) 17 | def extract_tarball_x(name) 18 | ChefSpec::Matchers::ResourceMatcher.new(:tarball_x, :extract, name) 19 | end 20 | 21 | def extract_tarball(name) 22 | ChefSpec::Matchers::ResourceMatcher.new(:tarball, :extract, name) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'tarball' 2 | maintainer 'Ooyala' 3 | maintainer_email 'availability@ooyala.com' 4 | license 'All rights reserved' 5 | description 'tar resource provider' 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 7 | version '0.0.1' 8 | supports 'linux' # Add other platforms here if necessary 9 | -------------------------------------------------------------------------------- /providers/x.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | require 'zlib' 15 | require 'fileutils' 16 | require 'rubygems/package' 17 | 18 | def whyrun_supported? 19 | true 20 | end 21 | 22 | use_inline_resources 23 | 24 | def t_open(tarfile) 25 | ::File.open(tarfile, 'rb') 26 | rescue StandardError => e 27 | Chef::Log.warn e.message 28 | raise e 29 | end 30 | 31 | def t_stream(f) 32 | tgz = Zlib::GzipReader.new(f) 33 | rescue Zlib::GzipFile::Error 34 | # Not gzipped 35 | f.rewind 36 | f 37 | else 38 | tgz 39 | end 40 | 41 | def mkdestdir(tarball) 42 | directory tarball.destination do 43 | action :create 44 | owner tarball.owner 45 | group tarball.group 46 | # We use octal here for UNIX file mode readability, but we could just 47 | # as easily have used decimal 511 and gotten the correct behavior 48 | mode 0777 & ~tarball.umask.to_i 49 | recursive true 50 | tarball.updated_by_last_action(true) 51 | end 52 | end 53 | 54 | # Placeholder method in case someone actually needs PAX support 55 | def pax_handler(pax) 56 | Chef::Log.debug("PAX: #{pax}") if pax 57 | end 58 | 59 | def t_mkdir(tarball, entry, pax, name = nil) 60 | pax_handler(pax) 61 | if name.nil? 62 | dir = ::File.join(tarball.destination, entry.full_name).gsub(%r{/$}, '') 63 | else 64 | dir = name 65 | end 66 | directory dir do 67 | action :create 68 | owner tarball.owner || entry.header.uid 69 | group tarball.group || entry.header.gid 70 | mode { (fix_mode(entry.header.mode) | 0111) & ~tarball.umask.to_i } 71 | recursive true 72 | end 73 | end 74 | 75 | def get_target(tarball, entry, type) 76 | if type == :symbolic 77 | entry.header.linkname 78 | else 79 | ::File.join(tarball.destination, entry.header.linkname) 80 | end 81 | end 82 | 83 | def t_link(tarball, entry, type, pax, longname) 84 | pax_handler(pax) 85 | dir = tarball.destination 86 | t_mkdir(tarball, entry, pax, dir) unless ::File.exist?(dir) 87 | target = get_target(tarball, entry, type) 88 | 89 | if type == :hard && 90 | !(::File.exist?(target) || tarball.created_files.include?(target)) 91 | Chef::Log.debug "Skipping #{entry.full_name}: #{target} not found" 92 | return 93 | end 94 | 95 | src = ::File.join(dir, longname || entry.full_name) 96 | t_mkdir(tarball, entry, pax, ::File.dirname(src)) \ 97 | unless ::File.directory?(::File.dirname(src)) 98 | link src do 99 | to target 100 | owner tarball.owner || entry.header.uid 101 | link_type type 102 | action :create 103 | end 104 | end 105 | 106 | def t_file(tarball, entry, pax, longname) 107 | pax_handler(pax) 108 | file_name = longname || entry.full_name 109 | Chef::Log.info "Creating file #{file_name}" 110 | fqpn = ::File.join(tarball.destination, file_name) 111 | t_mkdir(tarball, entry, pax, ::File.dirname(fqpn)) \ 112 | unless ::File.directory?(::File.dirname(fqpn)) 113 | file fqpn do 114 | action :create 115 | owner tarball.owner || entry.header.uid 116 | group tarball.group || entry.header.gid 117 | mode fix_mode(entry.header.mode) & ~tarball.umask.to_i 118 | sensitive true 119 | content entry.read 120 | end 121 | tarball.created_files << fqpn 122 | end 123 | 124 | def on_list?(name, tarball) 125 | Array(tarball.extract_list).each do |r| 126 | return true if ::File.basename(name).match(Regexp.quote(r)) 127 | end 128 | false 129 | end 130 | 131 | def wanted?(name, tarball, type) 132 | if ::File.exist?(::File.join(tarball.destination, name)) && 133 | tarball.overwrite == false 134 | false 135 | elsif %w(2 5 L).include?(type) 136 | true 137 | elsif tarball.extract_list 138 | on_list?(name, tarball) 139 | else 140 | true 141 | end 142 | end 143 | 144 | def t_extraction(tar, tarball) 145 | # pax and longname track extended types that span more than one tar entry 146 | pax = nil 147 | longname = nil 148 | Gem::Package::TarReader.new(tar).each do |ent| 149 | next unless wanted?(ent.full_name, tarball, ent.header.typeflag) 150 | Chef::Log.info "Next tar entry: #{ent.full_name}" 151 | case ent.header.typeflag 152 | when '1' 153 | t_link(tarball, ent, :hard, pax, longname) 154 | pax = nil 155 | longname = nil 156 | when '2' 157 | t_link(tarball, ent, :symbolic, pax, longname) 158 | pax = nil 159 | longname = nil 160 | when '5' 161 | t_mkdir(tarball, ent, pax) 162 | pax = nil 163 | longname = nil 164 | when '3', '4', '6', '7' 165 | Chef::Log.debug "Can't handle type for #{ent.full_name}: skipping" 166 | pax = nil 167 | longname = nil 168 | when 'x', 'g' 169 | Chef::Log.debug 'PaxHeader' 170 | pax = ent 171 | longname = nil 172 | when 'L', 'K' 173 | longname = ent.read.strip 174 | Chef::Log.debug "Using LONG(NAME|LINK) #{longname}" 175 | pax = nil 176 | else 177 | t_file(tarball, ent, pax, longname) 178 | pax = nil 179 | longname = nil 180 | end 181 | end 182 | end 183 | 184 | def fix_mode(mode) 185 | # GNU tar doesn't store the mode POSIX style, so we fix it 186 | mode > 07777.to_i ? mode.to_s(8).slice(-4, 4).to_i(8) : mode 187 | end 188 | 189 | provides :tarball if self.respond_to?('provides') 190 | 191 | action :extract do 192 | tarball = new_resource 193 | Chef::Log.info "TARFILE: #{tarball.source || tarball.name}" 194 | tar = t_open(tarball.source || tarball.name) 195 | tar = t_stream(tar) 196 | mkdestdir(tarball) 197 | t_extraction(tar, tarball) 198 | new_resource.updated_by_last_action(true) 199 | end 200 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | # Intentionally empty 15 | -------------------------------------------------------------------------------- /recipes/test.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | include_recipe 'tarball::default' 15 | 16 | cookbook_file 'testing.tgz' do 17 | path '/tmp/testing.tgz' 18 | action :create 19 | end 20 | 21 | tarball '/tmp/testing.tgz' do 22 | destination '/tmp/testing1' 23 | owner 'root' 24 | group 'root' 25 | umask 002 26 | action :extract 27 | end 28 | 29 | file '/tmp/testing.tgz' do 30 | action :delete 31 | end 32 | 33 | file = 'testing.tar' 34 | 35 | cookbook_file 'testing.tar' do 36 | path "/tmp/#{file}" 37 | action :create 38 | end 39 | 40 | tarball_x 'test2' do 41 | source lazy { "/tmp/#{file}" } 42 | destination '/tmp/testing2' 43 | owner 'root' 44 | group 'sys' 45 | extract_list ['1', '/.*_to_.*/'] 46 | action :extract 47 | end 48 | 49 | file 'testing.tar' do 50 | path "/tmp/#{file}" 51 | action :delete 52 | end 53 | -------------------------------------------------------------------------------- /resources/x.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | actions :extract 15 | default_action :extract if defined?(default_action) 16 | 17 | provides :tarball if self.respond_to?('provides') 18 | 19 | def initialize(*args) 20 | super 21 | @created_files = created_files 22 | end 23 | 24 | attribute :name, kind_of: String, name_attribute: true 25 | attribute :source, kind_of: String 26 | attribute :destination, kind_of: String, required: true 27 | attribute :extract_list, kind_of: [Array, String] 28 | attribute :owner, kind_of: String 29 | attribute :group, kind_of: String 30 | attribute :umask, kind_of: [String, Integer], default: 022 31 | attribute :overwrite, kind_of: [TrueClass, FalseClass], default: true 32 | 33 | # This attribute is *not* meant to be passed as in the tarball_x block 34 | attribute :created_files, kind_of: Array, default: [] 35 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | require 'chefspec' 15 | require 'chefspec/berkshelf' 16 | 17 | RSpec.configure do |config| 18 | config.platform = 'ubuntu' 19 | config.version = '12.04' 20 | config.mock_with :rspec do |c| 21 | c.syntax = [:should, :expect] 22 | end 23 | end 24 | 25 | at_exit { ChefSpec::Coverage.report! } 26 | -------------------------------------------------------------------------------- /spec/test_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | require_relative 'spec_helper.rb' 15 | 16 | describe 'tarball::test' do 17 | let(:chef_run) do 18 | ChefSpec::SoloRunner.new.converge(described_recipe) 19 | end 20 | 21 | it 'creates /tmp/testing.tgz' do 22 | expect(chef_run).to create_cookbook_file('/tmp/testing.tgz') 23 | end 24 | 25 | it 'creates /tmp/testing.tar' do 26 | expect(chef_run).to create_cookbook_file('testing.tar') 27 | end 28 | 29 | it 'calls tarball' do 30 | expect(chef_run).to extract_tarball('/tmp/testing.tgz') 31 | end 32 | 33 | it 'calls tarball_x' do 34 | expect(chef_run).to extract_tarball_x('test2') 35 | end 36 | 37 | it 'removes /tmp/testing.tgz' do 38 | expect(chef_run).to delete_file('/tmp/testing.tgz') 39 | end 40 | 41 | it 'removes /tmp/testing.tar' do 42 | expect(chef_run).to \ 43 | delete_file('testing.tar').with(path: '/tmp/testing.tar') 44 | end 45 | end 46 | 47 | # Run again, stepping into LWRP 48 | describe 'tarball::test' do 49 | let(:chef_run) do 50 | ChefSpec::SoloRunner.new( 51 | log_level: :error, 52 | step_into: %w(tarball tarball_x) 53 | ).converge( 54 | described_recipe 55 | ) 56 | end 57 | 58 | before do 59 | allow(::File).to receive(:exists?).and_call_original 60 | allow(::File).to receive(:exists?).with('/tmp/testing.tgz').and_return true 61 | allow(::File).to receive(:exists?).with('/tmp/testing.tar').and_return true 62 | allow(::File).to receive(:open).and_call_original 63 | allow(::File).to receive(:open).with('/tmp/testing.tgz', 'rb').and_return \ 64 | ::File.open(::File.join(::File.dirname(__FILE__), 65 | '../files/default/testing.tgz'), 'rb') 66 | allow(::File).to receive(:open).with('/tmp/testing.tar', 'rb').and_return \ 67 | ::File.open(::File.join(::File.dirname(__FILE__), 68 | '../files/default/testing.tar'), 'rb') 69 | end 70 | 71 | it 'creates extraction dirs' do 72 | expect(chef_run).to create_directory('/tmp/testing1') 73 | expect(chef_run).to create_directory('/tmp/testing2') 74 | end 75 | 76 | it 'creates extracted files as expected' do 77 | %w( 78 | testing/a/2 79 | testing/a/b/1 80 | testing/e/h/3 81 | testing/e/h/4 82 | testing/e/h/5 83 | testing/e/h/6 84 | testing/e/h/i/j/k/l/m/n/o/p/q/r/3 85 | ).each do |f| 86 | expect(chef_run).to create_file("/tmp/testing1/#{f}") 87 | expect(chef_run).to create_file("/tmp/testing1/#{f}").with(mode: 0664) 88 | expect(chef_run).to create_file("/tmp/testing1/#{f}").with(owner: 'root') 89 | expect(chef_run).to create_file("/tmp/testing1/#{f}").with(group: 'root') 90 | end 91 | end 92 | 93 | it 'creates a bunch of directories' do 94 | %w( /tmp/testing1 /tmp/testing2 ).each do |t| 95 | %w( 96 | testing 97 | testing/a 98 | testing/a/b 99 | testing/a/b/c 100 | testing/a/b/d 101 | testing/e 102 | testing/e/f 103 | testing/e/g 104 | testing/e/h 105 | testing/e/h/i 106 | testing/e/h/i/j 107 | testing/e/h/i/j/k 108 | testing/e/h/i/j/k/l 109 | testing/e/h/i/j/k/l/m 110 | testing/e/h/i/j/k/l/m/n 111 | testing/e/h/i/j/k/l/m/n/o 112 | testing/e/h/i/j/k/l/m/n/o/p 113 | testing/e/h/i/j/k/l/m/n/o/p/q 114 | testing/e/h/i/j/k/l/m/n/o/p/q/r 115 | ).each do |d| 116 | expect(chef_run).to create_directory("#{t}/#{d}") 117 | end 118 | end 119 | end 120 | 121 | it 'creates another set of extracted files as expected' do 122 | %w( testing/a/b/1 ).each do |f| 123 | expect(chef_run).to create_file("/tmp/testing2/#{f}") 124 | expect(chef_run).to create_file("/tmp/testing2/#{f}").with(mode: 0644) 125 | expect(chef_run).to create_file("/tmp/testing2/#{f}").with(owner: 'root') 126 | expect(chef_run).to create_file("/tmp/testing2/#{f}").with(group: 'sys') 127 | end 128 | 129 | %w( 130 | testing/a/2 131 | testing/e/h/3 132 | testing/e/h/4 133 | testing/e/h/5 134 | testing/e/h/6 135 | testing/e/h/i/j/k/l/m/n/o/p/q/r/3 136 | ).each do |f| 137 | expect(chef_run).to_not create_file("/tmp/testing2/#{f}") 138 | end 139 | end 140 | 141 | it 'creates some symlinks' do 142 | %w( 143 | /tmp/testing1/testing/a/symlink_to_2 144 | /tmp/testing1/testing/a/symlink_to_3 145 | /tmp/testing2/testing/a/symlink_to_2 146 | /tmp/testing2/testing/a/symlink_to_3 147 | ).each do |l| 148 | expect(chef_run).to create_link(l) 149 | end 150 | end 151 | 152 | it 'creates some links' do 153 | %w( 154 | /tmp/testing1/testing/a/b/hardlink_to_1 155 | /tmp/testing2/testing/a/b/hardlink_to_1 156 | ).each do |l| 157 | expect(chef_run).to create_link(l).with_link_type(:hard) 158 | end 159 | end 160 | end 161 | -------------------------------------------------------------------------------- /test/integration/.rubocop.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | GlobalVars: 15 | AllowedVariables: [ $node ] 16 | -------------------------------------------------------------------------------- /test/integration/default/serverspec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ooyala, Inc. All rights reserved. 2 | # 3 | # This file is licensed under the MIT License (the "License"); 4 | # you may not use this file except in compliance with the 5 | # License. You may obtain a copy of the License at 6 | # http://opensource.org/licenses/MIT 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | require 'serverspec' 15 | require 'pathname' 16 | require 'json' 17 | 18 | include Serverspec::Helper::Exec 19 | include Serverspec::Helper::DetectOS 20 | 21 | RSpec.configure do |c| 22 | c.before :all do 23 | c.path = '/bin:/usr/bin:/sbin:/usr/sbin' 24 | end 25 | end 26 | 27 | # This file gets created by the test-helper recipe. Make sure it's at the 28 | # end of your run list! 29 | $node = ::JSON.parse(File.read('/tmp/serverspec/node.json')) 30 | --------------------------------------------------------------------------------