gloo 0.7.3 → 0.7.7

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +38 -4
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +43 -17
  6. data/gloo.gemspec +3 -0
  7. data/lib/VERSION +1 -0
  8. data/lib/dependencies.rb +28 -0
  9. data/lib/gloo/app/engine.rb +4 -4
  10. data/lib/gloo/app/info.rb +11 -1
  11. data/lib/gloo/app/settings.rb +3 -3
  12. data/lib/gloo/core/baseo.rb +2 -0
  13. data/lib/gloo/core/factory.rb +22 -0
  14. data/lib/gloo/core/gloo_system.rb +9 -0
  15. data/lib/gloo/help/core/gloo_system.txt +3 -0
  16. data/lib/gloo/help/objs/cli/bar.txt +3 -0
  17. data/lib/gloo/help/objs/data/mysql.txt +40 -0
  18. data/lib/gloo/help/objs/data/query.txt +37 -0
  19. data/lib/gloo/help/objs/data/sqlite.txt +26 -0
  20. data/lib/gloo/help/objs/dev/git_repo.txt +2 -1
  21. data/lib/gloo/help/objs/dev/stats.txt +36 -0
  22. data/lib/gloo/help/objs/system/file.txt +7 -0
  23. data/lib/gloo/help/objs/system/ssh_exec.txt +30 -0
  24. data/lib/gloo/help/objs/web/http_post.txt +2 -0
  25. data/lib/gloo/help/objs/web/uri.txt +2 -1
  26. data/lib/gloo/objs/basic/boolean.rb +3 -0
  27. data/lib/gloo/objs/cli/bar.rb +22 -1
  28. data/lib/gloo/objs/data/mysql.rb +192 -0
  29. data/lib/gloo/objs/data/query.rb +176 -0
  30. data/lib/gloo/objs/data/sqlite.rb +159 -0
  31. data/lib/gloo/objs/dev/git.rb +13 -1
  32. data/lib/gloo/objs/dev/stats.rb +120 -0
  33. data/lib/gloo/objs/system/file_handle.rb +10 -1
  34. data/lib/gloo/objs/system/ssh_exec.rb +126 -0
  35. data/lib/gloo/objs/web/http_post.rb +53 -16
  36. data/lib/gloo/objs/web/json.rb +1 -1
  37. data/lib/gloo/objs/web/slack.rb +1 -1
  38. data/lib/gloo/objs/web/teams.rb +1 -1
  39. data/lib/gloo/objs/web/uri.rb +18 -1
  40. data/lib/gloo/persist/file_loader.rb +2 -0
  41. data/lib/gloo/utils/format.rb +21 -0
  42. data/lib/gloo/utils/stats.rb +205 -0
  43. data/lib/gloo/verbs/execute.rb +1 -1
  44. data/lib/gloo.rb +2 -4
  45. data/lib/run.rb +3 -2
  46. metadata +80 -7
