capistrano-puppeteer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,12 +2,42 @@
2
2
 
3
3
  Some useful capistrano tasks for standalone puppet masterless puppet deployments.
4
4
 
5
+ # Usage
6
+
7
+ ## Launching Amazon Instances
8
+
9
+ Populate ```config/deploy.rb``` with the following attributes
10
+
11
+ ``` ruby
12
+ require 'capistrano/puppeteer/aws'
13
+
14
+ set :cloud_provider, 'AWS'
15
+ set :aws_secret_access_key, 'X...'
16
+ set :aws_access_key_id, 'A...'
17
+ set :aws_region, 'us-west-2'
18
+ set :aws_availability_zone, 'us-west-2a'
19
+ set :aws_ami, 'ami-20800c10' # Precise 64bit http://cloud.ubuntu.com/ami/
20
+ set :aws_key_name, 'default'
21
+ set :aws_iam_role, 'backups' # Optional
22
+ ```
23
+
24
+ ## Bootstrapping an instance
25
+
26
+ Populate ```config/deploy.rb``` with the following attributes
27
+
28
+ ``` ruby
29
+ set :bootstrap_domain, 'example.com'
30
+ set :bootstrap_user, 'johnf'
31
+ set :ssh_key, 'config/aws.pem'
32
+ set :puppet_repo, 'git@github.com:johnf/puppet.git'
33
+ ```
34
+
5
35
  # Installation
6
36
 
7
37
  Add this line to your application's Gemfile:
8
38
 
9
39
  ``` ruby
10
- gem 'puppeteer'
40
+ gem 'capistrano-puppeteer'
11
41
  ```
12
42
 
13
43
  And then execute:
@@ -19,7 +49,7 @@ $ bundle
19
49
  Or install it yourself as:
20
50
 
21
51
  ``` bash
22
- $ gem install puppeteer
52
+ $ gem install capistrano-puppeteer
23
53
  ```
24
54
 
25
55
  Then add it to your _config/deploy.rb_
@@ -28,6 +58,15 @@ Then add it to your _config/deploy.rb_
28
58
  require 'capistrano/puppeteer'
29
59
  ```
30
60
 
61
+ # Configuration
62
+
63
+ Your puppet.conf requires at minimum
64
+
65
+ ``` ini
66
+ [main]
67
+ confdir = .
68
+ ```
69
+
31
70
  ## Usage
32
71
 
33
72
  TODO: Write usage instructions here
@@ -16,4 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Capistrano::Puppeteer::VERSION
17
17
 
18
18
  gem.add_dependency 'capistrano'
19
+ gem.add_dependency 'fog', '>= 1.9.0'
20
+
21
+ gem.add_development_dependency 'rake'
19
22
  end
@@ -1,32 +1,5 @@
1
- require 'puppeteer/version'
1
+ require 'capistrano/puppeteer/version'
2
2
  require 'capistrano'
3
3
 
4
- module Capistrano
5
-
6
- class Puppeteer
7
- def self.extended(configuration)
8
- configuration.load do
9
- _cset(:puppet_path) { abort "Please specify the path to puppet, set :puppet_path, '/srv/puppet'" }
10
-
11
- namespace :puppet do
12
- task :update do
13
- run_locally 'git push'
14
- run "cd #{puppet_path} && git pull --quiet"
15
- end
16
-
17
- desc 'Perform a puppet run'
18
- task :go do
19
- update
20
- options = ENV['options'] || ENV['OPTIONS'] || ''
21
- run "cd #{puppet_path} && #{sudo} puppet apply --configfile puppet.conf manifests/site.pp #{options}"
22
- end
23
- end
24
-
25
- end
26
- end
27
- end
28
- end
29
-
30
- if Capistrano::Configuration.instance
31
- Capistrano::Configuration.instance.extend Capistrano::Puppeteer
32
- end
4
+ require 'capistrano/puppeteer/puppet'
5
+ require 'capistrano/puppeteer/bootstrap'
@@ -0,0 +1,188 @@
1
+ require 'fog'
2
+
3
+ module Capistrano
4
+ module Puppeteer
5
+ module AWS
6
+ FLAVOURS = {
7
+ 't1.micro' => {:ram => 0.6, :io => 'low', :compute => 2, :price => 0.02},
8
+
9
+ 'm1.small' => {:ram => 1.7, :io => 'moderate', :compute => 1, :price => 0.08},
10
+ 'm1.medium' => {:ram => 3.75, :io => 'moderate', :compute => 2, :price => 0.16},
11
+ 'm1.large' => {:ram => 7.5, :io => 'high', :compute => 4, :price => 0.32},
12
+ 'm1.xlarge' => {:ram => 15, :io => 'high', :compute => 8, :price => 0.64},
13
+
14
+ 'm2.xlarge' => {:ram => 17.1, :io => 'moderate', :compute => 6.5, :price => 0.45},
15
+ 'm2.2xlarge' => {:ram => 34.2, :io => 'high', :compute => 13, :price => 0.90},
16
+ 'm2.4xlarge' => {:ram => 68.4, :io => 'high', :compute => 26, :price => 1.80},
17
+
18
+ 'c1.medium' => {:ram => 1.7, :io => 'moderate', :compute => 5, :price => 0.165},
19
+ 'c1.xlarge' => {:ram => 7, :io => 'high', :compute => 20, :price => 0.66},
20
+
21
+ 'cc1.4xlarge' => {:ram => 23, :io => 'v.high', :compute => 33.5, :price => 1.30},
22
+ 'cc1.8xlarge' => {:ram => 60.5, :io => 'v.high', :compute => 88 , :price => 2.40},
23
+
24
+ 'cg1.4xlarge' => {:ram => 22, :io => 'v.high', :compute => 33.5, :price => 2.10},
25
+ }
26
+
27
+ def self.extended(configuration)
28
+ configuration.load do
29
+ set(:cloud_provider) { abort "Please specify a cloud provider, set :cloud_provider, 'AWS'" } unless exists? :cloud_provider
30
+ set(:aws_ami) { abort "Please specify a AWS AMI, set :aws_ami, 'ami-a29943cb'" } unless exists? :aws_ami
31
+ set(:aws_secret_access_key) { abort "Please specify an AWS Access Key, set :aws_secret_access_key, 'XXXX'" } unless exists? :aws_secret_access_key
32
+ set(:aws_access_key_id) { abort "Please specify a AWS AMI, set :aws_access_key_id, 'ZZZ'" } unless exists? :aws_access_key_id
33
+ set(:aws_region) { abort "Please specify a AWS AMI, set :aws_region, 'us-west-1'" } unless exists? :aws_availability_zone
34
+ set(:aws_availability_zone) { abort "Please specify a AWS AMI, set :aws_availability_zone, 'us-west-1a'" } unless exists? :aws_availability_zone
35
+ set(:aws_key_name) { abort "Please specify a AWS AMI, set :aws_key_name, 'default'" } unless exists? :aws_key_name
36
+ set(:aws_ssh_key) { abort "Please specify a AWS AMI, set :aws_ssh_key, 'config/aws.pem'" } unless exists? :aws_ssh_key
37
+
38
+ namespace :aws do
39
+
40
+ desc <<-DESC
41
+ create an AWS instance.
42
+
43
+ cap aws:create [OPTIONS]
44
+
45
+ Available options:
46
+
47
+ flavour (required) - The type of EC2 instance to create
48
+ name (required) - The name of the instance, this will be used as the AWS tag
49
+ iam_role - An IAM role to apply to the instance
50
+
51
+ DESC
52
+ task :create do
53
+ flavour = ENV['flavour'] || abort('please specify a flavour')
54
+ name = ENV['name'] || abort('please specify name')
55
+ iam_role = ENV['iam_role']
56
+
57
+ puts "Creating Instance..."
58
+ instance_options = {
59
+ :image_id => aws_ami,
60
+ :availability_zone => aws_availability_zone,
61
+ :flavor_id => flavour,
62
+ :key_name => aws_key_name,
63
+ :tags => { 'Name' => name },
64
+ }
65
+
66
+ instance_options[:iam_instance_profile_name] = iam_role if iam_role
67
+
68
+ server = servers.create instance_options
69
+ server.wait_for { ready? }
70
+ server.reload
71
+ ENV['HOSTS'] = server.public_ip_address
72
+ end
73
+
74
+
75
+ desc 'List Instance types'
76
+ task :flavours do
77
+ puts "%-11s %-11s %-7s %-5s %s" % %w[Name Price/Month RAM Units IO]
78
+ Capistrano::Puppeteer::AWS::FLAVOURS.each do |flavor, opts|
79
+ puts "%-11s $ %7.2f %4.1f GB %4.1f %s" % [flavor, opts[:price] * 720, opts[:ram], opts[:compute], opts[:io]]
80
+ end
81
+ end
82
+
83
+ desc 'List current AWS instances'
84
+ task :list do
85
+ format = '%-15s %-10s %-8s %-10s %-43s %-15s %-10s %-s %s'
86
+ puts format % %w{Name ID State Zone DNS IP Type CreatedAt ImageID}
87
+ servers.sort {|a,b| (a.tags['Name'] || 'Unknown') <=> (b.tags['Name'] || 'Unknown') }.each do |server|
88
+ puts format % [server.tags['Name'], server.id, server.state, server.availability_zone, server.dns_name, server.private_ip_address, server.flavor_id, server.created_at, server.image_id]
89
+ end
90
+ end
91
+
92
+ desc 'Describe an instance'
93
+ desc <<-DESC
94
+ Describe an AWS instance.
95
+
96
+ cap aws:show instance_id=...
97
+
98
+ DESC
99
+ task :show do
100
+ instance_id = ENV['instance_id'] || abort('provide an instance_id')
101
+ server = servers.get instance_id
102
+ p server
103
+ end
104
+
105
+ desc <<-DESC
106
+ Start an AWS instance.
107
+
108
+ cap aws:start instance_id=...
109
+
110
+ DESC
111
+ task :start do
112
+ instance_id = ENV['instance_id'] || abort('provide an instance_id')
113
+
114
+ server = servers.get instance_id
115
+ server.start
116
+ end
117
+
118
+ desc <<-DESC
119
+ Stop an AWS instance.
120
+
121
+ cap aws:stop instance_id=...
122
+
123
+ Options:
124
+ force=true - Forces a stop for a hung instance
125
+
126
+ DESC
127
+ task :stop do
128
+ instance_id = ENV['instance_id'] || abort('provide an instance_id')
129
+ force = ENV['force'] =~ /^true$/i
130
+
131
+ server = servers.get instance_id
132
+ server.stop force
133
+ end
134
+
135
+ desc <<-DESC
136
+ Destroy an AWS instance.
137
+
138
+ cap aws:destroy instance_id=...
139
+
140
+ DESC
141
+ task :destroy do
142
+ instance_id = ENV['instance_id'] || abort('provide an instance_id')
143
+
144
+ server = servers.get instance_id
145
+ server.destroy
146
+ end
147
+
148
+ desc <<-DESC
149
+ Reboot an AWS instance.
150
+
151
+ cap aws:reboot instance_id=...
152
+
153
+ Options:
154
+ force=true - Forces a stop for a hung instance
155
+
156
+ DESC
157
+ task :reboot do
158
+ instance_id = ENV['instance_id'] || abort('provide an instance_id')
159
+ force = ENV['force'] =~ /^true$/i
160
+
161
+ server = servers.get instance_id
162
+ server.reboot force
163
+ end
164
+
165
+ def compute
166
+ @compute ||= Fog::Compute.new(
167
+ :provider => cloud_provider,
168
+ :region => aws_region,
169
+ :aws_secret_access_key => aws_secret_access_key,
170
+ :aws_access_key_id => aws_access_key_id,
171
+ )
172
+ end
173
+
174
+ def servers
175
+ @servers ||= compute.servers
176
+ end
177
+
178
+ end
179
+
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ if Capistrano::Configuration.instance
187
+ Capistrano::Configuration.instance.extend Capistrano::Puppeteer::AWS
188
+ end
@@ -0,0 +1,138 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ module Capistrano
5
+ module Puppeteer
6
+ module Bootstrap
7
+
8
+ def self.extended(configuration)
9
+ configuration.load do
10
+ set(:bootstrap_domain) { abort "Please specify a domain, set :bootstrap_domain, 'inodes.org'" } unless exists? :bootstrap_domain
11
+ set(:bootstrap_user) { abort "Please specify a user, set :bootstrap_user, 'johnf'" } unless exists? :bootstrap_domain
12
+ set(:puppet_path) { abort "Please specify the path to puppet, set :puppet_path, '/srv/puppet'" } unless exists? :puppet_path
13
+ set(:puppet_repo) { abort "Please specify the path to puppet, set :puppet_repo, 'git@...'" } unless exists? :puppet_repo
14
+
15
+ namespace :bootstrap do
16
+
17
+ desc 'Create and bootstrap the server'
18
+ task :create do
19
+ puts "NOTE: Add host to puppet first and git push"
20
+ puts
21
+ sleep 5
22
+
23
+ name = ENV['name'] or abort('please supply a name')
24
+ ENV['fqdn'] ||= "#{name}.#{bootstrap_domain}"
25
+ aws.create
26
+ unless wait_for_ssh
27
+ abort "Timed out waiting for SSH to come up on #{ENV['HOSTS']}"
28
+ end
29
+ bootstrap.go
30
+ end
31
+
32
+ def wait_for_ssh
33
+ 60.times do
34
+ begin
35
+ Timeout::timeout(1) do
36
+ s = TCPSocket.new(ENV['HOSTS'], 22)
37
+ s.close
38
+ return true
39
+ end
40
+ rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
41
+ end
42
+ end
43
+
44
+ return false
45
+ end
46
+
47
+ desc 'Bootstrap the server with puppet'
48
+ task :go do
49
+ if exists? :ssh_key
50
+ system "ssh-add #{ssh_key}"
51
+ end
52
+ hostname
53
+ github
54
+ upgrade
55
+ puppet_setup
56
+ unless ENV['skip_puppet']
57
+ puppet_ubuntu if exists?(:cloud_provider) && cloud_provider == 'AWS'
58
+ puppet.go
59
+ end
60
+ end
61
+
62
+ task :hostname do
63
+ set :user, 'ubuntu' if exists?(:cloud_provider) && cloud_provider == 'AWS'
64
+ fqdn = ENV['fqdn'] || Capistrano::CLI.ui.ask('What is the full fqdn for the host')
65
+ hostname = fqdn.split('.')[0]
66
+
67
+ run "#{sudo} sudo sed -i -e '/127.0.0.1/a127.0.1.1 #{fqdn} #{hostname}' /etc/hosts"
68
+ run "echo #{hostname} | #{sudo} tee /etc/hostname > /dev/null"
69
+ run "#{sudo} sed -itmp -e 's/\\(domain\\|search\\).*/\\1 #{bootstrap_domain}/' /etc/resolv.conf"
70
+ run "#{sudo} service hostname start"
71
+ end
72
+
73
+ task :github do
74
+ set :user, 'ubuntu' if exists?(:cloud_provider) && cloud_provider == 'AWS'
75
+ run "mkdir -p .ssh"
76
+ run "echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> .ssh/known_hosts"
77
+ end
78
+
79
+ task :upgrade do
80
+ set :user, 'ubuntu' if exists?(:cloud_provider) && cloud_provider == 'AWS'
81
+
82
+ run "#{sudo} apt-get -y update"
83
+ run "DEBIAN_FRONTEND=noninteractive #{sudo} -E apt-get -y dist-upgrade"
84
+ end
85
+
86
+ def remote_file_exists?(full_path)
87
+ 'true' == capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip
88
+ end
89
+
90
+ task :puppet_setup do
91
+ set :user, 'ubuntu' if exists?(:cloud_provider) && cloud_provider == 'AWS'
92
+
93
+ release = capture 'lsb_release --codename --short | tr -d "\n"'
94
+ fail "unable to determine distro release" if release.empty?
95
+
96
+ # add puppetlabs apt repos
97
+ unless remote_file_exists? puppet_path
98
+ filename = '/etc/apt/sources.list.d/puppetlabs.list'
99
+ run "echo 'deb http://apt.puppetlabs.com/ #{release} main' | #{sudo} tee #{filename}"
100
+ end
101
+ run "#{sudo} apt-key adv --keyserver keyserver.ubuntu.com --recv 4BD6EC30"
102
+ run "#{sudo} apt-get -yq update"
103
+ run "#{sudo} apt-get install -y puppet libaugeas-ruby git"
104
+
105
+ unless remote_file_exists? puppet_path
106
+ run "git clone #{puppet_repo} /tmp/puppet"
107
+ run "#{sudo} mv /tmp/puppet #{puppet_path}"
108
+ end
109
+
110
+ run "#{sudo} mkdir -p /home/#{bootstrap_user}/.ssh"
111
+ run "#{sudo} echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' | #{sudo} tee /home/#{bootstrap_user}/.ssh/known_hosts"
112
+ end
113
+
114
+ task :puppet_ubuntu do
115
+ set :user, 'ubuntu'
116
+
117
+ run 'cd /srv/puppet && git pull'
118
+
119
+ puppet.go
120
+ end
121
+
122
+ task :reboot do
123
+ set :user, ENV['USER']
124
+
125
+ run "#{sudo} reboot"
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ if Capistrano::Configuration.instance
137
+ Capistrano::Configuration.instance.extend Capistrano::Puppeteer::Bootstrap
138
+ end
@@ -0,0 +1,40 @@
1
+ module Capistrano
2
+ module Puppeteer
3
+ module Puppet
4
+
5
+ def self.extended(configuration)
6
+ configuration.load do
7
+ unless exists? :puppet_path
8
+ set(:puppet_path) { '/srv/puppet' } unless exists? :puppet_path
9
+ end
10
+
11
+ namespace :puppet do
12
+ task :update do
13
+ system 'git push'
14
+ run "#{sudo} chgrp -R adm #{puppet_path}"
15
+ run "#{sudo} chmod -R g+rw #{puppet_path}"
16
+ run "cd #{puppet_path} && git pull --quiet"
17
+ end
18
+
19
+ desc <<-DESC
20
+ Perform a puppet run.
21
+
22
+ Pass options to puppt using OPTIONS
23
+
24
+ puppet:go options="--noop"
25
+ DESC
26
+ task :go do
27
+ update
28
+ options = ENV['options'] || ENV['OPTIONS'] || ''
29
+ run "cd #{puppet_path} && #{sudo} puppet apply --config puppet.conf --verbose #{options} manifests/site.pp"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ if Capistrano::Configuration.instance
39
+ Capistrano::Configuration.instance.extend Capistrano::Puppeteer::Puppet
40
+ end
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
- class Puppeteer
3
- VERSION = "0.0.1"
2
+ module Puppeteer
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-puppeteer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-15 00:00:00.000000000 Z
12
+ date: 2013-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
@@ -27,6 +27,38 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: fog
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.9.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.9.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
30
62
  description: Some useful capistrano tasks for standalone puppet masterless puppet
31
63
  deployments.
32
64
  email:
@@ -42,6 +74,9 @@ files:
42
74
  - Rakefile
43
75
  - capistrano-puppeteer.gemspec
44
76
  - lib/capistrano/puppeteer.rb
77
+ - lib/capistrano/puppeteer/aws.rb
78
+ - lib/capistrano/puppeteer/bootstrap.rb
79
+ - lib/capistrano/puppeteer/puppet.rb
45
80
  - lib/capistrano/puppeteer/version.rb
46
81
  homepage: https://github.com/johnf/capistrano-puppeteer
47
82
  licenses: []
@@ -55,12 +90,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
90
  - - ! '>='
56
91
  - !ruby/object:Gem::Version
57
92
  version: '0'
93
+ segments:
94
+ - 0
95
+ hash: -2726431899788713285
58
96
  required_rubygems_version: !ruby/object:Gem::Requirement
59
97
  none: false
60
98
  requirements:
61
99
  - - ! '>='
62
100
  - !ruby/object:Gem::Version
63
101
  version: '0'
102
+ segments:
103
+ - 0
104
+ hash: -2726431899788713285
64
105
  requirements: []
65
106
  rubyforge_project:
66
107
  rubygems_version: 1.8.23
@@ -68,4 +109,3 @@ signing_key:
68
109
  specification_version: 3
69
110
  summary: Capistrano tasks for puppet
70
111
  test_files: []
71
- has_rdoc: