gloo 0.7.3 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
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?