lib/cloud_powers/zenv.rb in cloud_powers-1.0.1 vs lib/cloud_powers/zenv.rb in cloud_powers-1.1.0
- old
+ new
@@ -9,39 +9,18 @@
# 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
module Zenv
include Smash::CloudPowers::Helpers
- # Attempts to find a file by searching the current directory for the file
- # then walking up the file tree and searching at each stop all the way up
- # to the root directory
- #
- # Parameters
- # * name +String+ - name of the file or directory to find
- #
- # Returns
- # +Pathname+ - path to the file or directory given as the +name+ parameter
- def file_tree_search(name)
- next_dir = Pathname.new(`pwd`.strip).parent
- current_dir = Pathname.new(`pwd`.strip)
- until(next_dir == current_dir) do
- path = Dir.glob("#{current_dir}/#{name}").first
- return current_dir unless path.nil?
- current_dir = next_dir
- next_dir = next_dir.parent
- end
- return nil
- end
-
# Search through the {Dotenv}[https://github.com/bkeepers/dotenv]
# variables for a key or if no key is given, return all the .env-vars
# and their values
#
# Parameters
# * key +String+ -
def env_vars(key = '')
- return ENV if key.empty?
+ return ENV if key.empty? || key.nil?
ENV[to_snake(key).upcase]
end
# Search through the instance variables for a key or if no key is given,
# return all the i-vars and their values
@@ -52,65 +31,152 @@
# the value of the +key+ searched for
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?
- return self.instance_variables.inject({}) do |r, v|
- r.tap { |h| h[name] = self.instance_variable_get(name) }
+ 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
- self.instance_variable_get(name)
+ # Get the PID for the current process
+ #
+ # Returns
+ # * +String+
+ #
+ # Notes
+ # * See <tt>::Process#pid()</tt>
+ def pid
+ Process.pid
end
- # PROJECT_ROOT should be set as early as possible in this Node's initilize
- # method. This method tries to search for it, using #zfind() and if a `nil`
- # result is returned from that search, `pwd` is used as the PROJECT_ROOT.
+ def lsof_cwd
+ to_realpath((`lsof -p #{Process.pid} | grep cwd`).split(' ').last.strip)
+ end
+
+ def process_search
+ search_results = proc_cwd || lsof_cwd || ps_cwd || nil
+ paths_lcd(search_results, called_from)
+ end
+
+ # # Search the output of <tt>`ps ...`</tt> to find this process' working
+ # # directory
+ # #
+ # # Returns
+ # # * +Pathname+
+ # def path_resolution(one, two)
+ # logger.debug("path_resolution request from #{caller.first} as #{proc_cwd}")
+ # Pathname.new(sys_command_output).realpath
+ # end
+
+ # Ask <i>Linux</i> 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
+ 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
+
+ # 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:
+ # * * <tt>proc_cwd</tt>
+ # * * <tt>called_from</tt>
+ 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
+
+ # <tt>PROJECT_ROOT</tt>, <tt>project_root= your_project_root</tt> or
+ # <tt>@project_root</tt> should be set as early as possible in this
+ # Node's initilize process. This method tries to search for it, using
+ # <tt>Zenv#zfind</tt> 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 <tt>`pwd`</tt> 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
- # # called from cerebrum/cerebrum.rb in /home/ubuntu
- # project_root
+ # /home/ubuntu/cerebrum$ ruby -e cerebrum.rb 'Cerebrum.new.project_root'
# # => '/home/ubuntu/cerebrum/'
- # # or
- # # called from go_nuts.rb#begin_going_crazy():(line -999999999.9) in /Users/crazyman/.ssh/why/all/the/madness/
+ # or
+ # <tt>project_root</tt> invoked from somewhere in
+ # <tt>/Users/crazyman/.ssh/why/all/the/wasted_time</tt>
+ # <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/madness/'
+ # # => '/Users/crazyman/.ssh/why/all/the'
def project_root
if @project_root.nil?
- file_home = Pathname.new(
- caller_locations.first.path.strip.split(/\//).last).realdirpath.parent
- # path = (zfind('PROJECT_ROOT') or file_home)
- @project_root = Pathname.new(file_home)
+ 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
- @project_root
end
# Manually set the +@project_root+ i-var as a +Pathname+ object.
#
# Parameters
# * +String+|+Pathname+ - new path to the project root
#
# Returns
- # +Pathname+ - +@project_root+
+ # +@project_root+ [+Pathname+]
#
# Example
# project_root
# # => '/home/ubuntu/cerebrum/'
# project_root = Pathname.new(`pwd`)
# project_root == `pwd`
# # => true
- def project_root=(var)
- @project_root = Pathname.new(var)
+ def project_root=(path)
+ @project_root = to_pathname(path).realpath
end
# Search through the system environment variables for a key or if no key
# is given, return all the system-env-vars and their values
#
@@ -121,25 +187,11 @@
# * 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.
def system_vars(key = '')
- name = to_snake(key).upcase
- if key.empty?
- # Separate key-value pairs from the large string received by `ENV`
- separate_pairs = `ENV`.split(/\n/).map do |string_pair|
- string_pair.split('=')
- end
- # Separate key-value pairs from each other into a hash of
- # { key => value, other_key => other_value }
- # * keys with no value are removed
- separate_pairs.inject({}) do |res, pair|
- res.tap { |h_res| h_res[pair.first] = pair.last unless (pair.first == pair.last) }
- end
- else
- Object::ENV.has_key?(name) ? Object::ENV.fetch(name) : nil
- end
+ (key.empty? || key.nil?) ? ::ENV.to_h : ::ENV[to_snake(key).upcase]
end
# 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.
@@ -150,16 +202,29 @@
#
# Parameters
# * key +String+|+Symbol+ - the key to search for
#
# Returns
- # * +String+
+ # * +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
- def zfind(key)
- project_root if @project_root.nil?
+ def zfind(key = '')
i_vars(key) || env_vars(key) || system_vars(key)
+ end
+
+ # Get anything that matches, within the same area that <tt>#zfind</tt>
+ # can search through. This has the feel of <tt>Hash#select</tt>./
+ 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
end
end
end