summaryrefslogtreecommitdiff
path: root/lib/chef/knife/core/object_loader.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/knife/core/object_loader.rb')
-rw-r--r--lib/chef/knife/core/object_loader.rb112
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
+