Module: Smash::CloudPowers::Zenv

Includes:
Helpers
Included in:
Auth, AwsResources, Node, Resource, SelfAwareness, Storage::Local, Synapse::Broadcast, Synapse::Pipe, Synapse::Queue::Board
Defined in:
lib/cloud_powers/zenv.rb

Overview

This module provides some environment variable management and functionality Hopefully it should provide us with some “Zen”, when dealing with normally annoying env issues. Meh, it probably won’t but I like the name, so it stays :} System ENV, dotenv ENV and instance variables are considered for now but this will also use elasticache/redis…some other stuff too, in the coming versions

Instance Method Summary collapse

Methods included from Helpers

#create_logger, #log_file, #logger

Methods included from PathHelp

#common_delimiter, #expand_path, #file_exists?, #file_search, #filename?, #job_exist?, #job_path, #job_require_path, #path_search, #paths_gcd, #paths_lcd, #to_path, #to_pathname, #to_realpath, #touch, #zlib_path

Methods included from LogicHelp

#attr_map, #called_from, #i_var_hash, #instance_attr_accessor, #smart_retry, #update_message_body

Methods included from LangHelp

#deep_modify_keys_with, #extract!, #find_and_remove, #format_error_message, #from_json, #modify_keys_with, #to_basic_hash, #to_camel, #to_hyph, #to_i_var, #to_pascal, #to_ruby_file_name, #to_snake, #valid_json?, #valid_url?

Instance Method Details

#env_vars(key = '') ⇒ Object

Search through the Dotenv variables for a key or if no key is given, return all the .env-vars and their values

Parameters

  • key String -



20
21
22
23
# File 'lib/cloud_powers/zenv.rb', line 20

def env_vars(key = '')
  return ENV if key.empty? || key.nil?
  ENV[to_snake(key).upcase]
end

#i_vars(key = '') ⇒ Object

Search through the instance variables for a key or if no key is given, return all the i-vars and their values

Parameters [key <String]: The key to search for

Returns the value of the key searched for



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/cloud_powers/zenv.rb', line 32

def i_vars(key = '')
  name = to_i_var(key)

  # if no key is given, return a +Hash+ of all i-var/value pairs
  if key.empty? || key.nil?
    self.instance_variables.inject({}) do |r, v|
      r.tap { |h| h[to_i_var(v)] = self.instance_variable_get(v.to_s) }
    end
  else
    self.instance_variable_get(name)
  end
end

#lsof_cwdObject



56
57
58
# File 'lib/cloud_powers/zenv.rb', line 56

def lsof_cwd
  to_realpath((`lsof -p #{Process.pid} | grep cwd`).split(' ').last.strip)
end

#pidObject

Get the PID for the current process

Returns

  • String

Notes

  • See ::Process#pid()



52
53
54
# File 'lib/cloud_powers/zenv.rb', line 52

def pid
  Process.pid
end

#proc_cwdObject

Ask Linux systems what directory the process is running from.

Returns

  • Pathname - the lcoation containing the file that was called to run this program

  • nil - if the OS doesn’t support the proc methods, nil is returned



81
82
83
84
85
86
87
88
# File 'lib/cloud_powers/zenv.rb', line 81

def proc_cwd
  begin
    to_realpath(`ls -l /proc/#{pid}/cwd`.split(/\->\s?/).last.strip)
  rescue NoMethodError => e
    logger.debug('this system does not support /proc files system queries')
    nil
  end
end

#process_searchObject



60
61
62
63
# File 'lib/cloud_powers/zenv.rb', line 60

def process_search
  search_results = proc_cwd || lsof_cwd || ps_cwd || nil
  paths_lcd(search_results, called_from)
end

#project_rootObject

PROJECT_ROOT, project_root= your_project_root or @project_root should be set as early as possible in this Node’s initilize process. This method tries to search for it, using Zenv#zfind and if that fails, another search through system tools is run to make a best attempt at finding the lowest common path.

Returns Pathname - path to the project root or where ever `pwd` resolves to for the caller

Notes

  • TODO: improve this…it needs to find the gem’s method’s caller’s project

root or at least the gem’s method’s caller’s file’s location.

Example

/home/ubuntu/cerebrum$ ruby -e cerebrum.rb 'Cerebrum.new.project_root'
# => '/home/ubuntu/cerebrum/'

or project_root invoked from somewhere in /Users/crazyman/.ssh/why/all/the/wasted_time

<tt>called_from</tt> is
<tt>/Users/crazyman/.ssh/why/all/the/insanity/go_nuts.rb#ok():(line -999999999.9)</tt>

and

<tt>/proc/<pid>/cwd</tt> is /Users/crazyman/.ssh/why/all/the/madness/

and

# caller is
[
  ... , /Users/crazyman/.rbenv/versions/2.4.0/lib/ruby/
gems/2.4.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb, ...]</tt>

and

<tt>ps -ef | grep #{pid}...</tt> is <tt>[
..., /Users/crazyman/.rbenv/versions/2.4.0/lib/ruby/
gems/2.4.0/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb, ...]</tt>

then

project_root
# => '/Users/crazyman/.ssh/why/all/the'


152
153
154
155
156
157
158
159
160
# File 'lib/cloud_powers/zenv.rb', line 152

def project_root
  if @project_root.nil?
    new_root = to_realpath(zfind('project root') || process_search)
    logger.info("project root set to:#{new_root} by:#{called_from}")
    @project_root = new_root
  else
    @project_root
  end
end

#project_root=(path) ⇒ Object

Manually set the @project_root i-var as a Pathname object.

Parameters

  • String|Pathname - new path to the project root

Returns @project_root [Pathname]

Example

project_root
# => '/home/ubuntu/cerebrum/'
project_root = Pathname.new(`pwd`)
project_root == `pwd`
# => true


176
177
178
# File 'lib/cloud_powers/zenv.rb', line 176

def project_root=(path)
  @project_root = to_pathname(path).realpath
end

#ps_cwdObject

Get the location of the current working directory for the project that is calling this method.

Returns

  • Pathname

Notes:

  • Tested on Ubuntu, Mac and Centos 7

  • Similar methods:

    • proc_cwd

    • called_from



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/cloud_powers/zenv.rb', line 101

def ps_cwd
  begin
    ef = `ps -ef | grep #{pid}`.split("\n").first.split(' ').last
    aux = `ps aux | grep #{pid}`.split("\n").first.split(' ').last
    Pathname.new(/[A-Za-z]*\.[A-Za-z]+$/ =~ ef ? ef : aux).realpath
  rescue Exception => e
    if e.nil?
      logger.debug('This system does not support ps functionality')
      nil
    else
      super
    end
  end
end

#system_vars(key = '') ⇒ Object

Search through the system environment variables for a key or if no key is given, return all the system-env-vars and their values

Parameters

  • key String - the key to search for

Returns

  • if a key is given as a parameter, String

  • if no key is given as a parameter, Hash

with this structure { key => value, … } is returned for all keys with a value. Keys with no value are ommitted from the result.



191
192
193
# File 'lib/cloud_powers/zenv.rb', line 191

def system_vars(key = '')
  (key.empty? || key.nil?) ? ::ENV.to_h : ::ENV[to_snake(key).upcase]
end

#zfind(key = '') ⇒ Object

ZFind looks for the key in a preditermined order of importance:

  • i-vars are considered first becuase they might be tracking different locations for multiple jobs or something like that.

  • dotenv files are second because they were manually set, so for sure it’s important

  • System Env variables are up next. Hopefully by this time we’ve found our information but if not, it should “search” through the system env too.

Parameters

  • key String|Symbol - the key to search for

Returns

  • Object - whatever type you were looking for, storing or accidentally now dealing with is what can be returned

Notes

  • TODO: implement a search for all 3 that can find close matches



212
213
214
# File 'lib/cloud_powers/zenv.rb', line 212

def zfind(key = '')
  i_vars(key) || env_vars(key) || system_vars(key)
end

#zselect(key = '') ⇒ Object

Get anything that matches, within the same area that #zfind can search through. This has the feel of Hash#select./



218
219
220
221
222
223
224
225
226
227
# File 'lib/cloud_powers/zenv.rb', line 218

def zselect(key = '')
  vars = system_vars.merge(env_vars).merge(i_vars)
  if (key.empty? || key.nil?)
    vars.values
  else
    vars.select { |k,v| %r"#{to_snake(key)}" =~ to_snake(k) }.values
    # results = vars.select { |k,v| %r"#{to_snake(key)}" =~ to_snake(k) }
    # (results.count == 1) ? results.values.first : results
  end
end