pult 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c4f5719e4a10fd6f1f1421c62042838d6e2af00bdba247d55960ee837d0c2d89
4
+ data.tar.gz: 44a7c5e29feac0dd68400a6820258a161b0292d335eb0f0a17e59f1ef2214717
5
+ SHA512:
6
+ metadata.gz: 0e4c22b4885c63d09b2bdef97b481d96cd66163377f007099fb029429731740784f6c0b6a3fa4f73f04b455a71535e91d3101f945546cc04a64ffd858a09718b
7
+ data.tar.gz: 3d36c7748749278bedd87f2053fde930700fb78074c2a8540b2f24152a06b0c7bf0d91c77192402b54045f4cdb12330c053d5b7fcc6ffc620bcc0dfb56b3af5a
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ dev.rb
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.3
7
+ before_install: gem install bundler -v 2.0.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pult.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pult (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activejob (5.2.3)
10
+ activesupport (= 5.2.3)
11
+ globalid (>= 0.3.6)
12
+ activesupport (5.2.3)
13
+ concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ i18n (>= 0.7, < 2)
15
+ minitest (~> 5.1)
16
+ tzinfo (~> 1.1)
17
+ axiom-types (0.1.1)
18
+ descendants_tracker (~> 0.0.4)
19
+ ice_nine (~> 0.11.0)
20
+ thread_safe (~> 0.3, >= 0.3.1)
21
+ builder (3.2.3)
22
+ coercible (1.0.0)
23
+ descendants_tracker (~> 0.0.1)
24
+ concurrent-ruby (1.1.5)
25
+ descendants_tracker (0.0.4)
26
+ thread_safe (~> 0.3, >= 0.3.1)
27
+ equalizer (0.0.11)
28
+ globalid (0.4.2)
29
+ activesupport (>= 4.2.0)
30
+ grape (1.2.4)
31
+ activesupport
32
+ builder
33
+ mustermann-grape (~> 1.0.0)
34
+ rack (>= 1.3.0)
35
+ rack-accept
36
+ virtus (>= 1.0.0)
37
+ i18n (1.6.0)
38
+ concurrent-ruby (~> 1.0)
39
+ ice_nine (0.11.2)
40
+ minitest (5.11.3)
41
+ mustermann (1.0.3)
42
+ mustermann-grape (1.0.0)
43
+ mustermann (~> 1.0.0)
44
+ rack (2.0.7)
45
+ rack-accept (0.4.5)
46
+ rack (>= 0.4)
47
+ rake (10.5.0)
48
+ thread_safe (0.3.6)
49
+ tzinfo (1.2.5)
50
+ thread_safe (~> 0.1)
51
+ virtus (1.0.5)
52
+ axiom-types (~> 0.1)
53
+ coercible (~> 1.0)
54
+ descendants_tracker (~> 0.0, >= 0.0.3)
55
+ equalizer (~> 0.0, >= 0.0.9)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ activejob (~> 5.2)
62
+ activesupport (~> 5.2)
63
+ bundler (~> 2.0)
64
+ grape (~> 1.2)
65
+ minitest (~> 5.0)
66
+ pult!
67
+ rake (~> 10.0)
68
+
69
+ BUNDLED WITH
70
+ 2.0.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 dmitryck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Pult
2
+
3
+ Pult is UNDER CONSTRUCTION
4
+
5
+ Comming soon...
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pult"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/init/boot.rb ADDED
@@ -0,0 +1,3 @@
1
+ require_relative 'req-lib'
2
+ require_relative 'struct'
3
+ require_relative 'req-proj'
data/lib/init/const.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Pult
2
+
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'active_job'
2
+ require 'grape'
3
+ require 'open3'
4
+ require 'yaml'
@@ -0,0 +1,11 @@
1
+ require_relative '../pult/version'
2
+ require_relative '../pult/executor'
3
+ require_relative '../pult/executor/enver'
4
+ require_relative '../pult/executor/screener'
5
+ require_relative '../pult/executor/terminator'
6
+ require_relative '../pult/panel'
7
+ require_relative '../pult/panel/executor'
8
+ require_relative '../pult/panel/dot_accessible'
9
+ require_relative '../pult/panel/injector/app'
10
+ require_relative '../pult/panel/injector/panel'
11
+ require_relative '../pult/panel/injector/runner'
@@ -0,0 +1,20 @@
1
+ module Pult
2
+ class Executor
3
+ class Job < ActiveJob::Base; end
4
+ module Enver; end
5
+ class Screener; end
6
+ class Terminator; end
7
+ end
8
+
9
+ class Panel < Hash
10
+ module Executor
11
+ class Job < ActiveJob::Base; end
12
+ end
13
+ module DotAccessible; end
14
+ module Injector
15
+ module App; end
16
+ module Panel; end
17
+ module Runner; end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,6 @@
1
+ class Pult::CliRunner
2
+
3
+ def self.start
4
+
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ module Pult::Executor::Enver
2
+
3
+ # TODO
4
+ DEFENV = ENV.to_h
5
+
6
+ def with_env env=ENV.to_h, env_base=DEFENV
7
+ env_delete_diff! env, env_base
8
+
9
+ yield
10
+
11
+ env_set_diff! env, env_base
12
+ end
13
+
14
+ def env_delete_diff! env, env_base
15
+ env_diff(env, env_base).each do |var|
16
+ ENV.delete(var)
17
+ end
18
+ end
19
+
20
+ def env_set_diff! env, env_base
21
+ env_diff(env, env_base).each do |var|
22
+ ENV[var] = env[var]
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def env_diff env, env_base
29
+ env_base.keys - env.keys
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ require 'open3'
2
+
3
+ class Pult::Executor::Screener
4
+
5
+ attr_reader :runner
6
+
7
+ def self.run! screen:, env:{}, params:{}, command:''
8
+ screener = new(screen, env, params, command)
9
+ screener.run!
10
+ screener.runner
11
+ end
12
+
13
+ def initialize screen, env, params, command
14
+ @screen = screen
15
+ @env = env
16
+ @params = params
17
+ @command = command
18
+ end
19
+
20
+ def run!
21
+ execute!
22
+ end
23
+
24
+ private
25
+
26
+ def execute!
27
+ command = "screen -S #{@screen} -p0 -X stuff \"#{@command}\015\""
28
+
29
+ Open3.popen3( @params, command ) do |stdin, stdout, stderr, thr|
30
+ # TODO for screen
31
+ @runner = {
32
+ stdout: stdout.read,
33
+ stderr: stderr.read,
34
+ info: thr.value
35
+ }
36
+ end
37
+ end
38
+
39
+ def env
40
+ # TODO
41
+ end
42
+
43
+ def params
44
+ to_var @params
45
+ end
46
+
47
+ def to_var hash
48
+ hash.each_with_object([]){|(k, v), o| o<<"#{k}='#{v}'" }.join(' ')
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ class Pult::Executor::Terminator
2
+
3
+ def self.kill! pid
4
+ Process.kill "TERM", pid
5
+ Process.wait pid
6
+ end
7
+ end
@@ -0,0 +1,101 @@
1
+ #!/bin/bash
2
+
3
+ function usage {
4
+ echo "$(basename $0) [[user@]server:[port]] <screen-name> command..." >&2
5
+ exit 1
6
+ }
7
+
8
+ [[ $# -ge 2 ]] || usage
9
+
10
+ SERVER=
11
+ SERVERPORT="-p 22"
12
+ SERVERPAT='^(([a-z]+@)?([A-Za-z0-9.]+)):([0-9]+)?$'
13
+ if [[ "$1" =~ $SERVERPAT ]]; then
14
+ SERVER="${BASH_REMATCH[1]}"
15
+ [[ -n "${BASH_REMATCH[4]}" ]] && SERVERPORT="-p ${BASH_REMATCH[4]}"
16
+ shift
17
+ fi
18
+
19
+ function xscreen {
20
+ # Usage: xscreen <screen-name> command...
21
+ local SCREEN_NAME=$1
22
+ shift
23
+
24
+ if ! screen -list | grep $SCREEN_NAME >/dev/null ; then
25
+ echo "Screen $SCREEN_NAME not found." >&2
26
+ return 124
27
+ # Create screen if it doesn't exist
28
+ #screen -dmS $SCREEN_NAME
29
+ fi
30
+
31
+ # Create I/O pipes
32
+ local DIR=$( mktemp -d )
33
+ mkfifo $DIR/stdin $DIR/stdout $DIR/stderr
34
+ echo 123 > $DIR/status
35
+ trap 'rm -f $DIR/{stdin,stdout,stderr,status}; rmdir $DIR' RETURN
36
+
37
+ # Forward ^C to screen
38
+ trap "screen -S $SCREEN_NAME -p0 -X stuff $'\003'" INT
39
+
40
+ # Print output and kill stdin when both pipes are closed
41
+ {
42
+ cat $DIR/stderr >&2 &
43
+ cat $DIR/stdout &
44
+ wait
45
+ [[ -e $DIR/stdin ]] && fuser -s -PIPE -k -w $DIR/stdin
46
+ } &
47
+ READER_PID=$!
48
+
49
+ # Close all the pipes if the command fails to start (e.g. syntax error)
50
+ {
51
+ # Kill the sleep when this subshell is killed. Ugh.. bash.
52
+ trap 'kill $(jobs -p)' EXIT
53
+
54
+ # Try to write nothing to stdin. This will block until something reads.
55
+ echo -n > $DIR/stdin &
56
+ TEST_PID=$!
57
+ sleep 2.0
58
+
59
+ # If the write failed and we're not killed, it probably didn't start
60
+ if [[ -e $DIR/stdin ]] && kill $TEST_PID 2>/dev/null; then
61
+ echo 'xscreen timeout' >&2
62
+ wait $TEST_PID 2>/dev/null
63
+
64
+ # Send ^C to clear any half-written command (e.g. no closing braces)
65
+ screen -S $SCREEN_NAME -p0 -X stuff $'\003'
66
+
67
+ # Write nothing to output, triggers SIGPIPE
68
+ echo -n 1> $DIR/stdout 2> $DIR/stderr
69
+
70
+ # Stop stdin by creating a fake reader and sending SIGPIPE
71
+ cat $DIR/stdin >/dev/null &
72
+ fuser -s -PIPE -k -w $DIR/stdin
73
+ fi
74
+ } &
75
+ CHECKER_PID=$!
76
+
77
+ # Start the command (Clear line ^A^K, enter command with redirects, run with ^O)
78
+ screen -S $SCREEN_NAME -p0 -X stuff "$(echo -ne '\001\013') { $* ; echo \$? > $DIR/status ; } <$DIR/stdin 1> >(tee $DIR/stdout) 2> >(tee $DIR/stderr >&2)$(echo -ne '\015')"
79
+
80
+ # Forward stdin
81
+ cat > $DIR/stdin
82
+ kill $CHECKER_PID 2>/dev/null && wait $CHECKER_PID 2>/dev/null
83
+
84
+ # Just in case stdin is closed early, wait for output to finish
85
+ wait $READER_PID 2>/dev/null
86
+
87
+ trap - INT
88
+
89
+ return $(cat $DIR/status)
90
+ }
91
+
92
+ if [[ -n $SERVER ]]; then
93
+ ssh $SERVER $SERVERPORT "$(typeset -f xscreen); xscreen $@"
94
+ RET=$?
95
+ if [[ $RET == 124 ]]; then
96
+ echo "To start screen: ssh $SERVER $SERVERPORT \"screen -dmS $1\"" >&2
97
+ fi
98
+ exit $RET
99
+ else
100
+ xscreen "$1" "${@:2}"
101
+ fi
@@ -0,0 +1,74 @@
1
+ class Pult::Executor
2
+
3
+ # ActiveJob::Base
4
+ class Job
5
+ def perform *args
6
+ Pult::Executor.run! *args
7
+ end
8
+ end
9
+
10
+ include Enver
11
+
12
+ attr_reader :runner
13
+
14
+ NOEXEC = 'Нет запуска'
15
+
16
+ def self.run! *args
17
+ runner = Pult::Executor.new(*args)
18
+ runner.run!
19
+ runner.runner
20
+ end
21
+
22
+ def self.run_job! *args
23
+ Job.perform_later(*args)
24
+ end
25
+
26
+ def initialize command, dir, params={}
27
+ @command = command
28
+ @dir = dir
29
+ @params = params.stringify_keys.transform_values {|v| v.to_s }
30
+
31
+ @runner = { info: NOEXEC }
32
+ end
33
+
34
+ def run!
35
+ if @command && @dir && @params
36
+ execute!
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def execute!
43
+ if screen = @params.delete("screen")
44
+ execute_in_screen! screen
45
+ else
46
+ execute_here!
47
+ end
48
+ end
49
+
50
+ def execute_here!
51
+ params = [ @params, @command, chdir: @dir ]
52
+
53
+ with_env do
54
+ Open3.popen3( *params ) do |stdin, stdout, stderr, thr|
55
+ @runner = {
56
+ stdout: stdout.read,
57
+ stderr: stderr.read,
58
+ info: thr.value
59
+ }
60
+ end
61
+ end
62
+ end
63
+
64
+ def execute_in_screen! screen
65
+ args = {
66
+ screen: screen,
67
+ env: ENV_DEFAULT,
68
+ params: @params,
69
+ command: @command
70
+ }
71
+
72
+ @runner = Screener.run! args
73
+ end
74
+ end
@@ -0,0 +1,65 @@
1
+ module Pult::Panel::DotAccessible
2
+
3
+ Runner = Pult::Panel::Injector::Runner
4
+
5
+ JOB_KEY = '_job'
6
+
7
+ module Basic
8
+ def method_missing meth, *args
9
+ self[meth]
10
+ end
11
+ end
12
+
13
+ class Job < ActiveJob::Base
14
+ def perform block_id
15
+ ObjectSpace._id2ref(block_id).call
16
+ end
17
+ end
18
+
19
+ def method_missing meth, *args
20
+ /(?<action>[^\!]+)(?<need_execute>\!?)/ =~ meth.to_s
21
+
22
+ for injection in [JOB_KEY] + Runner.read_injections
23
+ action.gsub! /#{injection}$/, ''
24
+ break if $&
25
+ end
26
+
27
+ value = self[action]
28
+
29
+ if !need_execute.blank?
30
+ if value.respond_to? :app?
31
+ with_job? $& do
32
+ for sub_action in value.keys
33
+ value.send "#{sub_action}!", *args
34
+ end
35
+ end
36
+ else
37
+ return execute!(action, $&, *args)
38
+ end
39
+ end
40
+
41
+ $& ? nil : value
42
+ end
43
+
44
+ private
45
+
46
+ def with_job? injection, &block
47
+ job?(injection) ? Job.perform_later(block.object_id) : block.call
48
+ end
49
+
50
+ def execute! action, injection=nil, *args
51
+ job = job?(injection) ? injection : nil
52
+
53
+ runner = Pult::Panel::Executor.send "run#{job}!", self, action, *args
54
+
55
+ if injection && !job
56
+ return send("#{action}#{injection}")
57
+ else
58
+ return runner
59
+ end
60
+ end
61
+
62
+ def job? str
63
+ str == JOB_KEY
64
+ end
65
+ end
@@ -0,0 +1,26 @@
1
+ module Pult::Panel::Executor
2
+
3
+ # ActiveJob::Base
4
+ class Job
5
+ def perform hash_id, action, *args
6
+ hash = ObjectSpace._id2ref hash_id
7
+ Pult::Panel::Executor.run! hash, action, *args
8
+ end
9
+ end
10
+
11
+ def self.run! hash, action, *args
12
+ command = hash[action]
13
+
14
+ runner = Pult::Executor.run! command, hash._config.dir, *args
15
+
16
+ runner.class_eval { include Pult::Panel::DotAccessible::Basic }
17
+
18
+ Pult::Panel::Injector::Runner.inject! hash, action, runner
19
+
20
+ runner
21
+ end
22
+
23
+ def self.run_job! hash, action, *args
24
+ Job.perform_later hash.object_id, action, *args
25
+ end
26
+ end
@@ -0,0 +1,71 @@
1
+ module Pult::Panel::Injector::App
2
+
3
+ SYS_KEYS = Pult::Panel::SYS_KEYS
4
+
5
+ def self.inject! hash, panel, app
6
+ hash.instance_eval <<-STR
7
+ def _app
8
+ "#{app}"
9
+ end
10
+
11
+ def _panel
12
+ ->{ ObjectSpace._id2ref(#{panel.object_id}) }.call
13
+ end
14
+ STR
15
+
16
+ hash.instance_eval do
17
+ def app?
18
+ true
19
+ end
20
+
21
+ def _to_flat param=self, prefix=nil
22
+ hash = param.each_pair.reduce({}) do |a, (k, v)|
23
+ v.is_a?(Hash) && ! SYS_KEYS.include?(k) ?
24
+ a.merge(_to_flat(v, "#{prefix}#{k}."))
25
+ : a.merge("#{prefix}#{k}" => v)
26
+ end
27
+
28
+ Pult::Panel.app_hash! hash, _panel, _app
29
+ end
30
+
31
+ def _config
32
+ _panel[_app].config
33
+ end
34
+
35
+ def _actions
36
+ keys - SYS_KEYS
37
+ end
38
+
39
+ def _translated_actions
40
+ _actions.map{ |action| _action_title(action) }
41
+ end
42
+
43
+ #
44
+ # TODO order param like :ui => :az, :orig => :config, etc..
45
+ #
46
+ def _ui_actions order: :az_ui
47
+ resproc = proc { |action| [action, _action_title(action)] }
48
+ tacts = _translated_actions
49
+
50
+ case order
51
+ when :config
52
+ _actions.map(&resproc)
53
+ when :config_ui
54
+ _actions.map(&resproc).sort_by{|arr| tacts.index(arr[1]) }
55
+ when :az
56
+ _actions.sort.map(&resproc)
57
+ when :az_ui
58
+ _actions.map(&resproc).sort_by{|arr| arr[1] }
59
+ end
60
+ end
61
+
62
+ def _action_title action
63
+ _action_translate(action) || action
64
+ end
65
+
66
+ def _action_translate action
67
+ self&.config&.ui&.ru&.action&.send(:[], action)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,63 @@
1
+ module Pult::Panel::Injector::Panel
2
+
3
+ Runner = Pult::Panel::Injector::Runner
4
+
5
+ def self.inject! panel
6
+ panel.class_eval do
7
+ attr_reader :_root
8
+ attr_reader :_apps
9
+ end
10
+
11
+ panel.instance_eval do
12
+ def panel?
13
+ true
14
+ end
15
+
16
+ def _ui_apps order: :az
17
+ resproc = proc { |app| [app, _app_title(app)] }
18
+ tapps = _translated_apps
19
+
20
+ case order
21
+ when :az
22
+ _apps.sort.map(&resproc)
23
+ when :az_ui
24
+ _actions.map(&resproc).sort_by{|arr| tapps.index(arr[1]) }
25
+ end
26
+ end
27
+
28
+ def _translated_apps
29
+ _apps.each { |app| _app_title(app) }
30
+ end
31
+
32
+ def _app_title app
33
+ _app_translate(app) || app
34
+ end
35
+
36
+ def _app_translate app
37
+ self[app].config&.ui&.ru&.title
38
+ end
39
+
40
+ def _apply_path path
41
+ path.split('/').reduce(self, :[])
42
+ end
43
+
44
+ def _apply_path! path, params=nil
45
+ params = params&.any? ? params : nil
46
+
47
+ for postfix in _exec_flags + Runner.injections
48
+ regexp = Regexp.new("\/([^\/]+" + Regexp.escape(postfix) + ")$")
49
+
50
+ path.gsub!(regexp, '')
51
+
52
+ return _apply_path(path).send(*[$1, params].compact) if $1
53
+ end
54
+
55
+ _apply_path(path)
56
+ end
57
+
58
+ def _exec_flags
59
+ %w{ ! }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,60 @@
1
+ module Pult::Panel::Injector::Runner
2
+
3
+ def self.injections
4
+ read_injections + run_injections
5
+ end
6
+
7
+ def self.read_injections
8
+ %w{ _out _in _err _success _info _active _pid }
9
+ end
10
+
11
+ def self.run_injections
12
+ %w{ _kill }
13
+ end
14
+
15
+ def self.inject! hash, action, runner
16
+ #
17
+ # TODO runner meths and sys maybe need list
18
+ # for safe using with ! and other
19
+ #
20
+ hash.instance_eval do
21
+ def runner?
22
+ true
23
+ end
24
+ end
25
+
26
+ hash.instance_eval <<-STR
27
+ def #{action}_runner
28
+ ->{ ObjectSpace._id2ref(#{runner.object_id}) }.call
29
+ end
30
+
31
+ def #{action}_out
32
+ #{action}_runner.stdout
33
+ end
34
+
35
+ def #{action}_err
36
+ #{action}_runner.stderr
37
+ end
38
+
39
+ def #{action}_info
40
+ #{action}_runner.info
41
+ end
42
+
43
+ def #{action}_success
44
+ #{action}_info.success?
45
+ end
46
+
47
+ def #{action}_pid
48
+ #{action}_info.pid
49
+ end
50
+
51
+ def #{action}_active
52
+
53
+ end
54
+
55
+ def #{action}_kill
56
+ Pult::Executor::Terminator.kill! #{action}_pid
57
+ end
58
+ STR
59
+ end
60
+ end
data/lib/pult/panel.rb ADDED
@@ -0,0 +1,106 @@
1
+ # Hash
2
+ class Pult::Panel
3
+
4
+ include DotAccessible
5
+
6
+ CONFIG_ROOT = ENV['PULT_CONFIG_ROOT'] || nil
7
+ CONFIG_FILE = ENV['PULT_CONFIG_FILE'] || 'pult.yml'
8
+
9
+ SYS_KEYS = %w{ config }
10
+
11
+ attr_accessor :_config_root
12
+ attr_accessor :_config_file
13
+
14
+ def initialize auto: true
15
+ @_config_root = CONFIG_ROOT
16
+ @_config_file = CONFIG_FILE
17
+
18
+ init! if auto && allow_init?
19
+ end
20
+
21
+ def init!
22
+ if allow_init?
23
+
24
+ panel_hash!
25
+ else
26
+ raise StandardError, 'Init is not allowed!'
27
+ end
28
+ end
29
+
30
+ def self.app_hash! hash, panel, app
31
+ array_node! hash
32
+
33
+ hash.class_eval { include DotAccessible }
34
+
35
+ Injector::App.inject! hash, panel, app
36
+
37
+ hash.values.each do |target|
38
+ app_hash!(target, panel, app) if target.is_a?(Hash)
39
+ end
40
+
41
+ hash
42
+ end
43
+
44
+ def self.array_node! hash
45
+ hash.keys.each do |key|
46
+ value = hash[key]
47
+
48
+ case value.class.name
49
+ when "Hash" then array_node! value
50
+ when "Array"
51
+ # clone hash
52
+ # complex = {}
53
+ # value.each{ |elm| complex[elm] = hash[elm] }
54
+ # hash[key] = complex
55
+
56
+ # combine commands
57
+ hash[key] = '$(' + value.join(') && $(') + ')'
58
+ end
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def allow_init?
65
+ true_abs_path?(@_config_file) || (!!@_config_root && !!@_config_file)
66
+ end
67
+
68
+ def true_abs_path? path
69
+ path[0] == '/' && File.exists(path)
70
+ end
71
+
72
+ def panel_hash!
73
+ compile_hash_from_configs!
74
+
75
+ @_apps = []
76
+
77
+ for app_name in keys
78
+ app = self[app_name]
79
+ @_apps << app_name
80
+
81
+ app_hash! app, self, app_name
82
+ end
83
+
84
+ class_eval { include DotAccessible }
85
+
86
+ Injector::Panel.inject! self
87
+ end
88
+
89
+ def compile_hash_from_configs!
90
+ scan = @_config_root + '/**/' + @_config_file
91
+
92
+ Dir[scan].each do |path|
93
+ config_file = YAML.load_file(path)
94
+
95
+ merge! config_file
96
+ end
97
+ end
98
+
99
+ def app_hash! *args
100
+ self.class.app_hash! *args
101
+ end
102
+
103
+ def array_node! *args
104
+ self.class.array_node *args
105
+ end
106
+ end
@@ -0,0 +1,3 @@
1
+ module Pult
2
+ VERSION = "0.0.1"
3
+ end
data/lib/pult.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative 'init/boot'
2
+
3
+ module Pult
4
+ class Error < StandardError; end
5
+ # Your code goes here...
6
+ end
data/pult.gemspec ADDED
@@ -0,0 +1,43 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "pult/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pult"
8
+ spec.version = Pult::VERSION
9
+ spec.authors = ["dmitryck"]
10
+ spec.email = ["dmitryck@gmail.com"]
11
+
12
+ spec.summary = %q{ Pult for your apps or tasks (UNDER CONSTRUCTION) }
13
+ spec.homepage = "https://github.com/dmitryck/pult"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = spec.homepage
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = "exe"
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ["lib"]
36
+
37
+ spec.add_development_dependency "bundler", "~> 2.0"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "minitest", "~> 5.0"
40
+ spec.add_development_dependency "activesupport", "~> 5.2"
41
+ spec.add_development_dependency "activejob", "~> 5.2"
42
+ spec.add_development_dependency "grape", "~> 1.2"
43
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pult
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - dmitryck
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activejob
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: grape
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.2'
97
+ description:
98
+ email:
99
+ - dmitryck@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/setup
113
+ - lib/init/boot.rb
114
+ - lib/init/const.rb
115
+ - lib/init/req-lib.rb
116
+ - lib/init/req-proj.rb
117
+ - lib/init/struct.rb
118
+ - lib/pult.rb
119
+ - lib/pult/cli_runner.rb
120
+ - lib/pult/executor.rb
121
+ - lib/pult/executor/enver.rb
122
+ - lib/pult/executor/screener.rb
123
+ - lib/pult/executor/terminator.rb
124
+ - lib/pult/executor/xscreen
125
+ - lib/pult/panel.rb
126
+ - lib/pult/panel/dot_accessible.rb
127
+ - lib/pult/panel/executor.rb
128
+ - lib/pult/panel/injector/app.rb
129
+ - lib/pult/panel/injector/panel.rb
130
+ - lib/pult/panel/injector/runner.rb
131
+ - lib/pult/version.rb
132
+ - pult.gemspec
133
+ homepage: https://github.com/dmitryck/pult
134
+ licenses:
135
+ - MIT
136
+ metadata:
137
+ allowed_push_host: https://rubygems.org
138
+ homepage_uri: https://github.com/dmitryck/pult
139
+ source_code_uri: https://github.com/dmitryck/pult
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.7.6
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: Pult for your apps or tasks (UNDER CONSTRUCTION)
160
+ test_files: []