ponyup 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ /Rakefile
2
+ Berksfile.lock
3
+ dna.json
@@ -0,0 +1,62 @@
1
+ # Pony Up
2
+ A friendly DSL on top of [Rake][rake] to define and launch your cloud services.
3
+ Uses [Fog][fog] to talk to the cloud.
4
+
5
+ This is all for AWS right now.
6
+
7
+ # Philosophy
8
+ * Infrastructure as code
9
+ * Start with basic building blocks: security groups, hosts, etc
10
+ * Everything at a higher level can be done by chef
11
+ * Provide the transition from lower layer (fog) to apps (chef)
12
+
13
+ # Overview
14
+
15
+ ### ~/.fog
16
+
17
+ First, set up your ~/.fog file with credentials and defaults:
18
+
19
+ :production:
20
+ :aws_access_key_id: XXXXXXXXXXXXXXXXX
21
+ :aws_secret_access_key: XXXXXXXXXXXXXXXXXX
22
+ :region: us-east-1
23
+ :key_name: production
24
+ :image_id: ami-9b85eef2
25
+ :flavor_id: t1.micro
26
+
27
+ Your key_name field should have a matching ~/.ssh/{key_name}.pem file. If you
28
+ name the group in fog anything other than `default` you will need to use the
29
+ FOG_CREDENTIAL environment variable when running rake.
30
+
31
+
32
+ ### Rakefile
33
+
34
+ require_relative 'lib/ponyup'
35
+
36
+ security 'web', [80, 8080]
37
+
38
+ host 'appserver', 'web', 'recipe[appserver]'
39
+
40
+ task :default => :ponyup
41
+
42
+ ### Invocation
43
+
44
+ To set up your full set of hosts and security groups:
45
+
46
+ rake FOG_CREDENTIAL=production
47
+
48
+ To tear down your server:
49
+
50
+ rake host:appserver:destroy [FOG_CREDENTIAL=...]
51
+
52
+ To see all availabe tasks:
53
+
54
+ rake -D
55
+
56
+ # Examples
57
+
58
+ There are examples in the [exmaples/][examples] directory.
59
+
60
+ [fog]: http://fog.io/
61
+ [rake]: http://rake.rubyforge.org/
62
+ [examples]: http://github.com/xtoddx/ponyup/tree/master/examples
@@ -0,0 +1,6 @@
1
+ require_relative 'lib/ponyup'
2
+
3
+ security 'ssh', 22
4
+ secrity 'web', 80
5
+
6
+ host 'appserver', ['ssh', 'web']
@@ -0,0 +1,3 @@
1
+ site :opscode
2
+
3
+ cookbook 'chef-server'
@@ -0,0 +1,15 @@
1
+ # Ponyup Example: Chef Server
2
+
3
+ The first thing you probably want to do in the cloud is run a chef server that
4
+ all your instances launched in the future can connect to. This is that initail
5
+ step.
6
+
7
+ ### Requirements
8
+
9
+ * knife-solo, bootstraps the server node w/o an existing chef server
10
+ * berkshelf, for specifying cookbooks in a plaintext format
11
+
12
+ ### Running
13
+
14
+ rake [FOG_CREDENTIAL=staging]
15
+
@@ -0,0 +1,11 @@
1
+ require_relative '../../lib/ponyup'
2
+
3
+ # 22 lets us run `knife solo bootstrap ...`
4
+ # 443 is for the actual chef traffic.
5
+ security 'chef', [22, 443]
6
+
7
+ # The runlist is specified in dna.json, not here.
8
+ # This is a limitation of knife-solo.
9
+ host 'chefserver', 'chef', runlist='', knife_solo: true, attributes: 'dna.json'
10
+
11
+ task :default => :ponyup
@@ -0,0 +1 @@
1
+ {"chef-server": {"api_fqdn": "chef.us-east-1.mycloudhosting.com"} }
@@ -0,0 +1,191 @@
1
+ require 'fog'
2
+
3
+ Fog.credential = (ENV['FOG_CREDENTIAL'] || :staging).to_sym
4
+
5
+ # Define a security group.
6
+ #
7
+ # To define a group that allows public access:
8
+ #
9
+ # security 'vulnerable', [22, 80]
10
+ # security 'webish', 443
11
+ #
12
+ # To define an internal network accessible by instances on other groups:
13
+ #
14
+ # security 'shadows', [], vulnerable: [22]
15
+ # security 'shadows', nil, vulnerable: 22
16
+ #
17
+ # To define a group that allows both public and internal net traffic:
18
+ #
19
+ # security 'hybrid', 22, shadows: 8080
20
+ # security 'hybrid', [22, 80], shadows: 8080
21
+ #
22
+ def security name, public_ports=[], group_ports={}
23
+ security_namespace = SecurityRecord.define name, public_ports, group_ports
24
+ CloudRunner.add_component security_namespace
25
+ end
26
+
27
+ # Define a server.
28
+ #
29
+ # Options: key_name, image_id, size, knife_solo, attributes (filename)
30
+ #
31
+ def host name, security_groups, runlist, options={}
32
+ host_namespace = HostRecord.define name, security_groups, runlist, options
33
+ CloudRunner.add_component host_namespace
34
+ end
35
+
36
+ class CloudRunner # :nodoc:
37
+ extend Rake::DSL
38
+ def self.add_component namespace
39
+ task 'ponyup' => "#{namespace}:create"
40
+ task 'ponydown' => "#{namespace}:destroy"
41
+ end
42
+ end
43
+
44
+ class SecurityRecord # :nodoc:
45
+ extend Rake::DSL
46
+
47
+ # Return the namespace as string
48
+ def self.define name, public_ports, group_ports
49
+ namespace :security do
50
+ namespace name do
51
+ desc "Create #{name} security group"
52
+ task :create do
53
+ SecurityRecord.create name, public_ports, group_ports
54
+ end
55
+
56
+ desc "Delete #{name} security group"
57
+ task :destroy do
58
+ SecurityRecord.destroy name
59
+ end
60
+ end
61
+ end
62
+ "security:#{name}"
63
+ end
64
+
65
+ def self.create name, public_ports, group_ports
66
+ public_ports = Array(public_ports)
67
+ group = Fog::Compute[:aws].security_groups.get(name)
68
+ if group
69
+ delete_all_rules(group)
70
+ else
71
+ group = Fog::Compute[:aws].security_groups.new(name: name,
72
+ description: "Autmated Group #{name}")
73
+ group.save
74
+ end
75
+ unless public_ports.empty?
76
+ add_public_ports(group, public_ports)
77
+ end
78
+ unless group_ports.empty?
79
+ group_ports.each do |extern_group, ports|
80
+ ports = Array(ports)
81
+ add_group_ports(group, extern_group, ports)
82
+ end
83
+ end
84
+ end
85
+
86
+ def self.destroy name, ports
87
+ if group=Fog::Compute[:aws].security_groups.get(name)
88
+ group.delete
89
+ end
90
+ end
91
+
92
+ def self.add_public_ports group, ports
93
+ ports.each do |range|
94
+ range = range.respond_to?(:min) ? range : (range .. range)
95
+ group.authorize_port_range(range)
96
+ end
97
+ end
98
+
99
+ def self.add_group_ports group, other_name, ports
100
+ external_group = Fog::Compute[:aws].security_groups.get(other_name)
101
+ aws_spec = {external_group.owner_id => external_group.name}
102
+ ports.each do |port|
103
+ range = port.respond_to?(:min) ? port : (port .. port)
104
+ group.authorize_port_range range, group: aws_spec
105
+ end
106
+ end
107
+
108
+ def self.delete_all_rules group
109
+ group.ip_permissions.each do |perm|
110
+ ports = (perm['fromPort'] .. perm['toPort'])
111
+ if perm['groups'].any?
112
+ perm['groups'].each do |g|
113
+ group_spec = {g['userId'] => g['groupId']}
114
+ group.revoke_port_range(ports, group: group_spec)
115
+ end
116
+ else
117
+ group.revoke_port_range(ports)
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ class HostRecord # :nodoc:
124
+ extend Rake::DSL
125
+
126
+ def self.define name, security_groups, runlist=[], options={}
127
+ namespace :host do
128
+ namespace name do
129
+ desc "Launch #{name} in the cloud"
130
+ task :spinup do
131
+ HostRecord.launch name, security_groups, options
132
+ end
133
+
134
+ desc "Provision #{name} with chef"
135
+ task :provision do
136
+ HostRecord.provision name, runlist, options
137
+ end
138
+
139
+ desc "Create #{name} host"
140
+ task :create => [:spinup, :provision]
141
+
142
+ desc "Delete #{name} security group"
143
+ task :destroy do
144
+ HostRecord.destroy name
145
+ end
146
+ end
147
+ end
148
+ "host:#{name}"
149
+ end
150
+
151
+ def self.launch name, security_groups, options
152
+ if existing=get_instance(name)
153
+ existing.destroy
154
+ end
155
+ key = options[:key_name] || Fog.credentials[:key_name]
156
+ size = options[:size] || Fog.credentials[:size]
157
+ image = options[:image_id] || Fog.credentials[:image_id]
158
+ server = Fog::Compute[:aws].servers.create(groups: security_groups,
159
+ key_name: key,
160
+ flavor_id: size,
161
+ image_id: image,
162
+ tags: {'Name' => name})
163
+ Fog.wait_for { server.reload ; server.ready? }
164
+ end
165
+
166
+ def self.provision name, runlist, options
167
+ return if runlist.to_s.empty? && !options[:knife_solo]
168
+ instance = get_instance(name)
169
+ key_name = options[:key_name] || Fog.credentials[:key_name]
170
+ if options[:knife_solo]
171
+ system "knife solo bootstrap ubuntu@#{instance.dns_name} " +
172
+ "#{options[:attributes]} " +
173
+ "--identity-file ~/.ssh/#{key_name}.pem --node-name #{name}" +
174
+ "--run-list #{runlist}"
175
+ else
176
+ system "knife bootstrap #{instance.dns_name} " +
177
+ "--identity-file ~/.ssh/#{key_name}.pem --forward-agent " +
178
+ "--ssh-user ubuntu --sudo --node-name #{name} " +
179
+ "--run-list #{runlist}"
180
+ end
181
+ end
182
+
183
+ def self.destroy name
184
+ get_instance(name).destroy
185
+ end
186
+
187
+ def self.get_instance name
188
+ Fog::Compute[:aws].servers.all('tag:Name' => name,
189
+ 'instance-state-name' => 'running').first
190
+ end
191
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2
3
+ s.required_rubygems_version = Gem::Requirement.new('>= 0')
4
+
5
+ s.name = 'ponyup'
6
+ s.version = '0.0.2'
7
+ s.date = '2014-01-21'
8
+ s.summary = 'Manage virtual machines from cloud setup to chef provisioning'
9
+ s.description = 'Ponyup uses fog to manipulate clouds to get the them to the point you want use chef for provisioning, and then uses kinfe to bootstrap the nodes'
10
+ s.authors = ['xtoddx']
11
+ s.email = 'xtoddx@gmail.com'
12
+ s.homepage = 'http://github.com/xtoddx/ponyup'
13
+ s.license = 'MIT'
14
+ s.require_paths = %w[lib]
15
+ s.extra_rdoc_files = %w[README.md]
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {spec,tests}/*`.split("\n")
19
+
20
+ s.add_dependency('fog', '>= 1.19.0')
21
+ #s.add_dependency('chef', '>= 11.8.2')
22
+ #s.add_dependency('knife-solo', '>= 0.4.1')
23
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ponyup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - xtoddx
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.19.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.19.0
30
+ description: Ponyup uses fog to manipulate clouds to get the them to the point you
31
+ want use chef for provisioning, and then uses kinfe to bootstrap the nodes
32
+ email: xtoddx@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files:
36
+ - README.md
37
+ files:
38
+ - .gitignore
39
+ - README.md
40
+ - Rakefile.sample
41
+ - examples/chefserver/Berksfile
42
+ - examples/chefserver/README.md
43
+ - examples/chefserver/Rakefile
44
+ - examples/chefserver/dna.json.example
45
+ - lib/ponyup.rb
46
+ - ponyup.gemspec
47
+ homepage: http://github.com/xtoddx/ponyup
48
+ licenses:
49
+ - MIT
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.25
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: Manage virtual machines from cloud setup to chef provisioning
72
+ test_files: []
73
+ has_rdoc: