lib/forj-account.rb in forj-0.0.43 vs lib/forj-account.rb in forj-0.0.44
- old
+ new
@@ -43,14 +43,42 @@
Dir.foreach($FORJ_ACCOUNTS_PATH) { |x| aAccounts << x if not x.match(/^\..?$/) }
aAccounts
end
end
+# ForjAccount manage a list of key/value grouped by section.
+# The intent of ForjAccount is to attach some keys/values to
+# an account to help end users to switch between each of them.
+#
+# ForjAccount based on ForjConfig (see forj-config.rb)
+# ensure ForjConfig and ForjAccount defines following common functions
+# - set (key, value)
+# - get (key)
+#
+# This means that key HAVE to be unique across sections
+# By default, keys maps with the same key name in ForjConfig.
+# But we can redefine the ForjConfig mapping of any key on need.
+#
+# ForjConfig, loads Account meta structure from defaults.yaml, sections
+#
+# defaults.yaml structure is:
+# sections:
+# default: => defines key/values recognized by ForjAccount to be only managed by ForjConfig.
+# <key> :
+# :desc : <value> => defines the ForjConfig key description.
+# <section>: Define a section name. For each keys on this section, the account file will kept those data under this section.
+# <key>:
+# :desc: defines the key description.
+# :readonly: true if this key cannot be updated by ForjAccount.set
+# :account_exclusive: true if this key cannot be predefined on ForjConfig keys list
+# :default: <ForjConfig real key name> Used to map the ForjAccount key to a different ForjConfig key name.
+
class ForjAccount
attr_reader :sAccountName
attr_reader :hAccountData
+ attr_reader :oConfig
# This object manage data located in oConfig[:hpc_accounts/AccountName]
def initialize(oConfig)
# Initialize object
@@ -65,83 +93,185 @@
sProvider = 'hpcloud'
sProvider = @oConfig.get(:provider) if @oConfig.get(:provider)
@hAccountData = {}
- rhSet(@hAccountData, @sAccountName, [:account, :name]) if rhExist?(@hAccountData, [:account, :name]) != 2
- rhSet(@hAccountData, sProvider, [:account, :provider]) if rhExist?(@hAccountData, [:account, :provider]) != 2
+ _set(:account, :name, @sAccountName) if exist?(:name) != 'hash'
+ _set(:account, :provider, sProvider) if exist?(:provider) != 'hash'
+
end
- # oForjAccount data get are retrieved from the account file under section described in defaults.yaml (:account_section_mapping), as soon as this mapping exists.
- # If not found, get the data from the local configuration file. Usually ~/.forj/config.yaml
- # If not found, get the data from defaults.yaml
+ # oForjAccount data get at several levels:
+ # - get the data from runtime (runtimeSet/runtimeGet)
+ # - otherwise, get data from account file under section described in defaults.yaml (:account_section_mapping), as soon as this mapping exists.
+ # - otherwise, get the data from the local configuration file. Usually ~/.forj/config.yaml
+ # - otherwise, get the data from defaults.yaml
# otherwise, use the get default parameter as value. Default is nil.
def get(key, default = nil)
return nil if not key
key = key.to_sym if key.class == String
- section = rhGet(@oConfig.getAppDefault(:account_section_mapping, key), :section)
- yInterm = nil
- if section
- yInterm = rhGet(@hAccountData, section)
- else
+
+ return @oConfig.runtimeGet(key) if @oConfig.runtimeExist?(key)
+
+ section = ForjDefault.get_meta_section(key)
+ default_key = key
+
+ if not section
Logging.debug("ForjAccount.get: No section found for key '%s'." % [key])
+ else
+ return rhGet(@hAccountData, section, key) if rhExist?(@hAccountData, section, key) == 2
+
+ hMeta = @oConfig.getAppDefault(:sections)
+ if rhExist?(hMeta, section, key, :default) == 3
+ default_key = rhGet(hMeta, section, key, :default)
+ Logging.debug("ForjAccount.get: Reading default key '%s' instead of '%s'" % [default_key, key])
+ end
+ return default if rhExist?(hMeta, section, key, :account_exclusive) == 3
end
- @oConfig.get(key, yInterm , default )
+
+ @oConfig.get(default_key , default )
end
def exist?(key)
return nil if not key
key = key.to_sym if key.class == String
- section = rhGet(@oConfig.getAppDefault(:account_section_mapping, key), :section)
- yInterm = nil
- yInterm = rhGet(@hAccountData, section) if section
- @oConfig.exist?(key, yInterm)
+ section = ForjDefault.get_meta_section(key)
+ if not section
+ Logging.debug("ForjAccount.exist?: No section found for key '%s'." % [key])
+ return nil
+ end
+ return @sAccountName if rhExist?(@hAccountData, section, key) == 2
+ hMeta = @oConfig.getAppDefault(:sections)
+ if rhExist?(hMeta, section, key, :default) == 3
+ default_key = rhGet(hMeta, section, key, :default)
+ Logging.debug("ForjAccount.exist?: Reading default key '%s' instead of '%s'" % [default_key, key])
+ else
+ default_key = key
+ end
+ return nil if rhExist?(hMeta, section, key, :account_exclusive) == 3
+
+ @oConfig.exist?(default_key)
+
end
+ # Return true if readonly. set won't be able to update this value.
+ # Only _set (private function) is able.
+ def readonly?(key)
+ return nil if not key
+
+ key = key.to_sym if key.class == String
+ section = ForjDefault.get_meta_section(key)
+
+ rhGet(@oConfig.getAppDefault(:sections, section), key, :readonly)
+
+ end
+
+ def meta_set(key, hMeta)
+ key = key.to_sym if key.class == String
+ section = ForjDefault.get_meta_section(key)
+ hCurMeta = rhGet(@oConfig.getAppDefault(:sections, section), key)
+ hMeta.each { | mykey, myvalue |
+ rhSet(hCurMeta, myvalue, mykey)
+ }
+ end
+
+ def meta_exist?(key)
+ return nil if not key
+
+ key = key.to_sym if key.class == String
+ section = ForjDefault.get_meta_section(key)
+ rhExist?(@oConfig.getAppDefault(:sections, section), key) == 1
+ end
+
+ def get_meta_section(key)
+ key = key.to_sym if key.class == String
+ rhGet(@account_section_mapping, key)
+ end
+
+ def meta_type?(key)
+ return nil if not key
+
+ section = ForjDefault.get_meta_section(key)
+
+ return section if section == :default
+ @sAccountName
+ end
+
+ # Loop on account metadata
+ def metadata_each
+ rhGet(ForjDefault.dump(), :sections).each { | section, hValue |
+ next if section == :default
+ hValue.each { | key, value |
+ yield section, key, value
+ }
+ }
+ end
+
+ # Return true if exclusive
+ def exclusive?(key)
+ return nil if not key
+
+ key = key.to_sym if key.class == String
+ section = ForjDefault.get_meta_section(key)
+
+ rhGet(@oConfig.getAppDefault(:sections, section), key, :account_exclusive)
+ end
+
+ # This function update a section/key=value if the account structure is defined.
+ # If no section is defined, set it in runtime config.
def set(key, value)
return nil if not key
key = key.to_sym if key.class == String
- section = rhGet(@oConfig.getAppDefault(:account_section_mapping, key), :section)
- return nil if not section
- rhSet(@hAccountData, value, section, key)
+ section = ForjDefault.get_meta_section(key)
+
+ return @oConfig.set(key, value) if not section
+ return nil if readonly?(key)
+ _set(section, key, value)
end
def del(key)
return nil if not key
key = key.to_sym if key.class == String
- section = rhGet(@oConfig.getAppDefault(:account_section_mapping, key), :section)
+ section = ForjDefault.get_meta_section(key)
return nil if not section
rhSet(@hAccountData, nil, section, key)
end
def getAccountData(section, key, default=nil)
return rhGet(@hAccountData, section, key) if rhExist?(@hAccountData, section, key) == 2
default
end
- def ac_load(sAccountName = @sAccountName)
+ def ac_new(sAccountName)
+ return nil if sAccountName.nil?
+ @sAccountName = sAccountName
+ @sAccountFile = File.join($FORJ_ACCOUNTS_PATH, @sAccountName)
+
+ @hAccountData = {:account => {:name => sAccountName, :provider => @oConfig.get(:provider_name)}}
+ end
+
+ def ac_load(sAccountName = @sAccountName, bHPCloudLoad = true)
# Load Account Information
if sAccountName != @sAccountName
- @sAccountName = sAccountName
- @sAccountFile = File.join($FORJ_ACCOUNTS_PATH, @sAccountName)
+ ac_new(sAccountName)
end
if File.exists?(@sAccountFile)
@hAccountData = @oConfig.ExtraLoad(@sAccountFile, :forj_accounts, @sAccountName)
# Check if hAccountData are using symbol or needs to be updated.
- sProvider = @oConfig.get(:provider, nil, 'hpcloud')
+ sProvider = @oConfig.get(:provider, 'hpcloud')
rhSet(@hAccountData, @sAccountName, :account, :name) if rhExist?(@hAccountData, :account, :name) != 2
rhSet(@hAccountData, sProvider, :account, :provider) if rhExist?(@hAccountData, :account, :provider) != 2
- provider_load()
+ provider_load() if bHPCloudLoad
if rhKeyToSymbol?(@hAccountData, 2)
- @hAccountData = rhKeyToSymbol(@hAccountData, 2)
+ @hAccountData = rhKeyToSymbol(@hAccountData, 2)
self.ac_save()
end
return @hAccountData
end
nil
@@ -176,11 +306,11 @@
# Check/create keypair
self.keypair_setup()
# Checking cloud connection
Logging.message("Checking cloud connection")
- ForjConnection.new(@oConfig)
+ ForjConnection.new(self)
Logging.message("Setup '%s' done. Thank you." % @sAccountName)
end
def setup_provider_account()
@@ -234,11 +364,11 @@
tenant_name = nil
tenants.each { |elem| tenant_name = elem['name'] if elem['id'] == tenant_id }
if tenant_name
Logging.debug("Tenant ID '%s': '%s' found." % [tenant_id, tenant_name])
hCompute = { :tenant_name => tenant_name }
- rhSet(@hAccountData, hCompute, :compute)
+ rhSet(@hAccountData, hCompute, :maestro)
else
Logging.error("Unable to find the tenant Name for '%s' ID." % tenant_id)
end
@oConfig.set('tenants', tenants)
end
@@ -332,16 +462,16 @@
key_path = ask ("Please provide the SSH private key path used by default on this account:") do | q |
q.default = orig_key_path
q.validate = /.*+/
end
keys_entered = keypair_detect(key_name, key_path)
- if not keys_entered[:private_key_exist?] and not keys_entered[:public_key_exist?]
+ if not keys_entered[:private_key_exist? ] and not keys_entered[:public_key_exist? ]
if agree("The key you entered was not found. Do you want to create this one?")
base_dir = keys_entered[:keypair_path]
if not File.directory?(base_dir)
if agree("'%s' doesn't exist. Do you want to create it?" % base_dir)
- Helpers.ensure_dir_exists(base_dir)
+ AppInit.ensure_dir_exists(base_dir)
end
end
else
key_path = nil
end
@@ -364,19 +494,19 @@
private_key_file = File.join(keys[:keypair_path], keys[:private_key_name])
public_key_file = File.join(keys[:keypair_path], keys[:public_key_name])
# Creation sequences
- if not keys[:private_key_exist?]
+ if not keys[:private_key_exist? ]
# Need to create a key. ask if we need so.
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])
real_key_path = File.expand_path(ask("Private key file path:") do |q|
q.validate = /\w+/
q.default = private_key_file
end)
if not File.exists?(real_key_path)
- Helpers.ensure_dir_exists(File.dirname(real_key_path))
+ AppInit.ensure_dir_exists(File.dirname(real_key_path))
command = 'ssh-keygen -t rsa -f %s' % real_key_path
Logging.debug("Executing '%s'" % command)
system(command)
end
if not File.exists?(real_key_path)
@@ -388,11 +518,11 @@
@oConfig.SaveConfig()
end
end
end
- if not keys[:public_key_exist?]
+ if not keys[:public_key_exist? ]
Logging.message("Your public key '%s' was not found. Getting it from the private one. It may require your passphrase." % [public_key_file])
command = 'ssh-keygen -y -f %s > %s' % [private_key_file,public_key_file ]
Logging.debug("Executing '%s'" % command)
system(command)
end
@@ -520,26 +650,14 @@
pipe.puts('DNS_SECRET=%s' % [hpc_creds[:secret_key]])
pipe.close_write
}
Logging.info("'%s' written." % cloud_fog)
end
-end
+ # private functions
+ private
+ def _set(section, key, value)
+ return nil if not key or not section
-def ensure_forj_dirs_exists()
- # Function to create FORJ paths if missing.
+ rhSet(@hAccountData, value, section, key)
+ end
- # Defining Global variables
- $FORJ_DATA_PATH = File.expand_path(File.join('~', '.forj'))
- $FORJ_ACCOUNTS_PATH = File.join($FORJ_DATA_PATH, 'accounts')
- $FORJ_KEYPAIRS_PATH = File.join($FORJ_DATA_PATH, 'keypairs')
- $FORJ_CREDS_PATH = File.expand_path(File.join('~', '.cache', 'forj'))
-
- # TODO: To move to an hpcloud object.
- $HPC_KEYPAIRS = File.expand_path(File.join('~', '.hpcloud', 'keypairs'))
- $HPC_ACCOUNTS = File.expand_path(File.join('~', '.hpcloud', 'accounts'))
-
- Helpers.ensure_dir_exists($FORJ_DATA_PATH)
- Helpers.ensure_dir_exists($FORJ_ACCOUNTS_PATH)
- Helpers.ensure_dir_exists($FORJ_KEYPAIRS_PATH)
- FileUtils.chmod(0700, $FORJ_KEYPAIRS_PATH)
- Helpers.ensure_dir_exists($FORJ_CREDS_PATH)
end