Proc.new do
desc "edit an object in your EDITOR"
explain(<<-E)
## SUMMARY ##
+edit(object)+ allows you to edit any object that can be converted to JSON.
When finished editing, this method will return the edited object:
new_node = edit(existing_node)
## EDITOR SELECTION ##
Shef looks for an editor using the following logic
1. Looks for an EDITOR set by Shef.editor = "EDITOR"
2. Looks for an EDITOR configured in your shef config file
3. Uses the value of the EDITOR environment variable
E
def edit(object)
unless Shef.editor
puts "Please set your editor with Shef.editor = \"vim|emacs|mate|ed\""
return :failburger
end
filename = "shef-edit-#{object.class.name}-"
if object.respond_to?(:name)
filename += object.name
elsif object.respond_to?(:id)
filename += object.id
end
edited_data = Tempfile.open([filename, ".js"]) do |tempfile|
tempfile.sync = true
tempfile.puts object.to_json
system("#{Shef.editor.to_s} #{tempfile.path}")
tempfile.rewind
tempfile.read
end
JSON.parse(edited_data)
end
desc "Find and edit API clients"
explain(<<-E)
## SUMMARY ##
+clients+ allows you to query you chef server for information about your api
clients.
## LIST ALL CLIENTS ##
To see all clients on the system, use
clients.all #=> [<Chef::ApiClient...>, ...]
If the output from all is too verbose, or you're only interested in a specific
value from each of the objects, you can give a code block to +all+:
clients.all { |client| client.name } #=> [CLIENT1_NAME, CLIENT2_NAME, ...]
## SHOW ONE CLIENT ##
To see a specific client, use
clients.show(CLIENT_NAME)
## SEARCH FOR CLIENTS ##
You can also search for clients using +find+ or +search+. You can use the
familiar string search syntax:
clients.search("KEY:VALUE")
Just as the +all+ subcommand, the +search+ subcommand can use a code block to
filter or transform the information returned from the search:
clients.search("KEY:VALUE") { |c| c.name }
You can also use a Hash based syntax, multiple search conditions will be
joined with AND.
clients.find :KEY => :VALUE, :KEY2 => :VALUE2, ...
## BULK-EDIT CLIENTS ##
**BE CAREFUL, THIS IS DESTRUCTIVE**
You can bulk edit API Clients using the +transform+ subcommand, which requires
a code block. Each client will be saved after the code block is run. If the
code block returns +nil+ or +false+, that client will be skipped:
clients.transform("*:*") do |client|
if client.name =~ /borat/i
client.admin(false)
true
else
nil
end
end
This will strip the admin privileges from any client named after borat.
E
subcommands :all => "list all api clients",
:show => "load an api client by name",
:search => "search for API clients",
:transform => "edit all api clients via a code block and save them"
def clients
@clients ||= Shef::ModelWrapper.new(Chef::ApiClient, :client)
end
desc "Find and edit cookbooks"
subcommands :all => "list all cookbooks",
:show => "load a cookbook by name",
:transform => "edit all cookbooks via a code block and save them"
def cookbooks
@cookbooks ||= Shef::ModelWrapper.new(Chef::CookbookVersion)
end
desc "Find and edit nodes via the API"
explain(<<-E)
## SUMMARY ##
+nodes+ Allows you to query your chef server for information about your nodes.
## LIST ALL NODES ##
You can list all nodes using +all+ or +list+
nodes.all #=> [<Chef::Node...>, <Chef::Node...>, ...]
To limit the information returned for each node, pass a code block to the +all+
subcommand:
nodes.all { |node| node.name } #=> [NODE1_NAME, NODE2_NAME, ...]
## SHOW ONE NODE ##
You can show the data for a single node using the +show+ subcommand:
nodes.show("NODE_NAME") => <Chef::Node @name="NODE_NAME" ...>
## SEARCH FOR NODES ##
You can search for nodes using the +search+ or +find+ subcommands:
nodes.find(:name => "app*") #=> [<Chef::Node @name="app1.example.com" ...>, ...]
Similarly to +all+, you can pass a code block to limit or transform the
information returned:
nodes.find(:name => "app#") { |node| node.ec2 }
## BULK EDIT NODES ##
**BE CAREFUL, THIS OPERATION IS DESTRUCTIVE**
Bulk edit nodes by passing a code block to the +transform+ or +bulk_edit+
subcommand. The block will be applied to each matching node, and then the node
will be saved. If the block returns +nil+ or +false+, that node will be
skipped.
nodes.transform do |node|
if node.fqdn =~ /.*\\.preprod\\.example\\.com/
node.set[:environment] = "preprod"
end
end
This will assign the attribute to every node with a FQDN matching the regex.
E
subcommands :all => "list all nodes",
:show => "load a node by name",
:search => "search for nodes",
:transform => "edit all nodes via a code block and save them"
def nodes
@nodes ||= Shef::ModelWrapper.new(Chef::Node)
end
desc "Find and edit roles via the API"
explain(<<-E)
## SUMMARY ##
+roles+ allows you to query and edit roles on your Chef server.
## SUBCOMMANDS ##
* all (list)
* show (load)
* search (find)
* transform (bulk_edit)
## SEE ALSO ##
See the help for +nodes+ for more information about the subcommands.
E
subcommands :all => "list all roles",
:show => "load a role by name",
:search => "search for roles",
:transform => "edit all roles via a code block and save them"
def roles
@roles ||= Shef::ModelWrapper.new(Chef::Role)
end
desc "Find and edit +databag_name+ via the api"
explain(<<-E)
## SUMMARY ##
+databags(DATABAG_NAME)+ allows you to query and edit data bag items on your
Chef server. Unlike other commands for working with data on the server,
+databags+ requires the databag name as an argument, for example:
databags(:users).all
## SUBCOMMANDS ##
* all (list)
* show (load)
* search (find)
* transform (bulk_edit)
## SEE ALSO ##
See the help for +nodes+ for more information about the subcommands.
E
subcommands :all => "list all items in the data bag",
:show => "load a data bag item by id",
:search => "search for items in the data bag",
:transform => "edit all items via a code block and save them"
def databags(databag_name)
@named_databags_wrappers ||= {}
@named_databags_wrappers[databag_name] ||= Shef::NamedDataBagWrapper.new(databag_name)
end
desc "A REST Client configured to authenticate with the API"
def api
@rest = Shef::ShefREST.new(Chef::Config[:chef_server_url])
end
end