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,192 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # A MySQL database connection.
5
+ #
6
+ #
7
+ # https://github.com/brianmario/mysql2
8
+ # https://www.rubydoc.info/gems/mysql2/0.2.3/Mysql2/Client
9
+ #
10
+ # Connection Parameters
11
+ # user = opts[:username]
12
+ # pass = opts[:password]
13
+ # host = opts[:host] || 'localhost'
14
+ # port = opts[:port] || 3306
15
+ # database = opts[:database]
16
+ # socket = opts[:socket]
17
+ # flags = opts[:flags] || 0
18
+ #
19
+ require 'mysql2'
20
+
21
+ module Gloo
22
+ module Objs
23
+ class Mysql < Gloo::Core::Obj
24
+
25
+ KEYWORD = 'mysql'.freeze
26
+ KEYWORD_SHORT = 'mysql'.freeze
27
+
28
+ HOST = 'host'.freeze
29
+ DB = 'database'.freeze
30
+ USER = 'username'.freeze
31
+ PASSWD = 'password'.freeze
32
+
33
+ #
34
+ # The name of the object type.
35
+ #
36
+ def self.typename
37
+ return KEYWORD
38
+ end
39
+
40
+ #
41
+ # The short name of the object type.
42
+ #
43
+ def self.short_typename
44
+ return KEYWORD_SHORT
45
+ end
46
+
47
+ # ---------------------------------------------------------------------
48
+ # Children
49
+ # ---------------------------------------------------------------------
50
+
51
+ #
52
+ # Does this object have children to add when an object
53
+ # is created in interactive mode?
54
+ # This does not apply during obj load, etc.
55
+ #
56
+ def add_children_on_create?
57
+ return true
58
+ end
59
+
60
+ #
61
+ # Add children to this object.
62
+ # This is used by containers to add children needed
63
+ # for default configurations.
64
+ #
65
+ def add_default_children
66
+ fac = $engine.factory
67
+ fac.create_string HOST, nil, self
68
+ fac.create_string DB, nil, self
69
+ fac.create_string USER, nil, self
70
+ fac.create_string PASSWD, nil, self
71
+ end
72
+
73
+ # ---------------------------------------------------------------------
74
+ # Messages
75
+ # ---------------------------------------------------------------------
76
+
77
+ #
78
+ # Get a list of message names that this object receives.
79
+ #
80
+ def self.messages
81
+ return super + [ 'verify' ]
82
+ end
83
+
84
+ #
85
+ # SSH to the host and execute the command, then update result.
86
+ #
87
+ def msg_verify
88
+ return unless connects?
89
+
90
+ $engine.heap.it.set_to true
91
+ end
92
+
93
+ # ---------------------------------------------------------------------
94
+ # DB functions (all database connections)
95
+ # ---------------------------------------------------------------------
96
+
97
+ #
98
+ # Open a connection and execute the SQL statement.
99
+ # Return the resulting data.
100
+ #
101
+ def query( sql, params = nil )
102
+ h = {
103
+ host: host_value,
104
+ database: db_value,
105
+ username: user_value,
106
+ password: passwd_value
107
+ }
108
+ client = Mysql2::Client.new( h )
109
+ return client.query( sql ) unless params
110
+
111
+ pst = client.prepare( sql )
112
+ return pst.execute( *params )
113
+ end
114
+
115
+ # ---------------------------------------------------------------------
116
+ # Private functions
117
+ # ---------------------------------------------------------------------
118
+
119
+ private
120
+
121
+ #
122
+ # Get the host from the child object.
123
+ # Returns nil if there is none.
124
+ #
125
+ def host_value
126
+ o = find_child HOST
127
+ return nil unless o
128
+
129
+ o = Gloo::Objs::Alias.resolve_alias( o )
130
+ return o.value
131
+ end
132
+
133
+ #
134
+ # Get the Database name from the child object.
135
+ # Returns nil if there is none.
136
+ #
137
+ def db_value
138
+ o = find_child DB
139
+ return nil unless o
140
+
141
+ o = Gloo::Objs::Alias.resolve_alias( o )
142
+ return o.value
143
+ end
144
+
145
+ #
146
+ # Get the Username from the child object.
147
+ # Returns nil if there is none.
148
+ #
149
+ def user_value
150
+ o = find_child USER
151
+ return nil unless o
152
+
153
+ o = Gloo::Objs::Alias.resolve_alias( o )
154
+ return o.value
155
+ end
156
+
157
+ #
158
+ # Get the Password name from the child object.
159
+ # Returns nil if there is none.
160
+ #
161
+ def passwd_value
162
+ o = find_child PASSWD
163
+ return nil unless o
164
+
165
+ o = Gloo::Objs::Alias.resolve_alias( o )
166
+ return o.value
167
+ end
168
+
169
+ #
170
+ # Try the connection and make sure it works.
171
+ # Returns true if we can establish a connection.
172
+ #
173
+ def connects?
174
+ begin
175
+ h = {
176
+ host: host_value,
177
+ database: db_value,
178
+ username: user_value,
179
+ password: passwd_value
180
+ }
181
+ Mysql2::Client.new( h )
182
+ rescue => e
183
+ $engine.err e.message
184
+ $engine.heap.it.set_to false
185
+ return false
186
+ end
187
+ return true
188
+ end
189
+
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,176 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # A SQL database query.
5
+ # Relies on a database connection object.
6
+ #
7
+
8
+ module Gloo
9
+ module Objs
10
+ class Query < Gloo::Core::Obj
11
+
12
+ KEYWORD = 'query'.freeze
13
+ KEYWORD_SHORT = 'sql'.freeze
14
+
15
+ DB = 'database'.freeze
16
+ SQL = 'sql'.freeze
17
+ RESULT = 'result'.freeze
18
+ PARAMS = 'params'.freeze
19
+
20
+ DB_MISSING_ERR = 'The database connection is missing!'.freeze
21
+
22
+ #
23
+ # The name of the object type.
24
+ #
25
+ def self.typename
26
+ return KEYWORD
27
+ end
28
+
29
+ #
30
+ # The short name of the object type.
31
+ #
32
+ def self.short_typename
33
+ return KEYWORD_SHORT
34
+ end
35
+
36
+ # ---------------------------------------------------------------------
37
+ # Children
38
+ # ---------------------------------------------------------------------
39
+
40
+ #
41
+ # Does this object have children to add when an object
42
+ # is created in interactive mode?
43
+ # This does not apply during obj load, etc.
44
+ #
45
+ def add_children_on_create?
46
+ return true
47
+ end
48
+
49
+ #
50
+ # Add children to this object.
51
+ # This is used by containers to add children needed
52
+ # for default configurations.
53
+ #
54
+ def add_default_children
55
+ fac = $engine.factory
56
+ fac.create_alias DB, nil, self
57
+ fac.create_string SQL, nil, self
58
+ fac.create_can RESULT, self
59
+ end
60
+
61
+ # ---------------------------------------------------------------------
62
+ # Messages
63
+ # ---------------------------------------------------------------------
64
+
65
+ #
66
+ # Get a list of message names that this object receives.
67
+ #
68
+ def self.messages
69
+ return super + [ 'run' ]
70
+ end
71
+
72
+ #
73
+ # SSH to the host and execute the command, then update result.
74
+ #
75
+ def msg_run
76
+ db = db_obj
77
+ unless db
78
+ $engine.err DB_MISSING_ERR
79
+ return
80
+ end
81
+
82
+ result = db.query( sql_value, param_array )
83
+ process_result result
84
+ end
85
+
86
+ # ---------------------------------------------------------------------
87
+ # Private functions
88
+ # ---------------------------------------------------------------------
89
+
90
+ private
91
+
92
+ #
93
+ # Get the database connection.
94
+ #
95
+ def db_obj
96
+ o = find_child DB
97
+ return Gloo::Objs::Alias.resolve_alias( o )
98
+ end
99
+
100
+ #
101
+ # Get the SQL from the child object.
102
+ # Returns nil if there is none.
103
+ #
104
+ def sql_value
105
+ o = find_child SQL
106
+ return nil unless o
107
+
108
+ return o.value
109
+ end
110
+
111
+ #
112
+ # Do something with the result of the SQL Query call.
113
+ # If there's a result container, we'll create objects in it.
114
+ # If not, we'll just show the output in the console.
115
+ #
116
+ def process_result( data )
117
+ r = find_child RESULT
118
+ if r
119
+ update_result_contaier data
120
+ else
121
+ show_result data
122
+ end
123
+ end
124
+
125
+ #
126
+ # Get the arrya of parameters.
127
+ # If there is no PARAM container of if it is empty,
128
+ # we'll return a nil value.
129
+ #
130
+ def param_array
131
+ o = find_child PARAMS
132
+ return nil unless o
133
+
134
+ return nil if o.child_count.zero?
135
+
136
+ params = []
137
+ o.children.each do |p|
138
+ params << p.value
139
+ end
140
+
141
+ return params
142
+ end
143
+
144
+ #
145
+ # Show the result of the query in the console.
146
+ #
147
+ def show_result( data )
148
+ return if data.nil?
149
+
150
+ data.each_with_index do |row, i|
151
+ # Show header for the first row
152
+ puts row.map { |k, _| k }.join( " \t " ).white if i.zero?
153
+
154
+ # Show the row data
155
+ puts row.map { |_, v| v }.join( " \t " )
156
+ end
157
+ end
158
+
159
+ #
160
+ # Update the result container with the data from the query.
161
+ #
162
+ def update_result_contaier( data )
163
+ r = find_child RESULT
164
+ r = Gloo::Objs::Alias.resolve_alias( r )
165
+ data.each_with_index do |row, i|
166
+ can = r.find_add_child( i.to_s, 'can' )
167
+ row.each do |k, v|
168
+ o = can.find_add_child( k, 'untyped' )
169
+ o.set_value v
170
+ end
171
+ end
172
+ end
173
+
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,159 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # A Sqlite3 database connection.
5
+ #
6
+ # https://www.rubydoc.info/gems/sqlite3/1.3.11
7
+ # https://www.devdungeon.com/content/ruby-sqlite-tutorial
8
+ #
9
+ # db.results_as_hash = true
10
+ # Set results to return as Hash object.
11
+ # This is slower but offers a huge convenience.
12
+ # Consider turning it off for high performance situations.
13
+ # Each row will have the column name as the hash key.
14
+ #
15
+ # # Alternatively, to only get one row and discard the rest,
16
+ # replace `db.query()` with `db.get_first_value()`.
17
+ #
18
+ require 'sqlite3'
19
+
20
+ module Gloo
21
+ module Objs
22
+ class Sqlite < Gloo::Core::Obj
23
+
24
+ KEYWORD = 'sqlite'.freeze
25
+ KEYWORD_SHORT = 'sqlite'.freeze
26
+
27
+ DB = 'database'.freeze
28
+ DEFAULT_DB = 'test.db'.freeze
29
+
30
+ DB_REQUIRED_ERR = 'The database name is required!'.freeze
31
+ DB_NOT_FOUND_ERR = 'The database file was not found!'.freeze
32
+
33
+ #
34
+ # The name of the object type.
35
+ #
36
+ def self.typename
37
+ return KEYWORD
38
+ end
39
+
40
+ #
41
+ # The short name of the object type.
42
+ #
43
+ def self.short_typename
44
+ return KEYWORD_SHORT
45
+ end
46
+
47
+ # ---------------------------------------------------------------------
48
+ # Children
49
+ # ---------------------------------------------------------------------
50
+
51
+ #
52
+ # Does this object have children to add when an object
53
+ # is created in interactive mode?
54
+ # This does not apply during obj load, etc.
55
+ #
56
+ def add_children_on_create?
57
+ return true
58
+ end
59
+
60
+ #
61
+ # Add children to this object.
62
+ # This is used by containers to add children needed
63
+ # for default configurations.
64
+ #
65
+ def add_default_children
66
+ fac = $engine.factory
67
+ fac.create_string DB, DEFAULT_DB, self
68
+ end
69
+
70
+ # ---------------------------------------------------------------------
71
+ # Messages
72
+ # ---------------------------------------------------------------------
73
+
74
+ #
75
+ # Get a list of message names that this object receives.
76
+ #
77
+ def self.messages
78
+ return super + [ 'verify' ]
79
+ end
80
+
81
+ #
82
+ # Verify access to the Sqlite database specified.
83
+ #
84
+ def msg_verify
85
+ name = db_value
86
+ if name.empty?
87
+ $engine.err DB_REQUIRED_ERR
88
+ $engine.heap.it.set_to false
89
+ return
90
+ end
91
+
92
+ unless File.exist? name
93
+ $engine.err DB_NOT_FOUND_ERR
94
+ $engine.heap.it.set_to false
95
+ return
96
+ end
97
+
98
+ return unless connects?
99
+
100
+ $engine.heap.it.set_to true
101
+ end
102
+
103
+ # ---------------------------------------------------------------------
104
+ # DB functions (all database connections)
105
+ # ---------------------------------------------------------------------
106
+
107
+ #
108
+ # Open a connection and execute the SQL statement.
109
+ # Return the resulting data.
110
+ #
111
+ def query( sql, params = nil )
112
+ name = db_value
113
+ unless name
114
+ $engine.err DB_REQUIRED_ERR
115
+ return
116
+ end
117
+
118
+ db = SQLite3::Database.open name
119
+ db.results_as_hash = true
120
+ return db.query( sql, params )
121
+ end
122
+
123
+ # ---------------------------------------------------------------------
124
+ # Private functions
125
+ # ---------------------------------------------------------------------
126
+
127
+ private
128
+
129
+ #
130
+ # Get the Database file from the child object.
131
+ # Returns nil if there is none.
132
+ #
133
+ def db_value
134
+ o = find_child DB
135
+ return nil unless o
136
+
137
+ return o.value
138
+ end
139
+
140
+ #
141
+ # Try the connection and make sure it works.
142
+ # Returns true if we can connect and do a query.
143
+ #
144
+ def connects?
145
+ begin
146
+ db = SQLite3::Database.open db_value
147
+ sql = "SELECT COUNT(name) FROM sqlite_master WHERE type='table'"
148
+ db.get_first_value sql
149
+ rescue => e
150
+ $engine.err e.message
151
+ $engine.heap.it.set_to false
152
+ return false
153
+ end
154
+ return true
155
+ end
156
+
157
+ end
158
+ end
159
+ end
@@ -40,7 +40,9 @@ module Gloo
40
40
  # Get a list of message names that this object receives.
