-
Notifications
You must be signed in to change notification settings - Fork 18
Getting Started
gem install motherbrain
Configure:
mb configure
MotherBrain plugins are a part of a cookbook and are distributed in the same way cookbooks are distributed. To create a new motherbrain plugin:
cd $COOKBOOK_REPO
$EDITOR ./motherbrain.rb
This is the simplest possible plugin (and where we will start building our first plugin):
component "web_server"
Congrats! You've written your first Mother Brain plugin.
Run mb plugins
to see that the plugin is auto-loaded:
mb plugins
** listing local plugins...
first_app: 0.1.0
first_app
is named such because the cookbook the motherbrain.rb is a part of is named first_app
.
The existance of the plugin in the current directory automatically provides the mb my_app
sub command:
mb first_app
using first_app (0.1.0)
Tasks:
mb first_app help [COMMAND] # Describe subcommands or one specific subcommand
mb first_app nodes ENVIRONMENT # List all nodes grouped by Component and Group
mb first_app web_server [COMMAND] # server component commands
This is all great, but currently our plugin doesn't do anything, nor does it know what nodes it can talk to to orchestrate.
We can fix that by fleshing out our "server" component.
Defining Components
A component is any unit of your application that must be managed independently and serves as a way to identify which nodes are required to be modified by various actions, something we identified as lacking in the previous step. For instance, in a rails application, you might have components including nginx and unicorn or a service monitor such as bluepill or upstart.
We added the component web_server
to the plugin when we created it.
The next step is to tell Mother Brain how to identify nodes that contain this component:
component "web_server" do
+ description "Serves as a reverse proxy for the application process"
+ group "web_server" do
+ recipe "first_app::reverse_proxy"
+ end
+ end
In this case, we're identifying nodes via their run list, however you can also use roles or attributes or a combination of all three:
group "web_server" do
+ role "first_app_web_server"
end
group "database_master" do
+ chef_attribute "first_app.db_master", true
end
Now Mother Brain can identify nodes, time to do things with them:
The web server is a running service on the node, so tell Mother Brain that:
component "web_server" do
description "Serves as a reverse proxy for the application process"
group "web_server" do
recipe "first::reverse_proxy"
end
+ service "web_server" do
+ end
end
The web server service should be able to start, so add a start action:
component "web_server" do
description "Serves as a reverse proxy for the application process"
group "web_server" do
recipe "first::reverse_proxy"
end
service "first" do
+ action :start do
+ end
end
end
How you start your service is up to the specific requirements of the application, however often the logic for the service can be relegated to the cookbook in the component's node's runlist. In this case, we can set an attribute and let Chef take care of the rest in the recipes:
(While you're at it, create a stop action as well)
component "web_server" do
description "Serves as a reverse proxy for the application process"
group "web_server" do
recipe "first::reverse_proxy"
end
service "first" do
action :start do
+ node_attribute 'first_app.web_server.start', true
end
+ action :stop do
+ node_attribute 'first_app.web_server.start', false
+ end
end
end
Now create commands on the component to control this service so we can trigger starts and stops from the command line:
component "web_server" do
description "Serves as a reverse proxy for the application process"
group "web_server" do
recipe "first::reverse_proxy"
end
service "first" do
action :start do
node_attribute 'first_app.web_server.start', true
end
action :stop do
node_attribute 'first_app.web_server.start', false
end
end
+ command "start" do
+ description "Start the web server"
+ execute do
+ on("web_server") do
+ service("first").run(:start)
+ end
+ end
+ end
+ command "stop" do
+ description "Stop the web server"
+ execute do
+ on("web_server") do
+ service("first").run(:stop)
+ end
+ end
+ end
end
That's it, check it out:
# Note that the output here is bugged. See: https://github.com/RiotGames/motherbrain/issues/33
# This is the corrected output:
$ mb first_app web_server
Tasks:
mb first_app web_server help [COMMAND] # Describe subcommands or one specific subcommand
mb first_app web_server nodes ENVIRONMENT # List all nodes grouped by Group
mb first_app web_server start ENVIRONMENT # Start the web server
mb first_app web_server stop ENVIRONMENT # Start the web server
Now we can start and stop our web_server with the following commands:
$ mb first_app web_server start
$ mb first_app web_server stop
Nice!
Up next: