A reliable Chef API client with a clean syntax
$ gem install ridley
Require Ridley into your application
require 'ridley'
ridley = Ridley.new(
server_url: "https://api.opscode.com/organizations/ridley",
client_name: "reset",
client_key: "/Users/reset/.chef/reset.pem"
)
Creating a new instance of Ridley requires the following options:
- server_url
- client_name
- client_key
Ridley exposes a number of functions that return resources which you can use to retrieve or create objects on your Chef server. Here is a simple example of getting a list of all the roles on your Chef server.
ridley = Ridley.new(...)
ridley.role.all #=> [
#<Ridley::RoleObject chef_id:motherbrain_srv ...>,
#<Ridley::RoleObject chef_id:motherbrain_proxy ...>
]
For more information scroll down to the Manipulating Chef Resources section of this README.
You can also tell Ridley to read the values from your Chef config (knife.rb):
ridley = Ridley.from_chef_config('/path/to/knife.rb')
ridley.role.all #=> [
#<Ridley::RoleObject chef_id:motherbrain_srv ...>,
#<Ridley::RoleObject chef_id:motherbrain_proxy ...>
]
The mapping between Chef Config values and Ridley values is:
Ridley | Chef |
---|---|
validator_client | validation_client_name |
validator_path | validation_key |
client_name | node_name |
server_url | chef_server_url |
Additionally, you can leave the path blank and Ridley will perform a "knife.rb search" the same way Chef does:
ridley = Ridley.from_chef_config
ridley.role.all #=> [
#<Ridley::RoleObject chef_id:motherbrain_srv ...>,
#<Ridley::RoleObject chef_id:motherbrain_proxy ...>
]
If you don't want to instantiate and manage a connection object you can use Ridley.open
to open a connection, do some work, and it will be closed for you after the block executes.
Ridley.open(server_url: "https://api.opscode.com", ...) do |r|
r.node.all
end
Resources are access by instance functions on a new instance of Ridley::Client.
ridley = Ridley.new(...)
ridley.client #=> Ridley::ClientResource
ridley.cookbook #=> Ridley::CookbookResource
ridley.data_bag #=> Ridley::DataBagResource
ridley.environment #=> Ridley::EnvironmentResource
ridley.node #=> Ridley::NodeResource
ridley.role #=> Ridley::RoleResource
ridley.sandbox #=> Ridley::SandboxResource
ridley.search #=> Ridley::SearchResource
DataBagItems are the only exception to this rule. The DataBagItem resource is accessed from a DataBagObject
data_bag = ridley.data_bag.find("my_data")
data_bag.item #=> Ridley::DataBagItemResource
data_bag.item.find("my_item") #=> Ridley::DataBagItemObject
Most resources can be listed, retrieved, created, updated, and destroyed. These are commonly referred to as CRUD (Create Read Update Delete) operations.
A new Chef Object can be created in a three ways
With the #create
function and an attribute hash
ridley = Ridley.new(...)
ridley.role.create(name: "reset") #=> #<Ridley::RoleObject: chef_id:reset>
With the #create
function and an instance of a Chef Object
obj = ridley.role.new
obj.name = "reset"
ridley.role.create(obj) #=> #<Ridley::RoleObject: chef_id:reset>
With the #save
function on an instance of a Chef Object
obj = ridley.role.new
obj.name = "reset"
obj.save #=> #<Ridley::RoleObject: chef_id:reset>
Each of these methods produce an identical object on the Chef server. It is up to you on how you'd like to create new resources.
Most resources have two read functions
#all
for listing all the Chef Objects#find
for retrieving a specific Chef Object
If you wanted to get a list of all of the roles on your Chef server
ridley = Ridley.new(...)
ridley.role.all #=> [
#<Ridley::RoleObject chef_id:motherbrain_srv ...>,
#<Ridley::RoleObject chef_id:motherbrain_proxy ...>
]
If you want to retrieve a single role from the Chef server
ridley = Ridley.new(...)
ridley.role.find("motherbrain_srv") #=> #<Ridley::RoleObject: chef_id:motherbrain_srv ...>
If the role does not exist on the Chef server then nil
is returned
ridley = Ridley.new(...)
ridley.role.find("not_there") #=> nil
Updating a resource can be expressed in three ways
With the #update
function, the ID of the Object to update, and an attributes hash
ridley = Ridley.new(...)
ridley.role.update("motherbrain_srv", description: "testing updates") #=>
#<Ridley::RoleObject chef_id:motherbrain_srv, description="testing updates" ...>
With the #update
function and an instance of a Chef Object
obj = ridley.role.find("motherbrain_srv")
obj.description = "chef object"
ridley.role.update(obj) #=> #<Ridley::RoleObject: chef_id:motherbrain_srv, description="chef object" ...
With the #save
function on an instance of a Chef Object
obj = ridley.role.find("reset")
obj.description = "saving an object"
obj.save #=> #<Ridley::RoleObject: chef_id:motherbrain_srv, description="saving an object" ...>
Destroying a resource can be express in three ways
With the #delete
function and the ID of the Object to destroy
ridley = Ridley.new(...)
ridley.role.delete("motherbrain_srv") => #<Ridley::RoleObject: chef_id:motherbrain_srv ...>
With the #delete
function and a Chef Object
obj = ridley.role.find("motherbrain_srv")
ridley.role.delete(obj) => #<Ridley::RoleObject: chef_id:motherbrain_srv ...>
With the #destroy
function on an instance of a Chef Object
obj = conn.role.find("motherbrain_srv")
obj.destroy #=> true
With the #regnerate_key
function and the ID of the Client to regenerate
ridley = Ridley.new(...)
ridley.client.regenerate_key("jamie") #=> #<Ridley::ClientObject: chef_id:"jamie", private_key="**HIDDEN***" ...>
With the #regenerate_key
function on an instance of a Client Object
obj = ridley.client.find("jamie")
obj.regenerate_key #=> #<Ridley::ClientObject: chef_id:"jamie", private_key="**HIDDEN***" ...>
A data bag is managed exactly the same as any other Chef resource
ridley = Ridley.new(...)
ridley.data_bag.create(name: "ridley-test")
You can create, delete, update, or retrieve a data bag exactly how you would expect if you read through the Manipulating Chef Resources portion of this document.
Unlike a role, node, client, or environment, a data bag is a container for other resources. These other resources are Data Bag Items. Data Bag Items behave slightly different than other resources. Data Bag Items can have an abritrary attribute hash filled with any key values that you would like. The one exception is that every Data Bag Item requires an 'id' key and value. This identifier is the name of the Data Bag Item.
ridley = Ridley.new(...)
data_bag = ridley.data_bag.create(name: "ridley-test")
data_bag.item.create(id: "appconfig", host: "reset.local", user: "jamie") #=>
#<Ridley::DataBagItemObject: chef_id:appconfig, host="reset.local", user="jamie">
Setting a default environment attribute is just like setting a node level default attribute
ridley = Ridley.new(...)
production_env = ridley.environment.find("production")
production_env.set_default_attribute("my_app.proxy.enabled", false)
production_env.save #=> true
And the same goes for setting an environment level override attribute
production_env.set_override_attribute("my_app.proxy.enabled", false)
production_env.save #=> true
ridley = Ridley.new(
server_url: "https://api.opscode.com",
organization: "vialstudios",
validator_client: "vialstudios-validator",
validator_path: "/Users/reset/.chef/vialstudios-validator.pem",
ssh: {
user: "vagrant",
password: "vagrant"
}
)
ridley.node.bootstrap("33.33.33.10", "33.33.33.11")
Windows Nodes are bootstrapped using a combination of WinRM, Batch, and PowerShell. You will probably need to tweak some settings on your Windows servers to ensure the commands are successful.
- Enable WinRM:
winrm quickconfig
and say Yes. - Set some WinRM settings to ensure that you don't get 401 Unauthorized responses and 500 Responses because of timeouts.
winrm set winrm/config/service/auth @{Basic="true"}
winrm set winrm/config/service @{AllowUnencrypted="true"}
winrm set winrm/config/service @{EnumerationTimeoutms="600000"}
winrm set winrm/config @{MaxTimeoutms="600000"}
winrm set winrm/config/client @{TrustedHosts="*"}
- You should also configure your PowerShell profile, so that PowerShell commands have a more lenient timeout period.
mkdir C:\Users\my_user\Documents\WindowsPowerShell
echo "$PSSessionOption = New-PSSessionOption -OpenTimeout 0 -CancelTimeout 0 -IdleTimeout 0 -OperationTimeout 0" > C:\Users\my_user\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
Verify the PowerShell settings by opening up the PowerShell Console and entering $PSSessionOption
and ensure those values are set, and that there are no errors output.
The following links offer some information about configuring a machine's PowerShell settings:
You may also want to tweak your Windows boxes a bit more ex: turning UAC off, turning off the Windows Firewall.
Setting role attributes is just like setting node and environment attributes
ridley = Ridley.new(...)
my_app_role = ridley.role.find("my_app")
my_app_role.set_default_attribute("my_app.proxy.enabled", false)
my_app_role.save #=> true
And the same goes for setting an environment level override attribute
my_app_role.set_override_attribute("my_app.proxy.enabled", false)
my_app_role.save #=> true
ridley = Ridley.new(...)
ridley.search(:node)
ridley.search(:node, "name:ridley-test.local")
Search will return an array of the appropriate Chef Objects if one of the default indices is specified. The indices are
- node
- role
- client
- environment
- Jamie Winsor ([email protected])
- Kyle Allan ([email protected])
Thank you to all of our Contributors, testers, and users.