forj 0.0.39 → 0.0.40

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/lib/connection.rb CHANGED
@@ -39,7 +39,7 @@ class ForjConnection
39
39
  @oConfig = oConfig
40
40
  @sAccountName = @oConfig.get('account_name')
41
41
  @provider='HP' # TODO: Support multiple provider. (Generic Provider object required)
42
- @sAccountName = @oConfig.get('provider') if not @sAccountName
42
+ @sAccountName = @oConfig.get(:provider) if not @sAccountName
43
43
  @sAccountName = 'hpcloud' if not @sAccountName
44
44
 
45
45
  @credentials = get_credentials()
@@ -71,7 +71,7 @@ class ForjConnection
71
71
  if not oSSLError.ErrorDetected(e.message,e.backtrace)
72
72
  retry
73
73
  end
74
- Logging.fatal(1, 'Compute: Unable to connect.')
74
+ Logging.fatal(1, 'Compute: Unable to connect.', e)
75
75
  end
76
76
  end
77
77
 
@@ -91,7 +91,7 @@ class ForjConnection
91
91
  if not oSSLError.ErrorDetected(e.message,e.backtrace)
92
92
  retry
93
93
  end
94
- Logging.fatal(1, 'Network: Unable to connect.')
94
+ Logging.fatal(1, 'Network: Unable to connect.', e)
95
95
  end
96
96
 
97
97
  end
data/lib/defaults.yaml CHANGED
@@ -22,11 +22,13 @@ default:
22
22
  image: Ubuntu Precise 12.04.4 LTS Server 64-bit 20140414 (Rescue Image)
23
23
 
24
24
  # Flavor to use for Maestro
25
- flavor: standard.xsmall
25
+ flavor: standard.medium
26
+ # Default flavor to use for all Blueprint nodes.
27
+ bp_flavor: standard.small
26
28
 
27
29
  # Ports to open for Maestro, added to the security group
28
30
  security_group: forj
29
- ports: [22, 80, 443, 3000, 3131, 3132, 3233, 3134, 3135, 4505-4506, 5000, 5666, 8000, 8080-8081, 8083, 8125, 8139-8140, 8773-8776, 9292, 29418, 35357]
31
+ ports: [22, 80, 443, 3000, 3131-3135, 4505-4506, 5000, 5666, 8000, 8080-8081, 8083, 8125, 8139-8140, 8773-8776, 9292, 29418, 35357]
30
32
 
31
33
  # Private key file path. Those files (private/public key) will be added to ~/.forj/keypairs/ as respectively 'keypair_name' and 'keypair_name'.pub
32
34
  keypair_path: ~/.ssh/forj-id_rsa
@@ -39,7 +41,7 @@ default:
39
41
  build_config: box
40
42
  branch: master
41
43
  box_name: maestro
42
- description:
44
+ :description:
43
45
  # Description of build.sh environment variable defined by forj cli for build.sh. (~/.forj/infra/build/<Account>.build.env)
44
46
  FORJ_HPC: "HPCloud cli Account used to build your Maestro box"
45
47
  FORJ_HPC_COMPUTE: "HPCloud Compute service (like region-b.geo-1) used to run your Maestro Box"
@@ -0,0 +1,454 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'rubygems'
19
+ require 'highline/import'
20
+
21
+ require 'yaml_parse.rb'
22
+ include YamlParse
23
+ require 'helpers.rb'
24
+ include Helpers
25
+
26
+ require 'encryptor' # gem install encryptor
27
+ require 'base64'
28
+
29
+ # TODO: To move to a specific module driven by providers.
30
+ require 'hpcloud/version'
31
+ require 'hpcloud/config'
32
+ require 'hpcloud/accounts'
33
+ require 'hpcloud/connection'
34
+ include HP::Cloud
35
+
36
+ class ForjAccount
37
+
38
+ attr_reader :sAccountName
39
+ attr_reader :hAccountData
40
+
41
+ # This object manage data located in oConfig[:hpc_accounts/AccountName]
42
+
43
+ def initialize(oConfig)
44
+ # Initialize object
45
+ @oConfig = oConfig
46
+
47
+ if @oConfig.get('account_name')
48
+ @sAccountName = @oConfig.get('account_name')
49
+ else
50
+ @sAccountName = 'hpcloud'
51
+ end
52
+ @sAccountFile = File.join($FORJ_ACCOUNTS_PATH, @sAccountName)
53
+
54
+ sProvider = 'hpcloud'
55
+ sProvider = @oConfig.get(:provider) if @oConfig.get(:provider)
56
+
57
+ @hAccountData = {}
58
+ rhSet(@hAccountData, @sAccountName, [:account, :name]) if rhExist?(@hAccountData, [:account, :name]) != 2
59
+ rhSet(@hAccountData, sProvider, [:account, :provider]) if rhExist?(@hAccountData, [:account, :provider]) != 2
60
+ end
61
+
62
+ def get(section, key, default = nil)
63
+ @oConfig.get(key, rhGet(@hAccountData, section), default )
64
+ end
65
+
66
+ def ac_load(sAccountName = @sAccountName)
67
+ # Load Account Information
68
+
69
+ if sAccountName != @sAccountName
70
+ @sAccountName = sAccountName
71
+ @sAccountFile = File.join($FORJ_ACCOUNTS_PATH, @sAccountName)
72
+ end
73
+
74
+ if File.exists?(@sAccountFile)
75
+ @hAccountData = @oConfig.ExtraLoad(@sAccountFile, :forj_accounts, @sAccountName)
76
+ sProvider = @oConfig.get(:provider, nil, 'hpcloud')
77
+ rhSet(@hAccountData, @sAccountName, :account, :name) if rhExist?(@hAccountData, :account, :name) != 2
78
+ rhSet(@hAccountData, sProvider, :account, :provider) if rhExist?(@hAccountData, :account, :provider) != 2
79
+ provider_load()
80
+ return @hAccountData
81
+ end
82
+ nil
83
+ end
84
+
85
+ def ac_save()
86
+ @oConfig.ExtraSet(:forj_accounts, @sAccountName, nil, @hAccountData)
87
+ @oConfig.ExtraSave(@sAccountFile, :forj_accounts, @sAccountName)
88
+
89
+ if not @oConfig.LocalDefaultExist?('account_name')
90
+ @oConfig.LocalSet('account_name',@sAccountName)
91
+ @oConfig.SaveConfig
92
+ end
93
+ end
94
+
95
+ def setup()
96
+ # Full setup to make it work.
97
+
98
+ # setting up provider account - Required, while calling external provider tool, like hpcloud.
99
+ self.setup_provider_account()
100
+
101
+ # Implementation of simple credential encoding for build.sh/maestro
102
+ self.setup_maestro_creds()
103
+
104
+ # DNS Setting for Gardener
105
+ self.setup_dns()
106
+
107
+ # Check/create keypair
108
+ self.keypair_setup()
109
+
110
+ # Checking cloud connection
111
+ Logging.message("Checking cloud connection")
112
+ oFC = ForjConnection.new(@oConfig)
113
+
114
+ Logging.message("Setup '%s' done. Thank you." % @sAccountName)
115
+ end
116
+
117
+ def setup_provider_account()
118
+ # TODO: Support of multiple providers thanks to fog.
119
+ # TODO: Replace this code by our own forj account setup, inspired/derived from hpcloud account::setup
120
+
121
+ # delegate the initial configuration to hpcloud (unix_cli)
122
+ if File.exists?(File.join($HPC_ACCOUNTS, 'hp')) and not File.exists?(File.join($HPC_ACCOUNTS, @sAccountName)) and @sAccountName != 'hp'
123
+ Logging.info("hpcloud: Copying 'hp' account setup to '%s'" % @sAccountName)
124
+ Kernel.system('hpcloud account:copy hp %s' % [@sAccountName])
125
+ end
126
+
127
+ Logging.info("Configuring hpcloud account '%s'" % [@sAccountName] )
128
+ command = 'hpcloud account:setup %s' % [@sAccountName]
129
+ Logging.debug("Executing : '%s'" % command)
130
+ case Kernel.system(command)
131
+ when false
132
+ Logging.fatal(1, "Unable to setup your '%s' account" % [@sAccountName])
133
+ when nil
134
+ Logging.fatal(1, "Unable to execute 'hpcloud' cli. Please check hpcloud installation.")
135
+ end
136
+
137
+ provider_load() # To ensure latest provider data are loaded
138
+
139
+ setup_tenant_name()
140
+ end
141
+
142
+ def provider_load()
143
+ # TODO: Should be provider agnostic
144
+ # Loading HPCloud account setting in Config.
145
+ hpc_account_file = File.join($HPC_ACCOUNTS, @sAccountName)
146
+
147
+ # Maestro compute use openstack. It requires meta tenant_name (not ID). Need to query HPC to get the Project Name from the ID.
148
+ @oConfig.ExtraLoad(hpc_account_file, :hpc_accounts, @sAccountName)
149
+ end
150
+
151
+ def setup_tenant_name()
152
+ # Maestro uses fog/openstack to connect to the cloud. It needs Tenant name instead of tenant ID.
153
+ # Getting it from Compute connection and set it
154
+
155
+ oSSLError=SSLErrorMgt.new # Retry object
156
+ Logging.debug("Getting tenants from hpcloud cli libraries")
157
+ begin
158
+ tenants = Connection.instance.tenants(@sAccountName)
159
+ rescue => e
160
+ if not oSSLError.ErrorDetected(e.message,e.backtrace)
161
+ retry
162
+ end
163
+ Logging.fatal(1, 'Network: Unable to connect.')
164
+ end
165
+ tenant_id = rhGet(@oConfig.ExtraGet(:hpc_accounts, @sAccountName, :credentials), :tenant_id)
166
+ tenant_name = nil
167
+ tenants.each { |elem| tenant_name = elem['name'] if elem['id'] == tenant_id }
168
+ if tenant_name
169
+ Logging.debug("Tenant ID '%s': '%s' found." % [tenant_id, tenant_name])
170
+ hCompute = { :tenant_name => tenant_name }
171
+ rhSet(@hAccountData, hCompute, :compute)
172
+ else
173
+ Logging.error("Unable to find the tenant Name for '%s' ID." % tenant_id)
174
+ end
175
+ @oConfig.set('tenants', tenants)
176
+ end
177
+
178
+ # Setting up DNS information
179
+ def setup_dns()
180
+ # Get HPCloud account definition
181
+ yHPC = @oConfig.ExtraGet(:hpc_accounts, @sAccountName)
182
+ # Get Forj account definition
183
+ yDNS = rhGet(@hAccountData, :dns)
184
+ yDNS = {} if not yDNS
185
+
186
+ sAsk = "Optionally, you can ask Maestro to use/manage a domain name on your cloud. It requires your DNS cloud service to be enabled.\nDo you want to configure it?"
187
+ if agree(sAsk)
188
+ # Getting tenants
189
+ tenants = @oConfig.get('tenants')
190
+
191
+ # Question about DNS Tenant ID
192
+ # In HPCloud : credentials/tenant_id
193
+ aDNS_TenantIDs = []
194
+ sDNS_TenantIDs = rhGet(yDNS, :tenant_id)
195
+ sDNS_TenantIDs = rhGet(yHPC, :credentials, :tenant_id) if not sDNS_TenantIDs and rhExist?(yHPC, :credentials, :tenant_id) > 0
196
+
197
+ Logging.message("Following are the list of know project attached to your credentials:")
198
+ tenants.each do | elem |
199
+ aDNS_TenantIDs.push(elem['id'])
200
+ if sDNS_TenantIDs and elem['id'] == sDNS_TenantIDs
201
+ Logging.message("%s - %s" % [ANSI.bold+elem['id']+ANSI.reset, elem['name']])
202
+ else
203
+ Logging.message("%s - %s" % [elem['id'], elem['name']])
204
+ end
205
+ end
206
+
207
+ sOption = ' [%s]' % aDNS_TenantIDs.join(', ') if aDNS_TenantIDs.length() == 2
208
+ sDNS_TenantID = ask('Enter DNS Tenant ID:%s' % sOption) do |q|
209
+ q.default = sDNS_TenantIDs
210
+ q.validate = /[\w\d]+/
211
+ end
212
+ yDNS[:tenant_id] = sDNS_TenantID.to_s
213
+
214
+ # Question about DNS Service
215
+ # In HPCloud : regions/dns
216
+ if sDNS_TenantID == rhGet(yHPC, :credentials, :tenant_id)
217
+ sDNS_Service = rhGet(yHPC, :regions, :dns)
218
+ else
219
+ aDNS_Services = []
220
+ aDNS_Services.push(rhGet(yDNS, :service)) if rhExist?(yDNS, :service) > 0
221
+
222
+ sDNS_Service = ask("Enter DNS Service for the Tenant ID '%s' (ex: region-a.geo-1): " % sDNS_TenantID) do |q|
223
+ q.validate = /[\w.-]+/
224
+ end
225
+ end
226
+ yDNS[:service] = sDNS_Service.to_s
227
+
228
+ else
229
+ yDNS.delete(:service)
230
+ yDNS.delete(:tenant_id)
231
+ Logging.message("Maestro won't manage any Domain with '%s' provider." % [ rhGet(@hAccountData, [:account, :provider])])
232
+ end
233
+ # Question about Domain name
234
+ previousDomainName = rhGet(yDNS, :domain_name) if rhExist?(yDNS, :domain_name) > 0
235
+
236
+ sDNS_DomainName = ask('Enter Domain name to add to hostnames (puppet requirement) (ex: dev.forj.io):') do |q|
237
+ q.default = previousDomainName if previousDomainName
238
+ q.validate = /[\w._]+/
239
+ end
240
+ yDNS[:domain_name] = sDNS_DomainName.to_s
241
+
242
+ # Attaching to the account.
243
+ rhSet(@hAccountData, yDNS, :dns)
244
+ end
245
+
246
+ # manage keypair attached to a FORJ account.
247
+ def keypair_setup()
248
+
249
+ # Getting Account keypair information
250
+ yCreds = rhGet(@hAccountData, :credentials)
251
+ key_name = @oConfig.get('keypair_name', yCreds )
252
+ orig_key_path = File.expand_path(@oConfig.get('keypair_path', yCreds))
253
+
254
+ Logging.warning("'keypair_path' is missing at least from defaults.yaml. To fix it, set it in your configuration file ~/.forj/config.yaml under default section") if not orig_key_path
255
+ key_path = nil
256
+ while not key_path
257
+ key_path = ask ("Please provide the SSH private key path used by default on this account:") do | q |
258
+ q.default = orig_key_path
259
+ q.validate = /.*+/
260
+ end
261
+ keys_entered = keypair_detect(key_name, key_path)
262
+ if not keys_entered[:private_key_exist?] and not keys_entered[:public_key_exist?]
263
+ if agree("The key you entered was not found. Do you want to create this one?")
264
+ base_dir = File.dirname(keys_entered[:keypair_path])
265
+ if File.directory?(base_dir)
266
+ if agree("'%s' doesn't exist. Do you want to create it?")
267
+ ensure_forj_dirs_exists(base_dir)
268
+ end
269
+ end
270
+ else
271
+ key_path = nil
272
+ end
273
+ end
274
+ end
275
+ keys_imported = nil
276
+ keys_imported = keypair_detect(key_name, @oConfig.LocalGet(key_name, :imported_keys)) if @oConfig.LocalExist?(key_name, :imported_keys)
277
+
278
+ if keys_imported and keys_imported[:key_basename] != keys_entered[:key_basename] and $FORJ_KEYPAIRS_PATH != keys_entered[:keypair_path]
279
+ Logging.warning("The private key '%s' was imported from a different private key file '%s'.\nTo not overwrite it, we recommend you to choose a different keypair name." % [key_name, sImportedKey])
280
+ key_name = nil
281
+ end
282
+
283
+ key_name = ask ("Please provide the keypair name used by default on this account:") do | q |
284
+ q.default = key_name
285
+ q.validate = /.*+/
286
+ end
287
+ key_name = key_name.to_s
288
+
289
+ keys = keypair_detect(key_name, key_path)
290
+
291
+ Logging.info("Configuring forj keypair '%s'" % [ keys[:keypair_name] ] )
292
+
293
+
294
+ private_key_file = File.join(keys[:keypair_path], keys[:private_key_name])
295
+ public_key_file = File.join(keys[:keypair_path], keys[:public_key_name])
296
+
297
+
298
+ # Creation sequences
299
+ if not keys[:private_key_exist?]
300
+ # Need to create a key. ask if we need so.
301
+ Logging.message("Private key file '%s' was not found. forj will propose to create one for you. Please review the proposed private key file name and path.\nYou can press Enter to accept the default value." % keys[:private_key_path])
302
+ real_key_path = File.expand_path(ask("Private key file path:") do |q|
303
+ q.validate = /\w+/
304
+ q.default = private_key_file
305
+ end)
306
+ if not File.exists?(real_key_path)
307
+ Helpers.ensure_dir_exists(File.dirname(real_key_path))
308
+ command = 'ssh-keygen -t rsa -f %s' % real_key_path
309
+ Logging.debug("Executing '%s'" % command)
310
+ system(command)
311
+ end
312
+ if not File.exists?(real_key_path)
313
+ Logging.fatal(1, "'%s' not found. Unable to add your keypair to hpcloud. Create it yourself and provide it with -p option. Then retry." % [real_key_path])
314
+ else
315
+ if real_key_path != key_path and not @oConfig.LocalDefaultExist?('keypair_path')
316
+ Logging.debug("Saving forj keypair '%s' as default." % [real_key_path] )
317
+ @oConfig.LocalSet('keypair_path', real_key_path)
318
+ @oConfig.SaveConfig()
319
+ end
320
+ end
321
+ end
322
+
323
+ if not keys[:public_key_exist?]
324
+ Logging.message("Your public key '%s' was not found. Getting it from the private one. It may require your passphrase." % [public_key_file])
325
+ command = 'ssh-keygen -y -f %s > %s' % [private_key_file,public_key_file ]
326
+ Logging.debug("Executing '%s'" % command)
327
+ system(command)
328
+ end
329
+
330
+ forj_private_key_file = File.join($FORJ_KEYPAIRS_PATH, key_name )
331
+ forj_public_key_file = File.join($FORJ_KEYPAIRS_PATH, key_name + ".pub")
332
+
333
+ # Saving sequences
334
+ if keys[:keypair_path] != $FORJ_KEYPAIRS_PATH
335
+ if not File.exists?(forj_private_key_file)
336
+ Logging.info("Importing key pair to FORJ keypairs list.")
337
+ FileUtils.copy(private_key_file, forj_private_key_file)
338
+ FileUtils.copy(public_key_file, forj_public_key_file)
339
+ # Attaching this keypair to the account
340
+ rhSet(@hAccountData, key_name, :credentials, 'keypair_name')
341
+ rhSet(@hAccountData, forj_private_key_file, :credentials, 'keypair_path')
342
+ @oConfig.LocalSet(key_name.to_s, private_key_file, :imported_keys)
343
+ @oConfig.SaveConfig()
344
+ end
345
+ end
346
+ end
347
+
348
+ def setup_maestro_creds()
349
+ # Check required global data
350
+ if not $FORJ_CREDS_PATH
351
+ Logging.fatal(1, "Internal error: '$FORJ_CREDS_PATH' missing.")
352
+ end
353
+ if not Helpers.dir_exists?($FORJ_CREDS_PATH)
354
+ Logging.fatal(1, "Internal error: '%s' doesn't exist." % $FORJ_CREDS_PATH)
355
+ end
356
+
357
+ Logging.info("Completing hpcloud account '%s' information." % [@sAccountName] )
358
+
359
+ forj_user = rhGet(@hAccountData, :credentials, :os_user)
360
+ enc_hpcloud_os_key = rhGet(@hAccountData, :credentials, :os_enckey)
361
+
362
+ hpcloud_os_user = ask('Enter hpcloud username: ') do |q|
363
+ q.validate = /\w+/
364
+ q.default = forj_user if forj_user
365
+ end
366
+
367
+
368
+ # Checking key file used to encrypt/decrypt passwords
369
+ key_file = File.join($FORJ_CREDS_PATH, '.key')
370
+ if not File.exists?(key_file)
371
+ # Need to create a random key.
372
+ entr = { :key => rand(36**10).to_s(36), :salt => Time.now.to_i.to_s, :iv => OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv}
373
+
374
+ Logging.debug("Writing '%s' key file" % key_file)
375
+ File.open(key_file, 'w') do |out|
376
+ out.write(Base64::encode64(entr.to_yaml))
377
+ end
378
+ else
379
+ Logging.debug("Loading '%s' key file" % key_file)
380
+ encoded_key = IO.read(key_file)
381
+ entr = YAML.load(Base64::decode64(encoded_key))
382
+ end
383
+
384
+ if enc_hpcloud_os_key
385
+ hpcloud_os_key_hidden = '*' * Encryptor.decrypt(
386
+ :value => Base64::strict_decode64(enc_hpcloud_os_key),
387
+ :key => entr[:key],
388
+ :iv => entr[:iv],
389
+ :salt => entr[:salt]
390
+ ).length
391
+ hpcloud_os_key_hidden="[%s]" % hpcloud_os_key_hidden
392
+ Logging.message("A password is already set for '%s'. If you want to keep it, just press Enter" % [hpcloud_os_user])
393
+ else
394
+ hpcloud_os_key_hidden = ""
395
+ end
396
+
397
+ hpcloud_os_key = ""
398
+ while hpcloud_os_key == ""
399
+ # ask for password.
400
+ hpcloud_os_key = ask("Enter hpcloud password for '%s': %s" % [hpcloud_os_user, hpcloud_os_key_hidden]) do |q|
401
+ q.echo = '*'
402
+ end
403
+ if hpcloud_os_key == "" and enc_hpcloud_os_key
404
+ hpcloud_os_key = Encryptor.decrypt(:value => Base64::strict_decode64(enc_hpcloud_os_key), :key => entr[:key], :iv => entr[:iv], :salt => entr[:salt])
405
+ else
406
+ Logging.message("The password cannot be empty.") if hpcloud_os_key == ""
407
+ end
408
+ end
409
+ enc_hpcloud_os_key = Base64::strict_encode64(Encryptor.encrypt(:value => hpcloud_os_key, :key => entr[:key], :iv => entr[:iv], :salt => entr[:salt]))
410
+
411
+ cloud_fog = File.join($FORJ_CREDS_PATH, @sAccountName+'.g64')
412
+
413
+ # Security fix: Remove old temp file with clear password.
414
+ old_file = '%s/master.forj-13.5' % [$FORJ_CREDS_PATH]
415
+ File.delete(old_file) if File.exists?(old_file)
416
+ old_file = '%s/creds' % [$FORJ_CREDS_PATH]
417
+ File.delete(old_file) if File.exists?(old_file)
418
+
419
+ provider_load() if not @oConfig.ExtraExist?(:hpc_accounts, @sAccountName)
420
+ hpc_creds = @oConfig.ExtraGet(:hpc_accounts, @sAccountName, :credentials)
421
+
422
+ rhSet(@hAccountData, hpcloud_os_user.to_s, :credentials, :os_user)
423
+ rhSet(@hAccountData, enc_hpcloud_os_key, :credentials, :os_enckey)
424
+
425
+ IO.popen('gzip -c | base64 -w0 > %s' % [cloud_fog], 'r+') {|pipe|
426
+ pipe.puts('HPCLOUD_OS_USER=%s' % [hpcloud_os_user] )
427
+ pipe.puts('HPCLOUD_OS_KEY=%s' % [hpcloud_os_key] )
428
+ pipe.puts('DNS_KEY=%s' % [hpc_creds[:account_id]] )
429
+ pipe.puts('DNS_SECRET=%s' % [hpc_creds[:secret_key]])
430
+ pipe.close_write
431
+ }
432
+ Logging.info("'%s' written." % cloud_fog)
433
+ end
434
+ end
435
+
436
+ def ensure_forj_dirs_exists()
437
+ # Function to create FORJ paths if missing.
438
+
439
+ # Defining Global variables
440
+ $FORJ_DATA_PATH = File.expand_path(File.join('~', '.forj'))
441
+ $FORJ_ACCOUNTS_PATH = File.join($FORJ_DATA_PATH, 'accounts')
442
+ $FORJ_KEYPAIRS_PATH = File.join($FORJ_DATA_PATH, 'keypairs')
443
+ $FORJ_CREDS_PATH = File.expand_path(File.join('~', '.cache', 'forj'))
444
+
445
+ # TODO: To move to an hpcloud object.
446
+ $HPC_KEYPAIRS = File.expand_path(File.join('~', '.hpcloud', 'keypairs'))
447
+ $HPC_ACCOUNTS = File.expand_path(File.join('~', '.hpcloud', 'accounts'))
448
+
449
+ Helpers.ensure_dir_exists($FORJ_DATA_PATH)
450
+ Helpers.ensure_dir_exists($FORJ_ACCOUNTS_PATH)
451
+ Helpers.ensure_dir_exists($FORJ_KEYPAIRS_PATH)
452
+ FileUtils.chmod(0700, $FORJ_KEYPAIRS_PATH)
453
+ Helpers.ensure_dir_exists($FORJ_CREDS_PATH)
454
+ end