ponyup 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: