diff options
Diffstat (limited to 'lib/chef/knife/core/object_loader.rb')
-rw-r--r-- | lib/chef/knife/core/object_loader.rb | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/lib/chef/knife/core/object_loader.rb b/lib/chef/knife/core/object_loader.rb new file mode 100644 index 0000000000..1d207c10d1 --- /dev/null +++ b/lib/chef/knife/core/object_loader.rb @@ -0,0 +1,112 @@ +# +# Author:: Daniel DeLeo (<dan@opscode.com>) +# Copyright:: Copyright (c) 2011 Opscode, 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. +# + +class Chef + class Knife + module Core + class ObjectLoader + + attr_reader :ui + attr_reader :klass + + class ObjectType + FILE = 1 + FOLDER = 2 + end + + def initialize(klass, ui) + @klass = klass + @ui = ui + end + + def load_from(repo_location, *components) + unless object_file = find_file(repo_location, *components) + ui.error "Could not find or open file '#{components.last}' in current directory or in '#{repo_location}/#{components.join('/')}'" + exit 1 + end + object_from_file(object_file) + end + + # When someone makes this awesome, please update the above error message. + def find_file(repo_location, *components) + if file_exists_and_is_readable?(File.expand_path( components.last )) + File.expand_path( components.last ) + else + relative_path = File.join(Dir.pwd, repo_location, *components) + if file_exists_and_is_readable?(relative_path) + relative_path + else + nil + end + end + end + + # Find all objects in the given location + # If the object type is File it will look for all *.{json,rb} + # files, otherwise it will lookup for folders only (useful for + # data_bags) + # + # @param [String] path - base look up location + # + # @return [Array<String>] basenames of the found objects + # + # @api public + def find_all_objects(path) + path = File.join(path, '*') + path << '.{json,rb}' + objects = Dir.glob(File.expand_path(path)) + objects.map { |o| File.basename(o) } + end + + def find_all_object_dirs(path) + path = File.join(path, '*') + objects = Dir.glob(File.expand_path(path)) + objects.delete_if { |o| !File.directory?(o) } + objects.map { |o| File.basename(o) } + end + + def object_from_file(filename) + case filename + when /\.(js|json)$/ + r = Yajl::Parser.parse(IO.read(filename)) + + # Chef::DataBagItem doesn't work well with the json_create method + if @klass == Chef::DataBagItem + r + else + @klass.json_create(r) + end + when /\.rb$/ + r = klass.new + r.from_file(filename) + r + else + ui.fatal("File must end in .js, .json, or .rb") + exit 30 + end + end + + def file_exists_and_is_readable?(file) + File.exists?(file) && File.readable?(file) + end + + end + end + end +end + |