cluster 0.5.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -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