cluster 0.5.33

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,19 @@
1
+ #!/bin/bash
2
+ # This will run periodically to do appropriate backups and cleanups.
3
+ # run as a crontab so the environment is minimal
4
+
5
+ export GEM_PATH=$(gem env gempath)
6
+ export CREDENTIALS=${HOME}/.cluster/credentials.yml
7
+
8
+ mysql_user=
9
+ mysql_host=$(cluster service -d database)
10
+ mysql_password=
11
+ aws_secret=""
12
+ aws_key=""
13
+ region=""
14
+ volume=""
15
+ mount=""
16
+
17
+ cluster period
18
+
19
+ sudo ec2-consistent-snapshot --aws-access-key-id ${aws_key} --aws-secret-access-key ${aws_secret} --mysql-user ${mysql_user} --mysql-password ${mysql_password} --mysql-host ${mysql_host} --xfs-filesystem ${mount} --region ${region} ${volume}
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
3
+ FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
4
+ VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
5
+ biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
6
+ dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
7
+ MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
8
+ MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
9
+ A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
10
+ b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
11
+ cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
12
+ bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
13
+ VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
14
+ ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
15
+ uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
16
+ 9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
17
+ hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
18
+ pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,24 @@
1
+ amazon:
2
+ user: 91*********
3
+ key: AKI**********
4
+ secret: U***************************
5
+
6
+ monitor:
7
+ email:
8
+ address: smtp.gmail.com
9
+ port: 587
10
+ domain: ingamersports.com
11
+ authentication: plain
12
+ user_name: dog@score345.com
13
+ password: *******
14
+ messages:
15
+ from: dog@ingamersports.com
16
+ contacts:
17
+ - name: alerts
18
+ email: alert@ingamersports.com
19
+ - name: panic
20
+ email: panic@ingamersports.com
21
+ group: emergency
22
+ - name: simon
23
+ email: sdeboer@ingamersports.com
24
+ group: person
@@ -0,0 +1,88 @@
1
+ #!/bin/env god -c
2
+ require 'rubygems'
3
+ require 'tlsmail'
4
+ require 'fileutils'
5
+ require 'cluster'
6
+ require 'cluster/infrastructures/amazon'
7
+
8
+ Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
9
+
10
+ CREDENTIALS = ENV['CREDENTIALS'] || File.join(ENV['HOME'], '.cluster', 'credentials.yml')
11
+
12
+ credentials_file = File.expand_path(CREDENTIALS)
13
+
14
+ unless File.exists?(credentials_file)
15
+ $stderr.puts "Cannot find credentials for cluster : #{credentials_file} !"
16
+ exit 2
17
+ end
18
+ MONITOR_PATH = File.join File.dirname(credentials_file), 'services.d'
19
+
20
+ Cluster::Configuration[:credentials_file] = credentials_file
21
+ CLUSTER = Cluster.new(Amazon.new)
22
+
23
+ class UserService < God::Behavior
24
+ def before_start
25
+ service = self.watch.name[/^(\w+)-/, 1]
26
+ users_file = File.join(MONITOR_PATH, service, 'users.sh')
27
+ unless File.exists? users_file
28
+ FileUtils.mkdir_p File.dirname users_file
29
+ CLUSTER.retrieve service, 'users.sh', users_file
30
+ end
31
+
32
+ system(users_file) if File.exists? users_file
33
+ end
34
+ end
35
+
36
+ class ProjectService < God::Behavior
37
+ def before_start
38
+ service = self.watch.name[/^(\w+)-/, 1]
39
+ end
40
+ end
41
+
42
+ creds = YAML::load_file credentials_file
43
+
44
+ if creds.include? 'monitor'
45
+ moni = creds['monitor']
46
+ email = moni['email'].keys.inject({}) {|m, k|
47
+ m.merge k.to_sym => moni['email'][k]
48
+ }
49
+ God::Contacts::Email.server_settings = email
50
+ God::Contacts::Email.message_settings = {
51
+ :from => moni['messages']['from']
52
+ }
53
+
54
+ if moni.include? 'contacts'
55
+ for contact in moni['contacts']
56
+ God.contact(:email) {|c|
57
+ c.name = contact['name']
58
+ c.email = contact['email']
59
+ contact['group'] and (c.group = contact['group'])
60
+ }
61
+ end
62
+ else
63
+ God.contact(:email) {|c|
64
+ c.name = 'system notification'
65
+ c.email = moni['messages']['from']
66
+ }
67
+ end
68
+ end
69
+
70
+ CLUSTER.instance_state('configuring')
71
+
72
+ for service in CLUSTER.current('services')
73
+ monitor_file = File.join MONITOR_PATH, service, "config.god"
74
+ FileUtils.mkdir_p File.dirname(monitor_file)
75
+ begin
76
+ CLUSTER.retrieve service, 'config.god', monitor_file
77
+ rescue => err
78
+ applog(nil, :warn, "Service of #{service} does not appear to have a monitor configuration. Skipping!")
79
+ next
80
+ end
81
+
82
+ if File.readable? monitor_file
83
+ applog(nil, :info, "Loading monitor file #{monitor_file}")
84
+ load monitor_file
85
+ else
86
+ applog(nil, :warn, "Cannot find a monitor file for #{monitor_file}")
87
+ end
88
+ end
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+
3
+ if ! id staging 2>/dev/null 1>&2; then
4
+ adduser --disabled-password --gecos 'staging' staging
5
+ mkdir -m 700 ~staging/.ssh
6
+ touch ~staging/.ssh/authorized_keys
7
+ chmod 600 ~staging/.ssh/authorized_keys
8
+ touch ~staging/.ssh/config
9
+ chmod 600 ~staging/.ssh/config
10
+
11
+ cat >>~staging/.ssh/authorized_keys <<END_OF_KEYS
12
+ ssh-dss AAAAB3NzaC1kc3MAAACBANcFLeySRpmVji+g9KcHBaedFE5SOLgkSQIKbeVjOwzGC75AIM5gY6gjOu0Kj4BYhlxUwOWkOEYgZwqu15qxtKPCnYQST3jqQnbfwN8UOC4y7XH/4G0gdOD9taFx4PpW0H+zvYs7smBb1qG8NnlUH1tyCGdNNmZLxn2b84R5pDcVAAAAFQDqV2zGPugaRR7gslhxyxrZnIpE9QAAAIAtEViFMBq8h4TXXbdeYR3EhR+zcUHzRz/yB3N7mdo8C1a5apHAnzwX7RPzvkskThU2Idj3ZxUyrTbd5WpBfk/OIwF+hvM3/Uw6XJLNaDSTd0t0HOJxE+SJuHwfOwNtI+J2IXwckUJ2laOTwjOc0YzIR1Gnf50gcz67R07H4qidtQAAAIANQsT7jT68TemlxBjjK22YDRxdRC5M2VuTAT6dDp9JL7KB6B1b3kU7EjiG9gk9oDUGWQiE5sEtHaFjgeViSwQhtaQ/Rqx8EmNG5W9lNgVcWtPmxqMJtOaaNggE+znE1xanY+fDtLqbAkbExZ8vypyUuMXvsgl7AiSSEMnpmX1Itw== simon@s345
13
+ ssh-dss AAAAB3NzaC1kc3MAAACBAIxHXUznZLryPsnK0YCa7W4HM3wSqpCV8MwIBYd4kl/qQzC2VlyX0mFhVFC3esLWyyWEAFcKyI3FlzI70Z4ppnukyL/2MonVTqto3RPoTQs8Ty3y10MYo+9UE65U6Rv2yHfx551vobJgHgVS7tmupCcemZYscgFCeUMgLOz+5tylAAAAFQC9NTxN10PfjndbLDaPYrpC3h8g9wAAAIBnq0vCE9FqjukltP85M5qiawS5sEXArB0HRP4MDpwk4xDdrpiEwa2qYSOiwN1brsxMGrVHe3HetPeApmZZV5vysV1sLp3CQAlGHoWJ3GjOR3lDYpTymlbZOzd62mKp7FxPVtNszbDiABJckTLUV95TM2OB2hn/mWqpzwJBh9GBrAAAAIAmFDbo3aCg3WcDFnBzI72aHBQ4532xEMrlASABJ9FwkNPCtr2VZRLR4vxo9Oyn21+z4SmFocJN0DcKgj1APeS8en/frAFG/UJr/4KdV/LAnTBz8qd6QnbxdUYxizVoYKI1Pl76axbPQCVe+dthfn0x19quOMc/ofHA7I0GGIojJw== nick@Sparta-MB.local
14
+ ssh-dss AAAAB3NzaC1kc3MAAACBAO/mj7W3wUuDAhvicx+C2MkAFJGFZvaPrBA+nbFbK240HDZcmS8sA9Ww3VwivKzQ4CwrpdMY3dPg0TM9H2USQvfMsis4bStDwLy4CFIvBEGoviVVdu8gBzVN+YGajhv7yZqJ9cpOSnUXUzCBh4ddhLtni4IQ2lEZyKdlUzmA77pZAAAAFQDSdiFXpCu3CrAm0zivwA68DcDj5wAAAIEA557V4w7vNgmZvkb3hnQui5IkVTpN+b2PKCzvA9clbJQvKBpivS7k5jpx+GeoAYA+pYNLppMf9zpyPLrJjJhJ3Y3qS3p5iFCed2aJRwxhd5lYIyEedZ2uW6tchVRPoXkT1/tmXBKUNnue8YHslhqXOy8nHyHd7dH7BXLblnQknRcAAACBANzpDp5oXEG7w40tCYd7dtJfDLT8cIXyA75yX2MtkHjpBylT+lP/c1P9pmPytEtBfoQCvwFKjVA7fVGTkF1QfMVzcJsB1wh6jUyS287JtbS4D2O/yEP6FioG5Qva8GdJ29Oy49+LIHgamc93ZaJPub+wvFYivNzQsomjdXtiNRNA olpc@xo-10-F8-44.localdomain
15
+ ssh-dss AAAAB3NzaC1kc3MAAACBAOC9i08N/CoZO9I4kXv8LFSkReglZw9gmOqK72E/IpijLZkd2oh0wyV98S+8lYZR0OPmK6B4vbPIarBsZiPfOe2EMGxsuYjwD3X3S2hIM/1zrvk+WMzf6UADxmCwWzC6bYa1aBH59ba9ojolsBuou6yOxm3boYmZYbnMCLUzm/eLAAAAFQCHNIOpZTKG0chczg+5T3WJ4Q5JAwAAAIA2/VIk8pST/ynuXuu82Z9ZsR9ZJHICYfYi2EqLA6qJUxSB8MjvF9BQGYgX+UCs96uFme8wPJMBU74c7mZlcHvtlgc+1rMQUTZhJ820b/eg2gcPKGYikWj8y3wT0TDoWemMWAaFprvgrPLhHYuVMUKKzI9VNTeKDD7NC1xMsd9pOgAAAIBT14VMwBZjaq0oJSDxzy7bgf5Tragy9yhs7ZgQ0QTpMTFrkO/YvbsCLeXbsRcq904EMcB5glOHXONppn5skwWwBCFtjpjL9WLaeCnhpCxFC+D89GyR7T3Jlvj/Wa2tkuCSFJLBc64kK+pTmDseRLBbhazJazn3oUrNuEFtazzZCw== simon@secondary
16
+ ssh-dss AAAAB3NzaC1kc3MAAACBALlZtmMckFufyVq+It10p4pC65NJCRdDpRrf1uIoVXvz1ZSlsm/f0jhatuNPpwnSQoRpvlWetiS5mzGJ3ze8aReqHHe9CZvDCpVy33cwyRhCZf7ndyGh1qa9ZA0YMHNVdVs03SpNr7Fzc3muGcKX3BiiOZz+6mtbaQW0X1p/VHpLAAAAFQC8AuBVqCRJKgBMHDHb0nxQAyHbRQAAAIEAgQJvHZ3Db3yVy99goeIJw/3lysVemaddIdPuJj/AdxRwkDeuZIxxtOUne/qjXr7hmu48EyXLVg/jsNivKarLI6CXZAk5JbxkgLN+8y0Ckzcd48KhSGpZsbTBtjV29UFH9aiMVOUTbL59603HNa3ucH2lCLhllBf+ameZZp+EFYMAAACARZwlCuPobEAk7wOxWzGQcaRvmSDSbIKexMeUBgZBZeYjp5Bxld6e7x/j3GBQEkzmxqf08zP6LpglDoNR3KuY2TEWhAS3H1KdT4GibNSNpY4y2Pl2K/GjUWC6wMmVcFFBCz/jJorttMSI1G+OVcy+Vdw42HyQ5Z2QtuoVA2MQ5IQ= staging@domU-12-31-39-0E-C8-82
17
+ END_OF_KEYS
18
+ cat >>~staging/.ssh/config <<END_OF_CONFIG
19
+ Host web
20
+ HostName domU-12-31-39-00-64-E4.compute-1.internal
21
+ User app
22
+ Host webu
23
+ HostName domU-12-31-39-00-64-E4.compute-1.internal
24
+ User ubuntu
25
+ Host *.compute-1.internal
26
+ ForwardAgent yes
27
+ END_OF_CONFIG
28
+
29
+ chown -R staging:staging ~staging/.ssh
30
+ fi
31
+
32
+ if ! id app 2>/dev/null 1>&2; then
33
+ adduser --disabled-password --gecos 'app' app
34
+ mkdir -m 700 ~app/.ssh
35
+ touch ~app/.ssh/authorized_keys
36
+ chmod 600 ~app/.ssh/authorized_keys
37
+
38
+ cat >>~app/.ssh/authorized_keys <<END_OF_KEYS
39
+ ssh-dss AAAAB3NzaC1kc3MAAACBALlZtmMckFufyVq+It10p4pC65NJCRdDpRrf1uIoVXvz1ZSlsm/f0jhatuNPpwnSQoRpvlWetiS5mzGJ3ze8aReqHHe9CZvDCpVy33cwyRhCZf7ndyGh1qa9ZA0YMHNVdVs03SpNr7Fzc3muGcKX3BiiOZz+6mtbaQW0X1p/VHpLAAAAFQC8AuBVqCRJKgBMHDHb0nxQAyHbRQAAAIEAgQJvHZ3Db3yVy99goeIJw/3lysVemaddIdPuJj/AdxRwkDeuZIxxtOUne/qjXr7hmu48EyXLVg/jsNivKarLI6CXZAk5JbxkgLN+8y0Ckzcd48KhSGpZsbTBtjV29UFH9aiMVOUTbL59603HNa3ucH2lCLhllBf+ameZZp+EFYMAAACARZwlCuPobEAk7wOxWzGQcaRvmSDSbIKexMeUBgZBZeYjp5Bxld6e7x/j3GBQEkzmxqf08zP6LpglDoNR3KuY2TEWhAS3H1KdT4GibNSNpY4y2Pl2K/GjUWC6wMmVcFFBCz/jJorttMSI1G+OVcy+Vdw42HyQ5Z2QtuoVA2MQ5IQ= staging@domU-12-31-39-0E-C8-82
40
+ END_OF_KEYS
41
+ chown -R app:app ~app/.ssh
42
+ fi
@@ -0,0 +1,267 @@
1
+ %w(configuration version infrastructure instance release).each {|l| require File.join('cluster', l) }
2
+
3
+ class Cluster
4
+ def security(*groups)
5
+ groups << 'access' if groups.empty?
6
+ @sub.security(groups)
7
+ end
8
+
9
+ def cost(*sizes)
10
+ @sub.cost(sizes)
11
+ end
12
+
13
+ def period(*args)
14
+ @sub.period(args)
15
+ end
16
+
17
+ def revoke(*ips)
18
+ if ips.empty?
19
+ current_ip = ''
20
+ require 'open-uri'
21
+ open('http://checkip.dyndns.com').each do |line|
22
+ current_ip = $1 and break if line =~ /IP Address: ([\d\.]+)</
23
+ end
24
+ ips << "#{current_ip}/32"
25
+ end
26
+ @sub.revoke(ips)
27
+ end
28
+
29
+ def authorize(*ips)
30
+ if ips.empty?
31
+ current_ip = ''
32
+ require 'open-uri'
33
+ open('http://checkip.dyndns.com').each do |line|
34
+ current_ip = $1 and break if line =~ /IP Address: ([\d\.]+)</
35
+ end
36
+ ips << "#{current_ip}/32"
37
+ end
38
+ @sub.authorize(ips)
39
+ end
40
+
41
+ def initialize(infrastructure)
42
+ self.class.set_credentials_file
43
+ infrastructure.configure
44
+ @sub = infrastructure
45
+ end
46
+
47
+ def machine(groups = [])
48
+ res = machines(groups)
49
+ res.empty? ? nil : res.first
50
+ end
51
+
52
+ def machines(groups = [])
53
+ @sub.machines(groups)
54
+ end
55
+ alias :instances :machines
56
+
57
+ def service(roles)
58
+ res = services(roles)
59
+ res.empty? ? nil : res.first
60
+ end
61
+
62
+ def services(roles = [])
63
+ @sub.services(roles)
64
+ end
65
+
66
+ def labeled(name)
67
+ @sub.instances.select {|i| i.identified_by? name}
68
+ end
69
+
70
+ def release(*params)
71
+ klass = @sub.release_class
72
+ env, tag = params
73
+ if tag
74
+ klass.find(env, tag) or klass.create(:environment => env, :tag => tag)
75
+ elsif env
76
+ klass.current(env)
77
+ else
78
+ nil
79
+ end
80
+ end
81
+
82
+ def to_credentials
83
+ {'credentials' => nil}
84
+ end
85
+
86
+ def create_file_store(name)
87
+ @sub.create_file_store(name)
88
+ end
89
+
90
+ def create_data_store(name)
91
+ @sub.create_data_store(name)
92
+ end
93
+
94
+ def start(machine_size, *services)
95
+ size = machine_size.to_s.strip.downcase
96
+ unless @sub.class.machine_sizes.include? size
97
+ msg = "#{Cluster::NAME} needs to have a size from: #{@sub.class.machine_sizes.join(', ')}"
98
+ puts msg
99
+ raise msg
100
+ end
101
+ # FIXME need a way to pass through a number argument
102
+ number ||= 1
103
+
104
+ services = services.map {|s|
105
+ s.split(',')
106
+ }.flatten
107
+
108
+ # This may not be necessary, but might as well make sure they are
109
+ # up to date any time that we are starting a new instance.
110
+ self.save_credentials
111
+
112
+ begin
113
+ number.times.map do |n|
114
+ @sub.new_instance(size, services)
115
+ end
116
+ rescue => err
117
+ puts "#{Cluster::NAME} cannot start new instance: #{err.message}\n\t#{err.backtrace.join("\n\t")}"
118
+ exit 2
119
+ end
120
+ end
121
+
122
+ def update_image_file(filename)
123
+ input = File.open(filename)
124
+ @sub.save_images(input)
125
+ end
126
+
127
+ def current(*params)
128
+ unless @sub.in_cluster?
129
+ puts "#{Cluster::NAME} says that we aren't in the cluster?"
130
+ exit 2
131
+ end
132
+
133
+ unless params.length > 0
134
+ puts "#{Cluster::NAME} current needs to know what to do?\n\t* services\n\t* name (|| dns)\n\t* ip\n\t* enable\n\t* disable"
135
+ exit 2
136
+ end
137
+
138
+ cmd = params.shift
139
+
140
+ case cmd.downcase
141
+ when 'services'
142
+ @sub.current_instance.services
143
+ when /^(n|dn)/
144
+ @sub.current_instance.dns
145
+ when /^i/
146
+ @sub.current_instance.ip
147
+ when /^e/
148
+ @sub.alter_instances!(@sub.current_instance) {|i| i.enable *params }
149
+ when /^di/
150
+ @sub.alter_instances!(@sub.current_instance) {|i| i.disable *params }
151
+ when /^s/
152
+ @sub.alter_instances!(@sub.current_instance) {|i| i.set_state *params }
153
+ else
154
+ puts "${Cluster::NAME} current did not understand '#{params.join(' ')}'"
155
+ exit 1
156
+ end
157
+ end
158
+ alias :instance :current
159
+
160
+ def instance_state(state)
161
+ @sub.current_instance.set_state(state)
162
+ end
163
+
164
+ def store(service, key, filename = nil)
165
+ full_key = File.join service, key
166
+ file = if filename and File.readable? filename
167
+ File.open(filename, 'r')
168
+ elsif File.readable? full_key
169
+ File.open(full_key, 'r')
170
+ elsif File.readable? File.basename(full_key)
171
+ File.open(File.basename(full_key))
172
+ else
173
+ puts "#{Cluster::NAME} cannot open a file for storage"
174
+ exit 2
175
+ end
176
+ @sub.store full_key, file
177
+ end
178
+
179
+ def retrieve(service, key, output = nil)
180
+ res = @sub.retrieve File.join(service, key)
181
+ if output
182
+ begin
183
+ File.open(output, 'w') {|f|
184
+ f.write res
185
+ }
186
+ rescue => err
187
+ puts "#{Cluster::NAME} cannot open #{output} for writing."
188
+ exit 2
189
+ end
190
+ else
191
+ res
192
+ end
193
+ end
194
+
195
+ def save_credentials(location = nil)
196
+ creds = if Cluster::Configuration.credentials?
197
+ File.open(Cluster::Configuration[:credentials_file])
198
+ else
199
+ cx = @sub.to_credentials.merge to_credentials
200
+ StringIO.new(cx.to_yaml)
201
+ end
202
+ @sub.save_credentials(creds, location)
203
+ end
204
+
205
+ def save_monitor(filename, key = nil)
206
+ file = open(filename)
207
+ unless file
208
+ puts "#{Cluster::NAME} cannot open file '#{filename}' for reading."
209
+ exit 2
210
+ end
211
+
212
+ key ||= File.basename(filename)
213
+ begin
214
+ @sub.save_monitor file, key
215
+ rescue => err
216
+ puts "#{Cluster::NAME} could not save monitor configuration: #{err.message}\n\t#{err.backtrace.join("\n\t")}"
217
+ exit 2
218
+ end
219
+ end
220
+
221
+ def credentials_url
222
+ @sub.credentials_url
223
+ end
224
+
225
+ def fetch_credentials(url)
226
+ unless Cluster::Configuration.credentials?
227
+ puts "Need to know where to save the incoming credentials."
228
+ exit 2
229
+ end
230
+
231
+ out = File.open(Cluster::Configuration[:credentials_file], 'w')
232
+ open(url).each do |l| out.write(l); end
233
+ out.close
234
+ end
235
+
236
+ def fetch_monitor(output)
237
+ monitor = @sub.fetch_monitor
238
+ unless monitor
239
+ puts "#{Cluster::NAME} cannot find any monitor information."
240
+ exit 1
241
+ end
242
+
243
+ File.open(output, 'w') {|f|
244
+ f.write(monitor)
245
+ }
246
+ end
247
+
248
+ def gemurl
249
+ Cluster::LOCATION
250
+ end
251
+
252
+ def imageurl
253
+ Cluster::IMAGES
254
+ end
255
+
256
+ class << self
257
+ def set_credentials_file
258
+ unless Cluster::Configuration.credentials?
259
+ if ENV['CREDENTIALS'] and File.exist?(ENV['CREDENTIALS'])
260
+ Cluster::Configuration[:credentials_file] = ENV['CREDENTIALS']
261
+ elsif ENV['HOME'] and File.exist?(File.join(ENV['HOME'], '.cluster', 'credentials.yml'))
262
+ Cluster::Configuration[:credentials_file] = File.join(ENV['HOME'], '.cluster', 'credentials.yml')
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end