forj 0.0.48 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/forj-account.rb CHANGED
@@ -16,22 +16,6 @@
16
16
  # limitations under the License.
17
17
 
18
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
19
 
36
20
  class ForjAccounts
37
21
  # Class to query FORJ Accounts list.
@@ -262,7 +246,7 @@ class ForjAccount
262
246
  @hAccountData = {:account => {:name => sAccountName, :provider => @oConfig.get(:provider_name)}}
263
247
  end
264
248
 
265
- def ac_load(sAccountName = @sAccountName, bHPCloudLoad = true)
249
+ def ac_load(sAccountName = @sAccountName)
266
250
  # Load Account Information
267
251
 
268
252
  if sAccountName != @sAccountName
@@ -275,7 +259,7 @@ class ForjAccount
275
259
  sProvider = @oConfig.get(:provider, 'hpcloud')
276
260
  rhSet(@hAccountData, @sAccountName, :account, :name) if rhExist?(@hAccountData, :account, :name) != 2
277
261
  rhSet(@hAccountData, sProvider, :account, :provider) if rhExist?(@hAccountData, :account, :provider) != 2
278
- provider_load() if bHPCloudLoad
262
+
279
263
  if rhKeyToSymbol?(@hAccountData, 2)
280
264
  @hAccountData = rhKeyToSymbol(@hAccountData, 2)
281
265
  self.ac_save()
@@ -286,7 +270,7 @@ class ForjAccount
286
270
  end
287
271
 
288
272
  def dump()
289
- { :forj_account => @hAccountData, :hpc_account => provider_load() }
273
+ { :forj_account => @hAccountData }
290
274
  end
291
275
 
292
276
  def ac_save()
@@ -299,367 +283,6 @@ class ForjAccount
299
283
  end
300
284
  end
301
285
 
