class Chef::ChefFS::Config
Helpers to take Chef::Config
and create chef_fs
and local_fs
(ChefFS
objects representing the server and local repository, respectively).
Constants
- CHEF_11_OSS_DYNAMIC_OBJECTS
- CHEF_11_OSS_STATIC_OBJECTS
ChefFS
supports three modes of operation: “static”, “everything”, and “hosted_everything”. These names are antiquated sinceChef
12 moved multi-tenant and RBAC to the open source product. In practice, they mean:-
static: just static objects that are included in a traditional chef-repo, with no support for anything introduced in
Chef
12 or later. -
everything: all of the objects supported by the open source
Chef
Server 11.x -
hosted_everything: (the name comes from Hosted
Chef
) supports everything inChef
Server 12 and later, including RBAC objects and Policyfile objects.
The “static” and “everything” modes are used for backup and upgrade/migration of older
Chef
Servers, so they should be considered frozen in time.-
- CHEF_12_OBJECTS
- EVERYTHING_MODE_OBJECT_NAMES
- HOSTED_EVERYTHING_MODE_OBJECT_NAMES
- INFLECTIONS
Not all of our object types pluralize by adding an ‘s’, so we map them out here:
- RBAC_OBJECT_NAMES
- STATIC_MODE_OBJECT_NAMES
Attributes
Public Class Methods
Create a new Config
object which can produce a chef_fs
and local_fs.
Arguments¶ ↑
chef_config
-
A hash that looks suspiciously like
Chef::Config
. These hash keys include:- :chef_repo_path
-
The root where all local chef object data is stored. Mirrors
Chef::Config.chef_repo_path
- :cookbook_path, node_path, …
-
Paths to cookbooks/, nodes/, data_bags/, etc. Mirrors
Chef::Config.cookbook_path
, etc. Defaults to +<chef_repo_path>/cookbooks+, etc. - :repo_mode
-
The directory format on disk. ‘everything’, ‘hosted_everything’ and ‘static’. Default: autodetected based on whether the URL has “/organizations/NAME.”
- :versioned_cookbooks
-
If true, the repository contains cookbooks with versions in their name (apache2-1.0.0). If false, the repository just has one version of each cookbook and the directory has the cookbook name (apache2). Default:
false
- :chef_server_url
-
The URL to the
Chef
server, e.g. api.opscode.com/organizations/foo. Used as the server for the remotechef_fs
, and to “guess” repo_mode if not specified. - :node_name
-
The username to authenticate to the
Chef
server with. - :client_key
-
The private key for the user for authentication
- :environment
-
The environment in which you are presently working
- :repo_mode
-
The repository mode, :hosted_everything, :everything or :static. This determines the set of subdirectories the
Chef
server will offer up. - :versioned_cookbooks
-
Whether or not to include versions in cookbook names
- cwd
-
The current working directory to base relative
Chef
paths from. Defaults toDir.pwd
. - options
-
A hash of other, not-suspiciously-like-chef-config options:
- :cookbook_version
-
When downloading cookbooks, download this cookbook version instead of the latest.
- ui
-
The object to print output to, with “output”, “warn” and “error” (looks a little like a Chef::Knife::UI object, obtainable from Chef::Knife.ui).
Example¶ ↑
require 'chef/chef_fs/config' config = Chef::ChefFS::Config.new config.chef_fs.child('cookbooks').children.each do |cookbook| puts "Cookbook on server: #{cookbook.name}" end config.local_fs.child('cookbooks').children.each do |cookbook| puts "Local cookbook: #{cookbook.name}" end
# File lib/chef/chef_fs/config.rb, line 142 def initialize(chef_config = Chef::Config, cwd = Dir.pwd, options = {}, ui = nil) @chef_config = chef_config @cwd = File.expand_path(cwd) @cookbook_version = options[:cookbook_version] if @chef_config[:repo_mode] == "everything" && is_hosted? && !ui.nil? ui.warn %Q{You have repo_mode set to 'everything', but your chef_server_url looks like it might be a hosted setup. If this is the case please use hosted_everything or allow repo_mode to default} end # Default to getting *everything* from the server. unless @chef_config[:repo_mode] if is_hosted? @chef_config[:repo_mode] = "hosted_everything" else @chef_config[:repo_mode] = "everything" end end end
Public Instance Methods
The current directory, relative to server root. This is a case-sensitive server path. It only exists if the current directory is a child of one of the recognized object_paths
below.
# File lib/chef/chef_fs/config.rb, line 239 def base_path @base_path ||= server_path(@cwd) end
# File lib/chef/chef_fs/config.rb, line 170 def chef_fs @chef_fs ||= create_chef_fs end
# File lib/chef/chef_fs/config.rb, line 174 def create_chef_fs require_relative "file_system/chef_server/chef_server_root_dir" Chef::ChefFS::FileSystem::ChefServer::ChefServerRootDir.new("remote", @chef_config, cookbook_version: @cookbook_version) end
# File lib/chef/chef_fs/config.rb, line 183 def create_local_fs require_relative "file_system/repository/chef_repository_file_system_root_dir" Chef::ChefFS::FileSystem::Repository::ChefRepositoryFileSystemRootDir.new(object_paths, Array(chef_config[:chef_repo_path]).flatten, @chef_config) end
Print the given server path, relative to the current directory
# File lib/chef/chef_fs/config.rb, line 244 def format_path(entry) server_path = entry.respond_to?(:display_path) ? entry.display_path : entry.path if base_path && server_path[0, base_path.length] == base_path if server_path == base_path return "." elsif server_path[base_path.length, 1] == "/" return server_path[base_path.length + 1, server_path.length - base_path.length - 1] elsif base_path == "/" && server_path[0, 1] == "/" return server_path[1, server_path.length - 1] end end server_path end
# File lib/chef/chef_fs/config.rb, line 166 def is_hosted? @chef_config[:chef_server_url] =~ %r{/+organizations/.+} end
# File lib/chef/chef_fs/config.rb, line 179 def local_fs @local_fs ||= create_local_fs end
Returns the given real path’s location relative to the server root.
If chef_repo is /home/jkeiser/chef_repo, and pwd is /home/jkeiser/chef_repo/cookbooks, server_path
(‘blah’) == ‘/cookbooks/blah’ server_path
(‘../roles/blah.json’) == ‘/roles/blah’ server_path
(‘../../readme.txt’) == nil server_path
(‘*/ab’) == ‘/cookbooks/*/ab’ server_path
(‘/home/jkeiser/chef_repo/cookbooks/blah’) == ‘/cookbooks/blah’ server_path
(‘/home/*/chef_repo/cookbooks/blah’) == nil
If there are multiple different, manually specified paths to object locations (cookbooks, roles, data bags, etc. can all have separate paths), and cwd+the path reaches into one of them, we will return a path relative to the first one to match it. Otherwise we expect the path provided to be to the chef repo path itself. Paths that are not available on the server are not supported.
Globs are allowed as well, but globs outside server paths are NOT (presently) supported. See above examples. TODO support that.
If the path does not reach into ANY specified directory, nil is returned.
# File lib/chef/chef_fs/config.rb, line 209 def server_path(file_path) target_path = Chef::ChefFS::PathUtils.realest_path(file_path, @cwd) # Check all object paths (cookbooks_dir, data_bags_dir, etc.) # These are either manually specified by the user or autogenerated relative # to chef_repo_path. object_paths.each_pair do |name, paths| paths.each do |path| object_abs_path = Chef::ChefFS::PathUtils.realest_path(path, @cwd) if relative_path = PathUtils.descendant_path(target_path, object_abs_path) return Chef::ChefFS::PathUtils.join("/#{name}", relative_path) end end end # Check chef_repo_path Array(@chef_config[:chef_repo_path]).flatten.each do |chef_repo_path| # We're using realest_path here but we really don't need to - we can just expand the # path and use realpath because a repo_path if provided *must* exist. realest_chef_repo_path = Chef::ChefFS::PathUtils.realest_path(chef_repo_path, @cwd) if Chef::ChefFS::PathUtils.os_path_eq?(target_path, realest_chef_repo_path) return "/" end end nil end
Private Instance Methods
# File lib/chef/chef_fs/config.rb, line 260 def object_paths @object_paths ||= begin result = {} case @chef_config[:repo_mode] when "static" object_names = STATIC_MODE_OBJECT_NAMES when "hosted_everything" object_names = HOSTED_EVERYTHING_MODE_OBJECT_NAMES else object_names = EVERYTHING_MODE_OBJECT_NAMES end object_names.each do |object_name| # cookbooks -> cookbook_path singular_name = INFLECTIONS[object_name] raise "Unknown object name #{object_name}" unless singular_name variable_name = "#{singular_name}_path" paths = Array(@chef_config[variable_name]).flatten result[object_name] = paths.map { |path| File.expand_path(path) } end result end end