41
41
  #
42
42
  def self.messages
43
- return super + %w[validate check_changes get_changes commit get_branch]
43
+ actions = %w[validate commit get_branch review]
44
+ changes = %w[check_changes get_changes]
45
+ return super + changes + actions
44
46
  end
45
47
 
46
48
  #
@@ -57,6 +59,16 @@ module Gloo
57
59
  $engine.heap.it.set_to branch
58
60
  end
59
61
 
62
+ #
63
+ # Review pending changes.
64
+ #
65
+ def msg_review
66
+ $log.debug 'Reviewing pending changes'
67
+ cmd = "cd #{path_value}; git diff"
68
+ $log.debug cmd
69
+ system cmd
70
+ end
71
+
60
72
  #
61
73
  # Commit pending changes.
62
74
  #
@@ -0,0 +1,120 @@
1
+ # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
+ # Copyright:: Copyright (c) 2020 Eric Crane. All rights reserved.
3
+ #
4
+ # Get statistics about a development project.
5
+ #
6
+
7
+ module Gloo
8
+ module Objs
9
+ class Stats < Gloo::Core::Obj
10
+
11
+ KEYWORD = 'stats'.freeze
12
+ KEYWORD_SHORT = 'stat'.freeze
13
+ FOLDER = 'folder'.freeze
14
+ TYPES = 'types'.freeze
15
+ SKIP = 'skip'.freeze
16
+
17
+ #
18
+ # The name of the object type.
19
+ #
20
+ def self.typename
21
+ return KEYWORD
22
+ end
23
+
24
+ #
25
+ # The short name of the object type.
26
+ #
27
+ def self.short_typename
28
+ return KEYWORD_SHORT
29
+ end
30
+
31
+ #
32
+ # Get the path to the git repo (locally).
33
+ #
34
+ def path_value
35
+ o = find_child FOLDER
36
+ return o ? o.value : nil
37
+ end
38
+
39
+ #
40
+ # The code file types to count.
41
+ #
42
+ def types_value
43
+ o = find_child TYPES
44
+ return o ? o.value : ''
45
+ end
46
+
47
+ #
48
+ # Get the list of files and folders to skip.
49
+ #
50
+ def skip_list
51
+ o = find_child SKIP
52
+ val = o ? o.value : ''
53
+ return val.split ' '
54
+ end
55
+
56
+ # ---------------------------------------------------------------------
57
+ # Children
58
+ # ---------------------------------------------------------------------
59
+
60
+ #
61
+ # Does this object have children to add when an object
62
+ # is created in interactive mode?
63
+ # This does not apply during obj load, etc.
64
+ #
65
+ def add_children_on_create?
66
+ return true
67
+ end
68
+
69
+ #
70
+ # Add children to this object.
71
+ # This is used by containers to add children needed
72
+ # for default configurations.
73
+ #
74
+ def add_default_children
75
+ fac = $engine.factory
76
+ fac.create_file FOLDER, '', self
77
+ fac.create_string TYPES, '', self
78
+ fac.create_can SKIP, self
79
+ end
80
+
81
+ # ---------------------------------------------------------------------
82
+ # Messages
83
+ # ---------------------------------------------------------------------
84
+
85
+ #
86
+ # Get a list of message names that this object receives.
87
+ #
88
+ def self.messages
89
+ all = %w[show_all]
90
+ more = %w[show_busy_folders show_types]
91
+ return super + all + more
92
+ end
93
+
94
+ #
95
+ # Show all project stats.
96
+ #
97
+ def msg_show_all
98
+ o = Gloo::Utils::Stats.new( path_value, types_value, skip_list )
99
+ o.show_all
100
+ end
101
+
102
+ #
103
+ # Show file types.
104
+ #
105
+ def msg_show_types
106
+ o = Gloo::Utils::Stats.new( path_value, types_value, skip_list )
107
+ o.file_types
108
+ end
109
+
110
+ #
111
+ # Show busy folders: those with the most files.
112
+ #
113
+ def msg_show_busy_folders
114
+ o = Gloo::Utils::Stats.new( path_value, types_value, skip_list )
115
+ o.busy_folders
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -36,8 +36,9 @@ module Gloo
36
36
  def self.messages
37
37
  basic = %w[read write]
38
38
  checks = %w[check_exists check_is_file check_is_dir]
39
+ search = %w[find_match]
39
40
  show = %w[show page open]
40
- return super + basic + show + checks
41
+ return super + basic + show + checks + search
41
42
  end
42
43
 
43
44
  #
@@ -124,6 +125,14 @@ module Gloo
124
125
  $engine.heap.it.set_to result
125
126
  end
126
127
 
128
+ #
129
+ # Look for any file matching pattern.
130
+ #
131
+ def msg_find_match
132
+ result = !Dir.glob( value ).empty?
133
+ $engine.heap.it.set_to result
134
+ end
135
+
127
136
  end
128
137
  end
129
138
  end