302
- def setup()
303
- # Full setup to make it work.
304
-
305
- # setting up provider account - Required, while calling external provider tool, like hpcloud.
306
- self.setup_provider_account()
307
-
308
- # Implementation of simple credential encoding for build.sh/maestro
309
- self.setup_maestro_creds()
310
-
311
- # DNS Setting for Gardener
312
- self.setup_dns()
313
-
314
- # Check/create keypair
315
- self.keypair_setup()
316
-
317
- # Checking cloud connection
318
- Logging.message("Checking cloud connection")
319
- ForjConnection.new(self)
320
-
321
- Logging.message("Setup '%s' done. Thank you." % @sAccountName)
322
- end
323
-
324
- def setup_provider_account()
325
- # TODO: Support of multiple providers thanks to fog.
326
- # TODO: Replace this code by our own forj account setup, inspired/derived from hpcloud account::setup
327
-
328
- # delegate the initial configuration to hpcloud (unix_cli)
329
- if File.exists?(File.join($HPC_ACCOUNTS, 'hp')) and not File.exists?(File.join($HPC_ACCOUNTS, @sAccountName)) and @sAccountName != 'hp'
330
- Logging.info("hpcloud: Copying 'hp' account setup to '%s'" % @sAccountName)
331
- Kernel.system('hpcloud account:copy hp %s' % [@sAccountName])
332
- end
333
-
334
- Logging.info("Configuring hpcloud account '%s'" % [@sAccountName] )
335
- command = 'hpcloud account:setup %s' % [@sAccountName]
336
- Logging.debug("Executing : '%s'" % command)
337
- case Kernel.system(command)
338
- when false
339
- Logging.fatal(1, "Unable to setup your '%s' account" % [@sAccountName])
340
- when nil
341
- Logging.fatal(1, "Unable to execute 'hpcloud' cli. Please check hpcloud installation.")
342
- end
343
-
344
- provider_load() # To ensure latest provider data are loaded
345
-
346
- setup_tenant_name()
347
- end
348
-
349
- def provider_load()
350
- # TODO: Should be provider agnostic
351
- # Loading HPCloud account setting in Config.
352
- hpc_account_file = File.join($HPC_ACCOUNTS, @sAccountName)
353
-
354
- # Maestro compute use openstack. It requires meta tenant_name (not ID). Need to query HPC to get the Project Name from the ID.
355
- @oConfig.ExtraLoad(hpc_account_file, :hpc_accounts, @sAccountName)
356
- end
357
-
358
- # Maestro uses fog/openstack to connect to the cloud. It needs Tenant name instead of tenant ID.
359
- # Getting it from Compute connection and set it
360
- def setup_tenant_name()
361
- oSSLError=SSLErrorMgt.new # Retry object
362
- Logging.debug("Getting tenants from hpcloud cli libraries")
363
- begin
364
- tenants = Connection.instance.tenants(@sAccountName)
365
- rescue => e
366
- if not oSSLError.ErrorDetected(e.message,e.backtrace)
367
- retry
368
- end
369
- Logging.fatal(1, 'Network: Unable to connect.')
370
- end
371
- tenant_id = rhGet(@oConfig.ExtraGet(:hpc_accounts, @sAccountName, :credentials), :tenant_id)
372
- tenant_name = nil
373
- tenants.each { |elem| tenant_name = elem['name'] if elem['id'] == tenant_id }
374
- if tenant_name
375
- Logging.debug("Tenant ID '%s': '%s' found." % [tenant_id, tenant_name])
376
- hCompute = { :tenant_name => tenant_name }
377
- rhSet(@hAccountData, hCompute, :maestro)
378
- else
379
- Logging.error("Unable to find the tenant Name for '%s' ID." % tenant_id)
380
- end
381
- @oConfig.set('tenants', tenants)
382
- end
383
-
384
- # Setting up DNS information
385
- def setup_dns()
386
- # Get HPCloud account definition
387
- yHPC = @oConfig.ExtraGet(:hpc_accounts, @sAccountName)
388
- # Get Forj account definition
389
- yDNS = rhGet(@hAccountData, :dns)
390
- yDNS = {} if not yDNS
391
-
392
- 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?"
393
- if agree(sAsk)
394
- # Getting tenants
395
- tenants = @oConfig.get(:tenants)
396
-
397
- # Question about DNS Tenant ID
398
- # In HPCloud : credentials/tenant_id
399
- aDNS_TenantIDs = []
400
- sDNS_TenantIDs = rhGet(yDNS, :tenant_id)
401
- sDNS_TenantIDs = rhGet(yHPC, :credentials, :tenant_id) if not sDNS_TenantIDs and rhExist?(yHPC, :credentials, :tenant_id) > 0
402
-
403
- Logging.message("Following are the list of know project attached to your credentials:")
404
- tenants.each do | elem |
405
- aDNS_TenantIDs.push(elem['id'])
406
- if sDNS_TenantIDs and elem['id'] == sDNS_TenantIDs
407
- Logging.message("%s - %s" % [ANSI.bold+elem['id']+ANSI.reset, elem['name']])
408
- else
409
- Logging.message("%s - %s" % [elem['id'], elem['name']])
410
- end
411
- end
412
-
413
- sOption = ' [%s]' % aDNS_TenantIDs.join(', ') if aDNS_TenantIDs.length() == 2
414
- sDNS_TenantID = ask('Enter DNS Tenant ID:%s' % sOption) do |q|
415
- q.default = sDNS_TenantIDs
416
- q.validate = /[\w\d]+/
417
- end
418
- yDNS[:tenant_id] = sDNS_TenantID.to_s
419
-
420
- # Question about DNS Service
421
- # In HPCloud : regions/dns
422
- if sDNS_TenantID == rhGet(yHPC, :credentials, :tenant_id)
423
- sDNS_Service = rhGet(yHPC, :regions, :dns)
424
- else
425
- aDNS_Services = []
426
- aDNS_Services.push(rhGet(yDNS, :service)) if rhExist?(yDNS, :service) > 0
427
-
428
- sDNS_Service = ask("Enter DNS Service for the Tenant ID '%s' (ex: region-a.geo-1): " % sDNS_TenantID) do |q|
429
- q.validate = /[\w.-]+/
430
- end
431
- end
432
- yDNS[:service] = sDNS_Service.to_s
433
-
434
- else
435
- yDNS.delete(:service)
436
- yDNS.delete(:tenant_id)
437
- Logging.message("Maestro won't manage any Domain with '%s' provider." % [ rhGet(@hAccountData, [:account, :provider])])
438
- end
439
- # Question about Domain name
440
- previousDomainName = rhGet(yDNS, :domain_name) if rhExist?(yDNS, :domain_name) > 0
441
-
442
- sDNS_DomainName = ask('Enter Domain name to add to hostnames (puppet requirement) (ex: dev.forj.io):') do |q|
443
- q.default = previousDomainName if previousDomainName
444
- q.validate = /[\w._]+/
445
- end
446
- yDNS[:domain_name] = sDNS_DomainName.to_s
447
-
448
- # Attaching to the account.
449
- rhSet(@hAccountData, yDNS, :dns)
450
- end
451
-
452
- # manage keypair attached to a FORJ account.
453
- def keypair_setup()
454
-
455
- # Getting Account keypair information
456
- yCreds = rhGet(@hAccountData, :credentials)
457
- key_name = @oConfig.get(:keypair_name, yCreds )
458
- orig_key_path = File.expand_path(@oConfig.get(:keypair_path, yCreds))
459
-
460
- 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
461
-
462
- key_name = ask ("Please provide the keypair name used by default on this account:") do | q |
463
- q.default = key_name
464
- q.validate = /.*+/
465
- end
466
- key_name = key_name.to_s
467
-
468
- key_path = nil
469
- while not key_path
470
- key_path = ask ("Please provide the SSH private key path used by default on this account:") do | q |
471
- q.default = orig_key_path
472
- q.validate = /.*+/
473
- end
474
- keys_entered = keypair_detect(key_name, key_path)
475
- if not keys_entered[:private_key_exist? ] and not keys_entered[:public_key_exist? ]
476
- if agree("The key you entered was not found. Do you want to create this one?")
477
- base_dir = keys_entered[:keypair_path]
478
- if not File.directory?(base_dir)
479
- if agree("'%s' doesn't exist. Do you want to create it?" % base_dir)
480
- AppInit.ensure_dir_exists(base_dir)
481
- end
482
- end
483
- else
484
- key_path = nil
485
- end
486
- end
487
- end
488
- keys_imported = nil
489
- keys_imported = keypair_detect(key_name, @oConfig.LocalGet(key_name, :imported_keys)) if @oConfig.LocalExist?(key_name, :imported_keys)
490
-
491
- if keys_imported and keys_imported[:key_basename] != keys_entered[:key_basename] and $FORJ_KEYPAIRS_PATH != keys_entered[:keypair_path]
492
- 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])
493
- key_name = nil
494
- end
495
-
496
-
497
- keys = keypair_detect(key_name, key_path)
498
-
499
- Logging.info("Configuring forj keypair '%s'" % [ keys[:keypair_name] ] )
500
-
501
-
502
- private_key_file = File.join(keys[:keypair_path], keys[:private_key_name])
503
- public_key_file = File.join(keys[:keypair_path], keys[:public_key_name])
504
-
505
-
506
- # Creation sequences
507
- if not keys[:private_key_exist? ]
508
- # Need to create a key. ask if we need so.
509
- Logging.message("The private key file attached to keypair named '%s' is 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[:keypair_name])
510
- real_key_path = File.expand_path(ask("Private key file path:") do |q|
511
- q.validate = /\w+/
512
- q.default = private_key_file
513
- end)
514
- if not File.exists?(real_key_path)
515
- AppInit.ensure_dir_exists(File.dirname(real_key_path))
516
- command = 'ssh-keygen -t rsa -f %s' % real_key_path
517
- Logging.debug("Executing '%s'" % command)
518
- system(command)
519
- end
520
- if not File.exists?(real_key_path)
521
- 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])
522
- else
523
- if real_key_path != key_path and not @oConfig.LocalDefaultExist?('keypair_path')
524
- Logging.debug("Saving forj keypair '%s' as default." % [real_key_path] )
525
- @oConfig.LocalSet('keypair_path', real_key_path)
526
- @oConfig.SaveConfig()
527
- end
528
- end
529
- end
530
-
531
- if not keys[:public_key_exist? ]
532
- Logging.message("Your public key '%s' was not found. Getting it from the private one. It may require your passphrase." % [public_key_file])
533
- command = 'ssh-keygen -y -f %s > %s' % [private_key_file,public_key_file ]
534
- Logging.debug("Executing '%s'" % command)
535
- system(command)
536
- end
537
-
538
- forj_private_key_file = File.join($FORJ_KEYPAIRS_PATH, key_name )
539
- forj_public_key_file = File.join($FORJ_KEYPAIRS_PATH, key_name + ".pub")
540
-
541
- # Saving sequences
542
- if keys[:keypair_path] != $FORJ_KEYPAIRS_PATH
543
- if not File.exists?(forj_private_key_file)
544
- Logging.info("Importing key pair to FORJ keypairs list.")
545
- FileUtils.copy(private_key_file, forj_private_key_file)
546
- FileUtils.copy(public_key_file, forj_public_key_file)
547
- # Attaching this keypair to the account
548
- rhSet(@hAccountData, key_name, :credentials, 'keypair_name')
549
- rhSet(@hAccountData, forj_private_key_file, :credentials, 'keypair_path')
550
- @oConfig.LocalSet(key_name.to_s, private_key_file, :imported_keys)
551
- @oConfig.SaveConfig()
552
- end
553
- end
554
- end
555
-
556
- def setup_maestro_creds()
557
- # Check required global data
558
- if not $FORJ_CREDS_PATH
559
- Logging.fatal(1, "Internal error: '$FORJ_CREDS_PATH' missing.")
560
- end
561
- if not Helpers.dir_exists?($FORJ_CREDS_PATH)
562
- Logging.fatal(1, "Internal error: '%s' doesn't exist." % $FORJ_CREDS_PATH)
563
- end
564
-
565
- Logging.info("Completing hpcloud account '%s' information." % [@sAccountName] )
566
-
567
- forj_user = rhGet(@hAccountData, :credentials, :os_user)
568
- enc_hpcloud_os_key = rhGet(@hAccountData, :credentials, :os_enckey)
569
-
570
- hpcloud_os_user = ask('Enter hpcloud username: ') do |q|
571
- q.validate = /\w+/
572
- q.default = forj_user if forj_user
573
- end
574
-
575
- # Checking key file used to encrypt/decrypt passwords
576
- key_file = File.join($FORJ_CREDS_PATH, '.key')
577
- if not File.exists?(key_file)
578
- # Need to create a random key.
579
- entr = {
580
- :key => rand(36**10).to_s(36),
581
- :salt => Time.now.to_i.to_s,
582
- :iv => Base64::strict_encode64(OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv)
583
- }
584
-
585
- Logging.debug("Writing '%s' key file" % key_file)
586
- File.open(key_file, 'w') do |out|
587
- out.write(Base64::encode64(entr.to_yaml))
588
- end
589
- else
590
- Logging.debug("Loading '%s' key file" % key_file)
591
- encoded_key = IO.read(key_file)
592
- entr = YAML.load(Base64::decode64(encoded_key))
593
- end
594
-
595
- if enc_hpcloud_os_key
596
- begin
597
- hpcloud_os_key_hidden = '*' * Encryptor.decrypt(
598
- :value => Base64::strict_decode64(enc_hpcloud_os_key),
599
- :key => entr[:key],
600
- :iv => Base64::strict_decode64(entr[:iv]),
601
- :salt => entr[:salt]
602
- ).length
603
- rescue => e
604
- Logging.error("Unable to decrypt your password. You will need to re-enter it.")
605
- enc_hpcloud_os_key = ""
606
- else
607
- hpcloud_os_key_hidden="[%s]" % hpcloud_os_key_hidden
608
- Logging.message("A password is already set for '%s'. If you want to keep it, just press Enter" % [hpcloud_os_user])
609
- end
610
- else
611
- hpcloud_os_key_hidden = ""
612
- end
613
-
614
- hpcloud_os_key = ""
615
- while hpcloud_os_key == ""
616
- # ask for password.
617
- hpcloud_os_key = ask("Enter hpcloud password for '%s': %s" % [hpcloud_os_user, hpcloud_os_key_hidden]) do |q|
618
- q.echo = '*'
619
- end
620
- if hpcloud_os_key == "" and enc_hpcloud_os_key
621
- hpcloud_os_key = Encryptor.decrypt(
622
- :value => Base64::strict_decode64(enc_hpcloud_os_key),
623
- :key => entr[:key],
624
- :iv => Base64::strict_decode64(entr[:iv]),
625
- :salt => entr[:salt]
626
- )
627
- else
628
- Logging.message("The password cannot be empty.") if hpcloud_os_key == ""
629
- end
630
- end
631
- enc_hpcloud_os_key = Base64::strict_encode64(
632
- Encryptor.encrypt(
633
- :value => hpcloud_os_key,
634
- :key => entr[:key],
635
- :iv => Base64::strict_decode64(entr[:iv]),
636
- :salt => entr[:salt]
637
- )
638
- )
639
-
640
- cloud_fog = File.join($FORJ_CREDS_PATH, @sAccountName+'.g64')
641
-
642
- # Security fix: Remove old temp file with clear password.
643
- old_file = '%s/master.forj-13.5' % [$FORJ_CREDS_PATH]
644
- File.delete(old_file) if File.exists?(old_file)
645
- old_file = '%s/creds' % [$FORJ_CREDS_PATH]
646
- File.delete(old_file) if File.exists?(old_file)
647
-
648
- provider_load() if not @oConfig.ExtraExist?(:hpc_accounts, @sAccountName)
649
- hpc_creds = @oConfig.ExtraGet(:hpc_accounts, @sAccountName, :credentials)
650
-
651
- rhSet(@hAccountData, hpcloud_os_user.to_s, :credentials, :os_user)
652
- rhSet(@hAccountData, enc_hpcloud_os_key, :credentials, :os_enckey)
653
-
654
- IO.popen('gzip -c | base64 -w0 > %s' % [cloud_fog], 'r+') {|pipe|
655
- pipe.puts('HPCLOUD_OS_USER=%s' % [hpcloud_os_user] )
656
- pipe.puts('HPCLOUD_OS_KEY=%s' % [hpcloud_os_key] )
657
- pipe.puts('DNS_KEY=%s' % [hpc_creds[:account_id]] )
658
- pipe.puts('DNS_SECRET=%s' % [hpc_creds[:secret_key]])
659
- pipe.close_write
660
- }
661
- Logging.info("'%s' written." % cloud_fog)
662
- end
663
286
  # private functions
664
287
  private
665
288
  def _set(section, key, value)
data/lib/forj-config.rb CHANGED
@@ -64,18 +64,18 @@ def rhSet(yVal, value, *p)
64
64
  p=p.flatten
65
65
  if p.length() == 1
66
66
  if not yVal.nil?
67
- if value
67
+ if not value.nil?
68
68
  yVal[p[0]] = value
69
69
  else
70
70
  yVal.delete(p[0])
71
71
  end
72
72
  return yVal
73
73
  end
74
- if value
75
- ret = { p[0] => value }
76
- else
77
- ret = {}
78
- end
74
+ #~ if value
75
+ ret = { p[0] => value }
76
+ #~ else
77
+ #~ ret = {}
78
+ #~ end
79
79
  return ret
80
80
  end
81
81
  if not yVal.nil?