Update our boxen template with the latest and greatest

This commit is contained in:
Will Farrington 2013-02-12 16:41:56 -08:00
parent 92dd6a9fdb
commit d4af4bf811
26 changed files with 245 additions and 40 deletions

View file

@ -1,7 +1,9 @@
source "http://rubygems.org"
source "https://rubygems.org"
gem "boxen", "~> 0.7"
gem "boxen", "0.7.3"
group :development do
gem "aws-sdk"
gem "net-ssh"
gem "rbvmomi"
end

View file

@ -1,5 +1,5 @@
GEM
remote: http://rubygems.org/
remote: https://rubygems.org/
specs:
addressable (2.3.2)
ansi (1.4.3)
@ -7,7 +7,7 @@ GEM
json (~> 1.4)
nokogiri (>= 1.4.4)
uuidtools (~> 2.1)
boxen (0.7.1)
boxen (0.7.3)
ansi (~> 1.4)
hiera (~> 1.0.0)
highline (~> 1.6)
@ -15,6 +15,7 @@ GEM
librarian-puppet (~> 0.9)
octokit (~> 1.15)
puppet (~> 3.0)
builder (3.1.4)
facter (1.6.17)
faraday (0.8.5)
multipart-post (~> 1.1)
@ -24,16 +25,17 @@ GEM
hiera (1.0.0)
highline (1.6.15)
json (1.7.6)
json_pure (1.7.6)
json_pure (1.7.7)
librarian-puppet (0.9.7)
json
puppet
thor (~> 0.15)
multi_json (1.5.0)
multi_json (1.6.0)
multipart-post (1.1.5)
net-ssh (2.6.5)
netrc (0.7.7)
nokogiri (1.5.6)
octokit (1.22.0)
octokit (1.23.0)
addressable (~> 2.2)
faraday (~> 0.8)
faraday_middleware (~> 0.9)
@ -43,7 +45,12 @@ GEM
puppet (3.1.0)
facter (~> 1.6)
hiera (~> 1.0)
rbvmomi (1.6.0)
builder
nokogiri (>= 1.4.1)
trollop
thor (0.17.0)
trollop (2.0)
uuidtools (2.1.3)
PLATFORMS
@ -51,4 +58,6 @@ PLATFORMS
DEPENDENCIES
aws-sdk
boxen (~> 0.7)
boxen (= 0.7.3)
net-ssh
rbvmomi

View file

@ -1,3 +1,5 @@
# This file manages Puppet module dependencies.
#
# It works a lot like Bundler. We provide some core modules by
# default. This ensures at least the ability to construct a basic
# environment.
@ -28,7 +30,7 @@ github "inifile", "0.9.0", :repo => "cprice-puppet/puppetlabs-inifile"
github "nginx", "0.2.1"
github "nodejs", "0.0.2"
github "nvm", "0.0.5"
github "ruby", "0.5.1"
github "ruby", "0.7.1"
github "stdlib", "3.0.0", :repo => "puppetlabs/puppetlabs-stdlib"
github "sudo", "0.0.1"

View file

@ -46,7 +46,7 @@ GITHUBTARBALL
GITHUBTARBALL
remote: boxen/puppet-ruby
specs:
ruby (0.5.1)
ruby (0.7.1)
GITHUBTARBALL
remote: boxen/puppet-sudo
@ -74,7 +74,7 @@ DEPENDENCIES
nginx (= 0.2.1)
nodejs (= 0.0.2)
nvm (= 0.0.5)
ruby (= 0.5.1)
ruby (= 0.7.1)
stdlib (= 3.0.0)
sudo (= 0.0.1)

View file