@@ -0,0 +1,126 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # An object that can post JSON to a URI.
5
+ #
6
+ require 'net/ssh'
7
+
8
+ module Gloo
9
+ module Objs
10
+ class SshExec < Gloo::Core::Obj
11
+
12
+ KEYWORD = 'ssh_exec'.freeze
13
+ KEYWORD_SHORT = 'ssh'.freeze
14
+ HOST = 'host'.freeze
15
+ DEFAULT_HOST = 'localhost'.freeze
16
+ CMD = 'cmd'.freeze
17
+ RESULT = 'result'.freeze
18
+ HOST_REQUIRED_ERR = 'The host is required!'.freeze
19
+
20
+ #
21
+ # The name of the object type.
22
+ #
23
+ def self.typename
24
+ return KEYWORD
25
+ end
26
+
27
+ #
28
+ # The short name of the object type.
29
+ #
30
+ def self.short_typename
31
+ return KEYWORD_SHORT
32
+ end
33
+
34
+ # ---------------------------------------------------------------------
35
+ # Children
36
+ # ---------------------------------------------------------------------
37
+
38
+ #
39
+ # Does this object have children to add when an object
40
+ # is created in interactive mode?
41
+ # This does not apply during obj load, etc.
42
+ #
43
+ def add_children_on_create?
44
+ return true
45
+ end
46
+
47
+ #
48
+ # Add children to this object.
49
+ # This is used by containers to add children needed
50
+ # for default configurations.
51
+ #
52
+ def add_default_children
53
+ fac = $engine.factory
54
+ fac.create_string HOST, DEFAULT_HOST, self
55
+ fac.create_string CMD, nil, self
56
+ fac.create_string RESULT, nil, self
57
+ end
58
+
59
+ # ---------------------------------------------------------------------
60
+ # Messages
61
+ # ---------------------------------------------------------------------
62
+
63
+ #
64
+ # Get a list of message names that this object receives.
65
+ #
66
+ def self.messages
67
+ return super + [ 'run' ]
68
+ end
69
+
70
+ #
71
+ # SSH to the host and execute the command, then update result.
72
+ #
73
+ def msg_run
74
+ h = host_value
75
+ unless h
76
+ $engine.err HOST_REQUIRED_ERR
77
+ return
78
+ end
79
+
80
+ Net::SSH.start( h ) do |ssh|
81
+ result = ssh.exec!( cmd_value )
82
+ update_result result
83
+ end
84
+ end
85
+
86
+ # ---------------------------------------------------------------------
87
+ # Private functions
88
+ # ---------------------------------------------------------------------
89
+
90
+ private
91
+
92
+ #
93
+ # Get the host from the child object.
94
+ # Returns nil if there is none.
95
+ #
96
+ def host_value
97
+ o = find_child HOST
98
+ return nil unless o
99
+
100
+ return o.value
101
+ end
102
+
103
+ #
104
+ # Get the command from the child object.
105
+ # Returns nil if there is none.
106
+ #
107
+ def cmd_value
108
+ o = find_child CMD
109
+ return nil unless o
110
+
111
+ return o.value
112
+ end
113
+
114
+ #
115
+ # Set the result of the API call.
116
+ #
117
+ def update_result( data )
118
+ r = find_child RESULT
119
+ return nil unless r
120
+
121
+ r.set_value data
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -16,6 +16,7 @@ module Gloo
16
16
  URL = 'uri'.freeze
17
17
  BODY = 'body'.freeze
18
18
  RESULT = 'result'.freeze
19
+ SKIP_SSL_VERIFY = 'skip_ssl_verify'.freeze
19
20
 
20
21
  #
21
22
  # The name of the object type.
@@ -113,8 +114,7 @@ module Gloo
113
114
  $log.debug "posting to: #{uri}"
114
115
  body = self.body_as_json
115
116
  $log.debug "posting body: #{body}"
116
- use_ssl = uri.downcase.start_with?( 'https' )
117
- data = Gloo::Objs::HttpPost.post_json uri, body, use_ssl
117
+ data = Gloo::Objs::HttpPost.post_json( uri, body, skip_ssl_verify? )
118
118
  self.update_result data
119
119
  end
120
120
 
@@ -125,20 +125,57 @@ module Gloo
125
125
  #
126
126
  # Post the content to the endpoint.
127
127
  #
128
- def self.post_json( url, body, use_ssl = true )
129
- # Structure the request
130
- uri = URI.parse( url )
131
- request = Net::HTTP::Post.new( uri.path )
132
- request.content_type = 'application/json'
133
- request.body = body
134
- n = Net::HTTP.new( uri.host, uri.port )
135
- n.use_ssl = use_ssl
136
-
137
- # Send the payload to the endpoint.
138
- result = n.start { |http| http.request( request ) }
139
- $log.debug result.code
140
- $log.debug result.message
141
- return result.body
128
+ def self.post_json( url, body, skip_ssl_verify = false )
129
+ uri = URI( url )
130
+ params = { use_ssl: uri.scheme == 'https' }
131
+ params[ :verify_mode ] = ::OpenSSL::SSL::VERIFY_NONE if skip_ssl_verify
132
+
133
+ Net::HTTP.start( uri.host, uri.port, params ) do |http|
134
+ request = Net::HTTP::Post.new uri
135
+ request.content_type = 'application/json'
136
+ request.body = body
137
+
138
+ result = http.request request # Net::HTTPResponse object
139
+ $log.debug result.code
140
+ $log.debug result.message
141
+ return result.body
142
+ end
143
+ end
144
+
145
+ # #
146
+ # # Post the content to the endpoint.
147
+ # #
148
+ # def self.post_json_1( url, body, use_ssl = true )
149
+ # # Structure the request
150
+ # uri = URI.parse( url )
151
+ #
152
+ # request = Net::HTTP::Post.new( uri.path )
153
+ # request.content_type = 'application/json'
154
+ # request.body = body
155
+ # n = Net::HTTP.new( uri.host, uri.port )
156
+ # n.use_ssl = use_ssl
157
+ #
158
+ # # Send the payload to the endpoint.
159
+ # result = n.start { |http| http.request( request ) }
160
+ # $log.debug result.code
161
+ # $log.debug result.message
162
+ # return result.body
163
+ # end
164
+
165
+ # ---------------------------------------------------------------------
166
+ # Private functions
167
+ # ---------------------------------------------------------------------
168
+
169
+ private
170
+
171
+ #
172
+ # Should we skip SSL verification during the request?
173
+ #
174
+ def skip_ssl_verify?
175
+ skip = find_child SKIP_SSL_VERIFY
176
+ return false unless skip
177
+
178
+ return skip.value
142
179
  end
143
180
 
144
181
  end
@@ -38,7 +38,7 @@ module Gloo
38
38
  # Initially only true for scripts.
39
39
  #
40
40
  def multiline_value?
41
- return true
41
+ return false
42
42
  end
43
43
 
44
44
  #
@@ -122,7 +122,7 @@ module Gloo
122
122
  uri = uri_value
123
123
  return unless uri
124
124
 
125
- Gloo::Objs::HttpPost.post_json uri, body_as_json, true
125
+ Gloo::Objs::HttpPost.post_json uri, body_as_json
126
126
  end
127
127
 
128
128
  end
@@ -109,7 +109,7 @@ module Gloo
109
109
  uri = uri_value
110
110
  return unless uri
111
111
 
112
- Gloo::Objs::HttpPost.post_json uri, body_as_json, true
112
+ Gloo::Objs::HttpPost.post_json uri, body_as_json
113
113
  end
114
114
 
115
115
  end
@@ -4,6 +4,8 @@
4
4
  # A URI (URL).
5
5
  #
6
6
  require 'uri'
7
+ require 'net/http'
8
+ require 'openssl'
7
9
 
8
10
  module Gloo
9
11
  module Objs
@@ -51,10 +53,25 @@ module Gloo
51
53
  def self.messages
52
54
  basic = %w[open]
53
55
  gets = %w[get_scheme get_host get_path]
54
- more = %w[get_query get_fragment]
56
+ more = %w[get_query get_fragment get_cert_expires]
55
57
  return super + basic + gets + more
56
58
  end
57
59
 
60
+ #
61
+ # Get the expiration date for the certificate.
62
+ #
63
+ def msg_get_cert_expires
64
+ return unless value
65
+ o = value
66
+ uri = URI( value )
67
+ response = Net::HTTP.start( uri.host, uri.port, :use_ssl => true )
68
+ cert = response.peer_cert
69
+ o = cert.not_after
70
+
71
+ $engine.heap.it.set_to o
72
+ return o
73
+ end
74
+
58
75
  #
59
76
  # Get the URI fragment that comes after the '#'
60
77
  # in the URL. Might be used to scroll down in the page.
@@ -36,6 +36,8 @@ module Gloo
36
36
  $log.error "File '#{@pn}' does not exist."
37
37
  return
38
38
  end
39
+
40
+ $log.debug "Loading file '#{@pn}'"
39
41
  @tabs = 0
40
42
  @parent_stack = []
41
43
  @parent = $engine.heap.root
@@ -0,0 +1,21 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # Formatting utilities
5
+ #
6
+
7
+ module Gloo
8
+ module Utils
9
+ class Format
10
+
11
+ #
12
+ # Format number, adding comma separators.
13
+ # Ex: 1000 -> 1,000
14
+ #
15
+ def self.number( num )
16
+ return num.to_s.reverse.scan( /.{1,3}/ ).join( ',' ).reverse
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,205 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # Utilities related to words (strings).
5
+ #
6
+
7
+ module Gloo
8
+ module Utils
9
+ class Stats
10
+
11
+ DIR_NOT_FOUND_ERR = 'The folder was not found!'.freeze
12
+
13
+ # ---------------------------------------------------------------------
14
+ # Setup
15
+ # ---------------------------------------------------------------------
16
+
17
+ #
18
+ # Create a stats utility class for the given directory.
19
+ #
20
+ def initialize( dir, types, skip = [] )
21
+ @dir = dir
22
+ setup_loc types
23
+ @skip = skip
24
+ end
25
+
26
+ # ---------------------------------------------------------------------
27
+ # Public Functions
28
+ # ---------------------------------------------------------------------
29
+
30
+ #
31
+ # Is the stats utility valid?
32
+ # Does it have a valid root directory.
33
+ #
34
+ def valid?
35
+ return true if @dir && File.directory?( @dir )
36
+
37
+ $engine.err DIR_NOT_FOUND_ERR
38
+ $engine.heap.it.set_to false
39
+
40
+ return false
41
+ end
42
+
43
+ #
44
+ # Show all stat data for the project.
45
+ #
46
+ def show_all
47
+ return unless valid?
48
+
49
+ generate
50
+ puts "Showing All stats for #{@dir}".white
51
+ puts "\n ** #{@dir_cnt} Total Folders ** "
52
+ puts " ** #{@file_cnt} Total Files ** "
53
+
54
+ busy_folders( 7 )
55
+ file_types
56
+ loc
57
+ end
58
+
59
+ #
60
+ # Get a list of the busiest folders.
61
+ # Count is how many results we want.
62
+ #
63
+ def busy_folders( count = 17 )
64
+ return unless valid?
65
+
66
+ generate
67
+ puts "\nBusy Folders:".yellow
68
+
69
+ @folders.sort! { |a, b| a[ :cnt ] <=> b[ :cnt ] }
70
+ @folders.reverse!
71
+ @folders[ 0..count ].each do |f|
72
+ puts " #{f[ :cnt ]} - #{f[ :name ]}"
73
+ end
74
+ end
75
+
76
+ #
77
+ # Show file types and how many of each there are.
78
+ #
79
+ def file_types
80
+ return unless valid?
81
+
82
+ generate
83
+ puts "\nFiles by Type:".yellow
84
+
85
+ @types = @types.sort_by( &:last )
86
+ @types.reverse!
87
+ @types.each do |o|
88
+ puts " #{o[ 1 ]} - #{o[ 0 ]}" unless o[ 0 ].empty?
89
+ end
90
+ end
91
+
92
+ #
93
+ # Show Lines of Code
94
+ #
95
+ def loc
96
+ return unless valid?
97
+
98
+ generate
99
+ total = 0
100
+
101
+ @loc.each do |k, v|
102
+ puts "\n #{k} Lines of Code".yellow
103
+ total += v[ :lines ]
104
+ formatted = Gloo::Utils::Format.number( v[ :lines ] )
105
+ puts " ** #{formatted} in #{v[ :files ].count} #{k} files ** "
106
+
107
+ puts "\n Busy #{k} files:".yellow
108
+ files = v[ :files ].sort! { |a, b| a[ :lines ] <=> b[ :lines ] }
109
+ files.reverse!
110
+ files[ 0..12 ].each do |f|
111
+ puts " #{f[ :lines ]} - #{f[ :file ]}"
112
+ end
113
+ end
114
+
115
+ formatted = Gloo::Utils::Format.number( total )
116
+ puts "\n #{formatted} Total Lines of Code".white
117
+ end
118
+
119
+ # ---------------------------------------------------------------------
120
+ # Private Functions
121
+ # ---------------------------------------------------------------------
122
+
123
+ #
124
+ # Setup counters for lines of code by file type.
125
+ def setup_loc( types )
126
+ @loc = {}
127
+
128
+ types.split( ' ' ).each do |t|
129
+ @loc[ t ] = { lines: 0, files: [] }
130
+ end
131
+ end
132
+
133
+ #
134
+ # Generate stat data unless we've already done so.
135
+ #
136
+ def generate
137
+ return if @folders
138
+
139
+ $log.debug 'Generating...'
140
+ @folders = []
141
+ @types = {}
142
+ @file_cnt = 0
143
+ @dir_cnt = 0
144
+
145
+ generate_for Pathname.new( @dir )
146
+ end
147
+
148
+ #
149
+ # Generate data for the given path.
150
+ # NOTE: this is a recursive function.
151
+ # It traverses all sub-direcctories.
152
+ #
153
+ def generate_for( path )
154
+ return if @skip.include?( File.basename( path ) )
155
+
156
+ cnt = 0
157
+ path.children.each do |f|
158
+ if f.directory?
159
+ @dir_cnt += 1
160
+ generate_for( f )
161
+ else
162
+ @file_cnt += 1
163
+ cnt += 1
164
+ handle_file( f )
165
+ inc_type( File.extname( f ) )
166
+ end
167
+ end
168
+ @folders << { name: path, cnt: cnt }
169
+ end
170
+
171
+ #
172
+ # Increment the file count.
173
+ #
174
+ def inc_type( type )
175
+ if @types[ type ]
176
+ @types[ type ] += 1
177
+ else
178
+ @types[ type ] = 1
179
+ end
180
+ end
181
+
182
+ #
183
+ # Consider code file types.
184
+ #
185
+ def handle_file( file )
186
+ ext = File.extname( file )
187
+ return unless ext
188
+
189
+ ext = ext[ 1..-1 ]
190
+ return unless @loc.key?( ext )
191
+
192
+ lines = count_lines( file )
193
+ @loc[ ext ][ :lines ] += lines
194
+ @loc[ ext ][ :files ] << { lines: lines, file: file }
195
+ end
196
+
197
+ #
198
+ # Count lines of code in file.
199
+ def count_lines( file )
200
+ return `wc -l #{file}`.split.first.to_i
201
+ end
202
+
203
+ end
204
+ end
205
+ end
@@ -27,7 +27,7 @@ module Gloo
27
27
 
28
28
  pid = fork { exec( cmd ) }
29
29
  Process.wait pid
30
-
30
+
31
31
  # pid = spawn cmd
32
32
  # Process.wait pid
33
33
  $log.debug "done executing cmd: #{cmd}"
data/lib/gloo.rb CHANGED
@@ -4,11 +4,9 @@
4
4
  # Start the Engine.
5
5
  #
6
6
 
7
+ # Look for all required dependencies.
7
8
  path = File.dirname( File.absolute_path( __FILE__ ) )
8
- root = File.join( path, 'gloo', '**/*.rb' )
9
- Dir.glob( root ).each do |ruby_file|
10
- require ruby_file
11
- end
9
+ require File.join( path, 'dependencies.rb' )
12
10
 
13
11
  module Gloo
14
12
  def self.run
data/lib/run.rb CHANGED
@@ -4,9 +4,10 @@
4
4
  #
5
5
  # From the /lib/ directory: ruby run.rb
6
6
  #
7
+
8
+ # Look for all required dependencies.
7
9
  path = File.dirname( File.absolute_path( __FILE__ ) )
8
- root = File.join( path, 'gloo', '**/*.rb' )
9
- Dir.glob( root ) { |ruby_file| require ruby_file }
10
+ require File.join( path, 'dependencies.rb' )
10
11
 
11
12
  params = []
12
13
  ( params << '--cli' ) if ARGV.count.zero?