ey-flex-test 0.3.3

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Engine Yard Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ == ey
2
+
3
+ A gem that provides...
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+
6
+ GEM = "ey-flex-test"
7
+ GEM_VERSION = "0.3.3"
8
+ AUTHOR = "Ezra Zygmuntowicz"
9
+ EMAIL = "awsmdev@engineyard.com"
10
+ HOMEPAGE = "http://engineyard.com/solo"
11
+ SUMMARY = "Command line interface to Engine Yard's cloud"
12
+
13
+ spec = Gem::Specification.new do |s|
14
+ s.name = GEM
15
+ s.version = GEM_VERSION
16
+ s.platform = Gem::Platform::RUBY
17
+ s.has_rdoc = true
18
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE", 'TODO']
19
+ s.summary = SUMMARY
20
+ s.description = s.summary
21
+ s.author = AUTHOR
22
+ s.email = EMAIL
23
+ s.homepage = HOMEPAGE
24
+ s.bindir = "bin"
25
+ s.executables = %w( ey-slave ey-recipes eybackup ey-snapshots ey-monitor ey-agent)
26
+ # Uncomment this to add a dependency
27
+ # s.add_dependency "foo"
28
+
29
+ s.require_path = 'lib'
30
+ s.autorequire = GEM
31
+ s.files = %w(LICENSE README.rdoc Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
32
+ end
33
+
34
+ Rake::GemPackageTask.new(spec) do |pkg|
35
+ pkg.gem_spec = spec
36
+ end
37
+
38
+ desc "install the gem locally"
39
+ task :install => [:package] do
40
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
41
+ end
42
+
43
+ desc "create a gemspec file"
44
+ task :make_spec do
45
+ File.open("#{GEM}.gemspec", "w") do |file|
46
+ file.puts spec.to_ruby
47
+ end
48
+ end
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ TODO:
2
+ Fix LICENSE with your name
3
+ Fix Rakefile with your name and contact info
4
+ Add your code to lib/<%= name %>.rb
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'big-brother'
4
+
5
+ json = JSON.parse(IO.read('/etc/chef/dna.json'))
6
+
7
+
8
+ # {'skip':[
9
+ # 'mysqld'
10
+ # ],
11
+ # 'check':[
12
+ # 'ttsrv'
13
+ # ]}
14
+
15
+ skips = JSON.parse(IO.read('/etc/ey-alerts.json')) rescue {}
16
+
17
+ puts EY::BigBrother.new(json.merge(skips)).check
@@ -0,0 +1,10 @@
1
+
2
+ require 'rubygems'
3
+ require 'yaml'
4
+ require 'stonith'
5
+
6
+ EventMachine.run {
7
+ opts = YAML::load(IO.read("/etc/.mysql.backups.yml"))
8
+ opts.merge!(YAML::load(IO.read("/etc/.ey-cloud.yml")))
9
+ EY::Stonith.new(opts.merge(:heartbeat => 10))
10
+ }
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'yaml'
4
+ require "optparse"
5
+ require "json"
6
+ require 'ey'
7
+
8
+ defaults = {:config => '~/.ey-cloud.yml',
9
+ :command => :get_envs,
10
+ :type => 'recipes',
11
+ :keep => 5}
12
+ options = {}
13
+ # Build a parser for the command line arguments
14
+ opts = OptionParser.new do |opts|
15
+ opts.version = "0.0.1"
16
+
17
+ opts.banner = "Usage: ey-recipes [-flag] [argument]"
18
+ opts.define_head "ey-recipes: managing your recipes..."
19
+ opts.separator '*'*80
20
+
21
+ opts.on("-l", "--list-recipes ENV", "List recipes for ENV") do |env|
22
+ options[:env] = env
23
+ options[:command] = :list
24
+ end
25
+
26
+ opts.on("-j", "--json ENV", "Get The DNA JSON for ENV") do |env|
27
+ options[:env] = env
28
+ options[:command] = :get_json
29
+ end
30
+
31
+ opts.on("-q", "--quick", "Run only the recipes required for a quick redeploy") do
32
+ options[:quick] = true
33
+ end
34
+
35
+ opts.on("-c", "--config CONFIG", "Use config file.") do |config|
36
+ options[:config] = config
37
+ end
38
+
39
+ opts.on("-r", "--rollback ENV", "Roll back to the previous recipe set for ENV and run them on your instances.") do |env|
40
+ options[:env] = env
41
+ options[:command] = :rollback
42
+ end
43
+
44
+ opts.on("-d", "--deploy ENV", "Upload a new recipe set and run them on your instances. Be sure to commit your changes to your git repo before deploying as we create a git archive of HEAD.") do |env|
45
+ options[:command] = :deploy
46
+ options[:identifier] = 'recipes'
47
+ options[:env] = env
48
+ end
49
+
50
+ opts.on("-u", "--upload ENV", "Upload a new recipe set so s3 but don't run it. Be sure to commit your changes to your git repo before deploying as we create a git archive of HEAD.") do |env|
51
+ options[:command] = :upload
52
+ options[:identifier] = 'recipes'
53
+ options[:env] = env
54
+ end
55
+
56
+ opts.on("--clear ENV", "Clear out any customer recipes attached to ENV") do |env|
57
+ options[:command] = :clear
58
+ options[:identifier] = 'recipes'
59
+ options[:env] = env
60
+ end
61
+
62
+ opts.on("--deploy-main ENV", "Redeploy the main EY recipe set and run it on your environment ENV") do |env|
63
+ options[:command] = :deploy_main
64
+ options[:env] = env
65
+ end
66
+
67
+ opts.on("-n", "--newest ENV", "download, install and run the current custom recipe set for ENV (THIS COMMAND CAN ONLY BE RUN ON YOUR EC2 INSTANCE)") do |env|
68
+ options[:command] = :converge
69
+ options[:identifier] = 'recipes'
70
+ options[:env] = env
71
+ end
72
+
73
+ opts.on("--view-log ENV", "view the last custom chef recipe run log file for ENV") do |env|
74
+ options[:command] = :view_logs
75
+ options[:env] = env
76
+ end
77
+
78
+ opts.on("--view-main-log ENV", "view the last main ey recipe run log file for ENV") do |env|
79
+ options[:command] = :view_logs
80
+ options[:env] = env
81
+ options[:main] = true
82
+ end
83
+
84
+ opts.on("--main ENV", "download, install and run the main ey recipe set for ENV (THIS COMMAND CAN ONLY BE RUN ON YOUR EC2 INSTANCE)") do |env|
85
+ options[:command] = :converge
86
+ options[:env] = env
87
+ options[:main] = true
88
+ options[:recipeloc] = "/etc/chef/recipes"
89
+ end
90
+
91
+ opts.on("--logs", "set the type to logs") do
92
+ options[:type] = 'logs'
93
+ options[:extension] = 'gz'
94
+ end
95
+
96
+ end
97
+
98
+ opts.parse!
99
+
100
+ ey = nil
101
+ if File.exist?(config = File.expand_path(options[:config] || defaults[:config]))
102
+ ey = EY::ChefRecipes.new(options = defaults.merge(YAML::load(IO.read(config))).merge(options))
103
+ elsif File.exist?(config = "/etc/.ey-cloud.yml")
104
+ ey = EY::ChefRecipes.new(options = defaults.merge(YAML::load(IO.read(config))).merge(options))
105
+ else
106
+ puts"You need to have an ~/.ey-cloud.yml file with your credentials in it to use this tool.\nOr point it at a yaml file with -c path/to/ey-cloud.yml"
107
+ exit 1
108
+ end
109
+
110
+ case options[:command]
111
+ when :list
112
+ ey.list true
113
+ when :rollback
114
+ ey.rollback
115
+ when :deploy
116
+ ey.deploy
117
+ when :get_json
118
+ jj ey.get_json
119
+ when :deploy_main
120
+ ey.deploy_main
121
+ when :view_logs
122
+ ey.view_logs
123
+ when :clear
124
+ ey.clear_bucket
125
+ when :upload
126
+ ey.upload_recipes
127
+ when :get_envs
128
+ envs = ey.get_envs
129
+ puts "Current Environments:"
130
+ envs.each {|k,v| puts "env: #{k} running instances: #{v['instances']}\n instance_ids: #{v['instance_ids'].inspect}" }
131
+ when :converge
132
+ ey.converge
133
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'mysql_slave'
4
+
5
+ puts "Adding this node as a mysql slave/replicant read only database"
6
+
7
+ EY::MysqlSlave.new.bootstrap
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'yaml'
4
+ require "optparse"
5
+ require "json"
6
+ require 'snapshot_minder'
7
+
8
+ defaults = {:config => '/etc/.mysql.backups.yml',
9
+ :command => :list_snapshots,
10
+ :keep => 5}
11
+
12
+ options = {}
13
+ # Build a parser for the command line arguments
14
+ opts = OptionParser.new do |opts|
15
+ opts.version = "0.0.1"
16
+
17
+ opts.banner = "Usage: ey-snapshots [-flag] [argument]"
18
+ opts.define_head "ey-snapshots: managing your snapshots..."
19
+ opts.separator '*'*80
20
+
21
+ opts.on("-l", "--list-snapshots", "list snapshots") do
22
+ options[:command] = :list_snapshots
23
+ end
24
+
25
+ opts.on("-c", "--config CONFIG", "Use config file.") do |config|
26
+ options[:config] = config
27
+ end
28
+
29
+ opts.on("-i", "--instance-id ID", "specify the instance id to work with(only needed if you are running this from ourside of ec2)") do |iid|
30
+ options[:instance_id] = iid
31
+ end
32
+
33
+
34
+ opts.on("--snapshot", "take snapshots of both of your volumes(only runs on your ec2 instance)") do
35
+ options[:command] = :snapshot_volumes
36
+ end
37
+
38
+
39
+ end
40
+
41
+ opts.parse!
42
+
43
+ ey = nil
44
+ if File.exist?(config = File.expand_path(defaults[:config]))
45
+ ey = EY::SnapshotMinder.new(options = defaults.merge(YAML::load(IO.read(config))).merge(options))
46
+ else
47
+ puts"You need to have an /etc/.mysql.backups.yml file with your credentials in it to use this tool.\nOr point it at a yaml file with -c .mysql.backups.yml"
48
+ exit 1
49
+ end
50
+
51
+ ey.send(options[:command])
52
+ ey.clean_snapshots(options[:keep])
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'yaml'
4
+ require "optparse"
5
+ require 'mysql_backup'
6
+ require 'postgresql_backup'
7
+
8
+ options = {:config => '/etc/.mysql.backups.yml',
9
+ :command => :new_backup}
10
+
11
+ # Build a parser for the command line arguments
12
+ opts = OptionParser.new do |opts|
13
+ opts.version = "0.0.1"
14
+
15
+ opts.banner = "Usage: eybackup [-flag] [argument]"
16
+ opts.define_head "eybackup: backing up your shit since way back when..."
17
+ opts.separator '*'*80
18
+
19
+ opts.on("-l", "--list-backup DATABASE", "List mysql backups for DATABASE") do |db|
20
+ options[:db] = (db || 'all')
21
+ options[:command] = :list
22
+ end
23
+
24
+ opts.on("-n", "--new-backup", "Create new mysql backup") do
25
+ options[:command] = :new_backup
26
+ end
27
+
28
+ opts.on("-c", "--config CONFIG", "Use config file.") do |config|
29
+ options[:config] = config
30
+ end
31
+
32
+ opts.on("-d", "--download BACKUP_INDEX", "download the backup specified by index. Run eybackup -l to get the index.") do |index|
33
+ options[:command] = :download
34
+ options[:index] = index
35
+ end
36
+
37
+ opts.on("-e", "--engine DATABASE_ENGINE", "The database engine. ex: mysql, postgres.") do |engine|
38
+ options[:engine] = engine || 'mysql'
39
+ options[:config] ||= '/etc/.#{options[:engine]}.backups.yml'
40
+ end
41
+
42
+ opts.on("-r", "--restore BACKUP_INDEX", "Download and apply the backup specified by index WARNING! will overwrite the current db with the backup. Run eybackup -l to get the index.") do |index|
43
+ options[:command] = :restore
44
+ options[:index] = index
45
+ end
46
+
47
+ end
48
+
49
+ opts.parse!
50
+
51
+ eyb = nil
52
+ if File.exist?(options[:config])
53
+ eyb = case options[:engine]
54
+ when 'postgres' then EyBackup::PostgresqlBackup.new(YAML::load(IO.read(options[:config])))
55
+ when 'mysql', NilClass then EyBackup::MysqlBackup.new(YAML::load(IO.read(options[:config])))
56
+ else raise "Invalid engine: #{options[:engine]}"
57
+ end
58
+ end
59
+
60
+ case options[:command]
61
+ when :list
62
+ eyb.list options[:db], true
63
+ when :new_backup
64
+ eyb.new_backup
65
+ when :download
66
+ eyb.download(options[:index])
67
+ when :restore
68
+ eyb.restore(options[:index])
69
+ end
70
+ eyb.cleanup
@@ -0,0 +1,66 @@
1
+ require 'dbi'
2
+ module EY
3
+ class BigBrother
4
+ def initialize(dna)
5
+ @dna = dna
6
+ @result = {}
7
+ end
8
+
9
+ def nginx_or_apache
10
+ server = ''
11
+ @dna['applications'].each do |name, app_data|
12
+ if app_data['recipes'].detect { |r| r == 'nginx' }
13
+ server = 'nginx'
14
+ end
15
+
16
+ if app_data['recipes'].detect { |r| r == 'passenger' }
17
+ server = 'apache2'
18
+ end
19
+ end
20
+ server
21
+ end
22
+
23
+ def skip?(name)
24
+ (@dna['skip']||[]).include?(name)
25
+ end
26
+
27
+ def check
28
+ case @dna['instance_role']
29
+ when 'solo'
30
+ check_process(nginx_or_apache) unless skip?(nginx_or_apache)
31
+ check_mysql unless skip?('mysqld')
32
+ when 'app', 'app_master'
33
+ check_process(nginx_or_apache) unless skip?(nginx_or_apache)
34
+ check_process('haproxy') unless skip?('haproxy')
35
+ when 'db_master', 'db_slave'
36
+ check_mysql unless skip?('mysqld')
37
+ when 'util'
38
+ end
39
+ (@dna['check']||[]).each do |check|
40
+ check_process(check)
41
+ end
42
+ @result.to_json
43
+ end
44
+
45
+ def check_mysql
46
+ check_process('mysqld')
47
+ DBI.connect("DBI:Mysql:mysql:#{@dna['db_host']}", 'root', @dna['users'].first['password'])
48
+ rescue DBI::DatabaseError => e
49
+ @result['mysqld'] = 'down'
50
+ end
51
+
52
+ def check_process(name)
53
+ return if name == ''
54
+ pids = `pgrep #{name}`.split("\n")
55
+ if pids.empty?
56
+ @result[name] = 'down'
57
+ else
58
+ if pids.detect {|p| `kill -0 #{p}; echo $?`.chomp.to_i != 0}
59
+ @result[name] = 'down'
60
+ else
61
+ @result[name] = 'up'
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,110 @@
1
+ module AWS::S3
2
+ class S3Object
3
+ def <=>(other)
4
+ DateTime.parse(self.about['last-modified']) <=> DateTime.parse(other.about['last-modified'])
5
+ end
6
+ end
7
+ end
8
+
9
+ require 'open-uri'
10
+
11
+ module EY
12
+
13
+ class BucketMinder
14
+
15
+ def initialize(opts={})
16
+ AWS::S3::Base.establish_connection!(
17
+ :access_key_id => opts[:aws_secret_id],
18
+ :secret_access_key => opts[:aws_secret_key]
19
+ )
20
+ @instance_id = opts[:instance_id]
21
+ @type = opts[:type]
22
+ @env = opts[:env]
23
+ @opts = opts
24
+ opts[:extension] ||= "tgz"
25
+ @keep = opts[:keep]
26
+ @name = "#{Time.now.strftime("%Y-%m-%dT%H:%M:%S").gsub(/:/, '-')}.#{@type}.#{opts[:extension]}"
27
+ end
28
+
29
+ def bucket
30
+ @bucket ||= begin
31
+ buck = "#{@env}-#{@type}-#{instance_id}-#{Digest::SHA1.hexdigest(@opts[:aws_secret_id])[0..6]}"
32
+ begin
33
+ AWS::S3::Bucket.create buck
34
+ rescue AWS::S3::ResponseError
35
+ end
36
+ buck
37
+ end
38
+ end
39
+
40
+ def instance_id
41
+ @instance_id ||= open("http://169.254.169.254/latest/meta-data/instance-id").read
42
+ end
43
+
44
+ def upload_object(file)
45
+ AWS::S3::S3Object.store(
46
+ @name,
47
+ open(file),
48
+ bucket,
49
+ :access => :private
50
+ )
51
+ FileUtils.rm file
52
+ puts "successful upload: #{@name}"
53
+ true
54
+ end
55
+
56
+ def download(index, printer = false)
57
+ obj = list[index.to_i]
58
+ puts "downloading: #{obj}" if printer
59
+ File.open(obj.key, 'wb') do |f|
60
+ print "." if printer
61
+ obj.value {|chunk| f.write chunk }
62
+ end
63
+ puts if printer
64
+ puts "finished" if printer
65
+ obj.key
66
+ end
67
+
68
+ def cleanup
69
+ list[0...-(@keep)].each{|o|
70
+ puts "deleting: #{o.key}"
71
+ o.delete
72
+ }
73
+ end
74
+
75
+ def get_current
76
+ name = download(list.size - 1)
77
+ File.expand_path(name)
78
+ end
79
+
80
+ def clear_bucket
81
+ list.each do |o|
82
+ puts "deleting: #{o.key}"
83
+ o.delete
84
+ end
85
+ end
86
+
87
+ def rollback
88
+ o = list.last
89
+ puts "rolling back: #{o.key}"
90
+ o.delete
91
+ end
92
+
93
+ def empty?
94
+ list.empty?
95
+ end
96
+
97
+ def list(printer = false)
98
+ objects = AWS::S3::Bucket.objects(bucket).sort
99
+ puts "listing bucket #{bucket}" if printer && !objects.empty?
100
+ if printer
101
+ objects.each_with_index do |b,i|
102
+ puts "#{i}:#{@env} #{b.key}"
103
+ end
104
+ end
105
+ objects
106
+ end
107
+
108
+ end
109
+
110
+ end