@ -7,9 +7,12 @@ per-user configurations.
How? The personal manifest.
## What even is a personal manifest?
Personal manifests live in `modules/people/manifests/<name>.pp`,
where `<name>` is your GitHub username.
A basic personal manifest might look like so:
The simplest personal manifest looks like this:
``` puppet
class people::wfarr {
@ -17,19 +20,46 @@ class people::wfarr {
}
```
Now, each time `wfarr` runs Boxen it'll automatically print out "hello world"
somewhere during the run.
You can even run `boxen-my-config` to generate a default template for you
and open it up in your editor.
When you're done, you can simply run `boxen` and it'll include your changes
in your personal manifest.
**You should always keep your manifest committed and pushed to your repository**.
Otherwise, auto-updates won't work!
Ah, the good old "Hello World".
It's boring, but you can see there's really not much boilerplate involved.
Let's try something *real* this time:
The whole point of these personal manifest are they are _your_ manifest.
You shouldn't worry if the things in here are work-related or not.
This is about full automation.
Want to install Minecraft and Rdio by default?
Do it in your personal manifest.
``` puppet
class people::wfarr {
include boxen::development
}
```
You can check out the [projects README](../modules/projects/README.md) for further examples.
So what does this do?
It clones every repo in the Boxen org to `~/src/boxen/<repo>`.
How?
Well, we can refer to [the source code](https://github.com/boxen/puppet-boxen/blob/master/manifests/development.pp)!
If you're new to Puppet, or are unsure of what that class is doing, check out
the [intro to puppet](./puppet.md) we've put together.
## Running different code on multiple machines
Puppet has conditionals and switching.
Typically, the most reliable way to ensure some code runs on one machine but not
others is to use the `case` statement on the `hostname` fact.
Example:
``` puppet
case $::hostname {
'scruffy': {
notify { "I'm Scruffy. The Janitor.": }
}
'bender': {
notify { "My full name is Bender Bending Rodriguez": }
}
default: {
notify { "Wha?": }
}
}
```
One thing to note here is that Puppet always **requires** a default path
on a case statement.
Default is equivalent to "anything that isn't matched above".

144
docs/puppet.md Normal file
View file

@ -0,0 +1,144 @@
# wtf is a puppet?
Puppet is configuration management tool, written in Ruby, that compiles
and runs code written in the Puppet language.
But what does that actually mean in words a human can understand?
Puppet is a tool that runs some code and that code can do all sorts of
really powerful things to configure computers for you.
Why do I want code mucking about with my laptop though?
For the exact same reasons you want code configuring your server.
In particular, homogeneity, reproducibility, reusability, and automation.
When you use code to express how a machine should be configured,
you know that all of your machines are configured the same way,
that you can repeat that configuration any number of times,
and that you don't have to do it manually each time.
## How does Puppet work?
A Puppet run has two main steps: compilation and application.
The compilations step starts with reading in what's called the site manifest.
The site manifest is a single file that contains Puppet code that is responsible
for telling the compiler what other Puppet code it should compile.
Here are the first few lines of the default site manifest for Boxen:
```
include boxen::environment
include homebrew
include gcc
```
This tells the Puppet compiler that it must include the classes
`boxen::environment`, `homebrew`, and `gcc`.
Puppet will look for those classes on the modulepath.
Typically, these files would be located at
`$modulepath/boxen/manifests/environment.pp` and
`$modulepath/homebrew/manifests/init.pp`.
These might include other classes as well, or define **resources**.
Resources are the building blocks of Puppet.
A resource is an abstract description about a **thing** and the **state**
that thing should be in.
Every resource has a **type**, which is just a classification of resources.
For example, we might have a resource `Package[mysql]` and its type would be
`Package`.
Puppet also supports multiple providers for types which act as pluggable
backends depending on the operating system it's running on or the tools
available on a particular system (in the case of the `Package` type,
we might have providers for `yum` and for `aptget`).
So now the Puppet compiler has finished tracking down and loading all the
classes and resources it needs.
Assuming we haven't encountered any compile-time errors, Puppet then begins
the next phase of a run: applying the catalog.
All of the resources Puppet has collected into the catalog have formed a
DAG (directed, acyclic graph) that represents the order in which all these
resources can be applied in a correct order.
Puppet simply grabs the first "node" in this graph and traverses all nodes
in the graph, applying each resource as it goes.
Application of an individual resource starts with Puppet asking "is this
resource in the state requested?" If the answer is yes, Puppet moves onto the
next node and repeats this process. If the answer is no, Puppet will make
whatever changes it can to reconcile the current state of the resource with
what it should be, and then continues on.
Once all resources have been applied, the Puppet run is complete.
## Declarative by nature
One of the most confusing parts of the Puppet language to many newcomers is
how the Puppet catalog orders and applies resources.
The key thing to remember is that Puppet is a **declarative** language rather
than a procedural one.
In human words, the only order that matters in Puppet is order specified by
relationships between resources.
Here's an example of how someone new to Puppet might write a class:
``` puppet
class mysql {
file { '/etc/my.cnf': source => 'puppet:///modules/mysql/my.cnf.erb' ; }
package { 'mysql': }
service { 'mysql': }
}
```
Someone expecting Puppet to be procedural would read this manifest as a list
saying:
* First create the my.cnf file
* Then install the mysql package
* Then start the mysql service
The problem is, they would be **wrong**.
There is no guarantee Puppet will apply these resources in that order,
and it's quite likely that it won't.
The proper way to ensure ordering in Puppet is to use one of the four
**relationship metaparameters**:
* before - Run this resource before another resource
* notify - Same as before, but triggers a refresh on that resource
* require - Run this resource after another resource
* subscribe - Same as require, but triggers a refresh on that resource
The behavior of these metaparameters should be pretty clear.
Triggering a resource simply means that a resource will "refresh" itself.
That typically means something like a `Service` resource restarting itself.
It's important to remember that these metaparameters are valid on **any** resource.
So, let's rewrite our example properly:
``` puppet
class mysql {
file { '/etc/my.cnf':
source => 'puppet:///modules/mysql/my.cnf.erb',
notify => Service['mysql']
}
package { 'mysql':
notify => Service['mysql']
}
service { 'mysql': }
}
```
Now we're telling Puppet what order to apply these resources in:
* Make sure /etc/my.cnf is in place before we start the mysql service
* If /etc/my.cnf changes, tell mysql to restart
* Make sure the mysql package is in place before we start the mysql service
* If the mysql package changes, tell mysql to restart
It's important to note that we didn't tell Puppet if `File[/etc/my.cnf]`
should come before or after `Package[mysql]`.
This is intentional.
Most package managers won't overwrite a configuration file that already exists
at package install-time, so in this case, we can assume installing the mysql
package won't clobber our custom `/etc/my.cnf` file.

View file

@ -18,11 +18,11 @@ class projects::rails_app {
include phantomjs
boxen::project { 'rails_app':
source => 'mycompany/rails_app',
ruby => '1.9.3',
mysql => true,
redis => true,
nginx => true,
source => 'username/rails_app'
}
}
```

View file

@ -1,5 +1,6 @@
require boxen::environment
require homebrew::repo
require homebrew
require gcc
Exec {
group => 'staff',
@ -8,6 +9,8 @@ Exec {
path => [
"${boxen::config::home}/rbenv/shims",
"${boxen::config::hime}/rbenv/bin",
"${boxen::config::hime}/rbenv/plugins/ruby-build/bin",
"${boxen::config::home}/homebrew/bin",
'/usr/bin',
'/bin',
@ -16,7 +19,7 @@ Exec {
],
environment => [
"HOMEBREW_CACHE=${homebrew::cachedir}",
"HOMEBREW_CACHE=${homebrew::config::cachedir}",
"HOME=/Users/${::luser}"
]
}
@ -43,6 +46,8 @@ Service {
provider => ghlaunchd
}
Homebrew::Formula <| |> -> Package <| |>
node default {
# core modules, needed for most things
include dnsmasq

View file

@ -13,10 +13,7 @@ set -e
rm -rf .bundle/config
rm -rf .librarian/puppet/config
# Export CC to explicitly set the compiler used for cexts.
export CC=gcc
# Bundle install unless we're already up to date.
export PATH=$(pwd)/vendor/shims:$PATH
bundle install --binstubs bin --path .bundle --quiet "$@"

View file

@ -19,6 +19,6 @@ unless File.exist? path
end
end
exec(editor, path) if editor && system("tty -s")
exec(editor, path) if editor && system("test -t 1")
puts path

View file

@ -14,11 +14,13 @@ services = false
OptionParser.new do |o|
o.banner = "Remove most traces of Boxen from your machine."
o.on("--all", "Remove everything possible.") { all = true }
o.on("--force", "Actually do it.") { force = true }
o.on("--help", "Show this help.") { abort o.to_s }
o.on("--opt", "Remove /opt/boxen.") { opt = true }
o.on("--services", "Remove and unload services.") { services = true }
o.on("--all", "Remove everything possible.") { all = true }
o.on("--force", "Actually do it.") { force = true }
o.on("--help", "Show this help.") { abort o.to_s }
o.on("--opt", "Remove /opt/boxen.") { opt = true }
o.on("--services", "Remove and unload services.") { services = true }
o.on("--receipts", "Remove package receipts used by Puppet.") { receipts = true }
o.on("--gitconfig", "Remove Boxen-provided git credential helper config.") { gitconfig = true }
o.parse!
@ -31,7 +33,7 @@ end
if all || services
boxen_services = []
boxen_services << Dir["/Library/Launch*/com.boxen.*.plist"]
boxen_services << Dir["/Library/Launch*/dev.*.plist"]
boxen_services.flatten.each do |plist|
warn "-> Removing #{plist}."
@ -49,3 +51,13 @@ if all || opt
warn "-> Removing /opt/boxen."
system "rm", "-rf", "/opt/boxen" if force
end
if all || receipts
warn "-> Removing /var/db/.puppet_*."
system "rm", "-rf", "/var/db/.puppet_*" if force
end
if all || gitconfig
warn "-> Removing git credential helper config."
system "/usr/bin/git", "config", "--global", "--unset", "credential.helper"
end

Binary file not shown.

BIN
vendor/cache/boxen-0.7.3.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/builder-3.1.4.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/json_pure-1.7.7.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/multi_json-1.6.0.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/net-ssh-2.6.5.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/octokit-1.23.0.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/rbvmomi-1.6.0.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/trollop-2.0.gem vendored Normal file

Binary file not shown.

Binary file not shown.

4
vendor/shims/xcrun vendored Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
# A noop xcrun for initial Boxen runs.
exec "$@"