appril-cli 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Rakefile +1 -0
- data/appril-cli.gemspec +19 -0
- data/bin/appril +4 -0
- data/boilerplate/app/.gitignore +6 -0
- data/boilerplate/app/.pryrc +1 -0
- data/boilerplate/app/Gemfile +6 -0
- data/boilerplate/app/Rakefile +1 -0
- data/boilerplate/app/base/api/base_controller.rb +21 -0
- data/boilerplate/app/base/api/index/client.coffee +4 -0
- data/boilerplate/app/base/api/index/layout.html +3 -0
- data/boilerplate/app/base/api/index/server.rb +3 -0
- data/boilerplate/app/base/api/rtcp_controller.rb +22 -0
- data/boilerplate/app/base/assets/styles.css +0 -0
- data/boilerplate/app/base/boot.rb +2 -0
- data/boilerplate/app/base/core.coffee +143 -0
- data/boilerplate/app/base/helpers/application_helpers.coffee +1 -0
- data/boilerplate/app/base/helpers/application_helpers.rb +4 -0
- data/boilerplate/app/base/load.rb +0 -0
- data/boilerplate/app/base/models/base_model.rb +0 -0
- data/boilerplate/app/base/templates/access_denied.html +3 -0
- data/boilerplate/app/base/templates/layout.liquid +11 -0
- data/boilerplate/app/base/templates/layouts/main.html +1 -0
- data/boilerplate/app/base/templates/layouts/none.html +1 -0
- data/boilerplate/app/config/config.rb +9 -0
- data/boilerplate/app/config/config.yml +18 -0
- data/boilerplate/app/config/env/development.yml +0 -0
- data/boilerplate/app/config/env/production.yml +0 -0
- data/boilerplate/app/config/env/stage.yml +0 -0
- data/boilerplate/app/config/env/test.yml +0 -0
- data/boilerplate/app/config.ru +3 -0
- data/boilerplate/app/core/Gemfile +4 -0
- data/boilerplate/app/core/boot.rb +16 -0
- data/boilerplate/app/core/generate_configs.rb +125 -0
- data/boilerplate/app/core/load.rb +14 -0
- data/boilerplate/app/core/load_controllers.rb +14 -0
- data/boilerplate/app/generators/api/client.coffee +4 -0
- data/boilerplate/app/generators/api/layout.html +0 -0
- data/boilerplate/app/generators/api/server.rb +3 -0
- data/boilerplate/app/package.json +10 -0
- data/boilerplate/app/public/.ignore +0 -0
- data/boilerplate/app/tmp/.ignore +0 -0
- data/boilerplate/app/var/.ignore +0 -0
- data/boilerplate/app/webpack.config.js +53 -0
- data/boilerplate/crudle/Gemfile +7 -0
- data/boilerplate/crudle/base/core.coffee +128 -0
- data/boilerplate/crudle/base/templates/menu.html +3 -0
- data/boilerplate/crudle/generators/api/client.coffee +11 -0
- data/boilerplate/crudle/generators/api/editor.html +0 -0
- data/boilerplate/crudle/generators/api/server.rb +26 -0
- data/boilerplate/crudle/package.json +15 -0
- data/boilerplate/crudle/webpack.config.js +54 -0
- data/docker/Dockerfile +5 -0
- data/docker/run +66 -0
- data/docker/skel/build.sh +1 -0
- data/docker/skel/cleanup.sh +7 -0
- data/docker/skel/config.yml +24 -0
- data/docker/skel/prepare_build.sh +5 -0
- data/docker/skel/start.sh +1 -0
- data/docker/start +7 -0
- data/lib/appril-cli/app/install.rb +46 -0
- data/lib/appril-cli/app/update.rb +27 -0
- data/lib/appril-cli/app.rb +46 -0
- data/lib/appril-cli/assertions.rb +60 -0
- data/lib/appril-cli/docker/build.rb +152 -0
- data/lib/appril-cli/docker/install.rb +23 -0
- data/lib/appril-cli/docker/update.rb +26 -0
- data/lib/appril-cli/docker.rb +61 -0
- data/lib/appril-cli/generator/api.rb +16 -0
- data/lib/appril-cli/generator.rb +32 -0
- data/lib/appril-cli/helpers.rb +47 -0
- data/lib/appril-cli/version.rb +5 -0
- data/lib/appril-cli.rb +102 -0
- data/sandbox/.gitignore +6 -0
- data/sandbox/.pryrc +1 -0
- data/sandbox/Gemfile +7 -0
- data/sandbox/Rakefile +1 -0
- data/sandbox/base/api/base_controller.rb +21 -0
- data/sandbox/base/api/index/client.coffee +4 -0
- data/sandbox/base/api/index/layout.html +3 -0
- data/sandbox/base/api/index/server.rb +3 -0
- data/sandbox/base/api/rtcp_controller.rb +22 -0
- data/sandbox/base/assets/styles.css +0 -0
- data/sandbox/base/boot.rb +2 -0
- data/sandbox/base/core.coffee +128 -0
- data/sandbox/base/helpers/application_helpers.coffee +1 -0
- data/sandbox/base/helpers/application_helpers.rb +4 -0
- data/sandbox/base/load.rb +0 -0
- data/sandbox/base/models/base_model.rb +0 -0
- data/sandbox/base/templates/access_denied.html +3 -0
- data/sandbox/base/templates/layout.liquid +11 -0
- data/sandbox/base/templates/layouts/main.html +1 -0
- data/sandbox/base/templates/layouts/none.html +1 -0
- data/sandbox/base/templates/menu.html +3 -0
- data/sandbox/config/config.rb +9 -0
- data/sandbox/config/config.yml +18 -0
- data/sandbox/config/env/development.yml +0 -0
- data/sandbox/config/env/production.yml +0 -0
- data/sandbox/config/env/stage.yml +0 -0
- data/sandbox/config/env/test.yml +0 -0
- data/sandbox/config.ru +3 -0
- data/sandbox/core/Gemfile +4 -0
- data/sandbox/core/boot.rb +16 -0
- data/sandbox/core/generate_configs.rb +125 -0
- data/sandbox/core/load.rb +14 -0
- data/sandbox/core/load_controllers.rb +14 -0
- data/sandbox/generators/api/client.coffee +11 -0
- data/sandbox/generators/api/editor.html +0 -0
- data/sandbox/generators/api/layout.html +0 -0
- data/sandbox/generators/api/server.rb +26 -0
- data/sandbox/package.json +15 -0
- data/sandbox/webpack.config.js +54 -0
- metadata +157 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Docker
|
4
|
+
|
5
|
+
class Build
|
6
|
+
|
7
|
+
def initialize dir, update_runner_only: false, push_opted: false
|
8
|
+
Dir.chdir dir do
|
9
|
+
|
10
|
+
config = load_config
|
11
|
+
validate_config(config)
|
12
|
+
|
13
|
+
build_dir = Pathname.new(File.expand_path('__tmpbuildir__'))
|
14
|
+
|
15
|
+
prepare_build_dir(build_dir)
|
16
|
+
|
17
|
+
install_files(build_dir)
|
18
|
+
|
19
|
+
app_dir = Pathname.new(File.expand_path(config['APP_DIR']))
|
20
|
+
|
21
|
+
if update_runner_only
|
22
|
+
puts "Skipping image building"
|
23
|
+
else
|
24
|
+
prepare_build(build_dir, app_dir)
|
25
|
+
|
26
|
+
image_built = build_image(build_dir, config['IMAGE_NAME'], config['BUILD_OPTS'])
|
27
|
+
|
28
|
+
if image_built && push_opted
|
29
|
+
push_image(config['IMAGE_NAME'])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Installing run script"
|
34
|
+
install_run_script(app_dir, *config.values_at('IMAGE_NAME', 'CONTAINER_NAME', 'RUN_SCRIPT', 'RUN_OPTS'))
|
35
|
+
|
36
|
+
FileUtils.rm_rf(build_dir)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_config
|
41
|
+
YAML.load(File.read(CONFIG_FILE))
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_config config
|
45
|
+
{
|
46
|
+
'IMAGE_NAME' => :validate_config__image_name,
|
47
|
+
'CONTAINER_NAME' => :validate_config__container_name,
|
48
|
+
'APP_DIR' => :validate_config__app_dir,
|
49
|
+
'RUN_SCRIPT' => :validate_config__run_script,
|
50
|
+
}.each_pair do |key,validator|
|
51
|
+
next if send(validator, config[key])
|
52
|
+
puts "", "\t::: Please set #{key} in config.yml :::", ""
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_config__image_name value
|
58
|
+
!value.nil? && !value.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_config__container_name value
|
62
|
+
!value.nil? && !value.empty? && value.values.any?
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_config__app_dir value
|
66
|
+
!value.nil? && !value.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_config__run_script value
|
70
|
+
!value.nil? && !value.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
def prepare_build_dir dir
|
74
|
+
FileUtils.rm_rf(dir)
|
75
|
+
FileUtils.mkdir_p(dir / 'build')
|
76
|
+
end
|
77
|
+
|
78
|
+
def install_files dir
|
79
|
+
install_dockerfile(dir)
|
80
|
+
install_start_file(dir)
|
81
|
+
install_build_files(dir)
|
82
|
+
install_cleanup_file(dir)
|
83
|
+
end
|
84
|
+
|
85
|
+
def install_dockerfile dir
|
86
|
+
FileUtils.cp(DOCKER_DIR / 'Dockerfile', dir)
|
87
|
+
end
|
88
|
+
|
89
|
+
def install_start_file dir
|
90
|
+
File.open dir / 'start', 'w' do |f|
|
91
|
+
f << File.read(DOCKER_DIR / 'start').sub('{start}', File.read(START_FILE))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def install_build_files dir
|
96
|
+
FileUtils.cp(PREPARE_BUILD_FILE, dir / 'build')
|
97
|
+
FileUtils.cp(BUILD_FILE, dir / 'build/build')
|
98
|
+
end
|
99
|
+
|
100
|
+
def install_cleanup_file dir
|
101
|
+
FileUtils.cp(CLEANUP_FILE, dir / 'build/cleanup')
|
102
|
+
end
|
103
|
+
|
104
|
+
def prepare_build dir, app_dir
|
105
|
+
Dir.chdir dir / 'build' do
|
106
|
+
CLI.run "APP_DIR=#{app_dir} #{PREPARE_BUILD_FILE}"
|
107
|
+
exit 1 unless $? && $?.success?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def build_image dir, image_name, build_opts
|
112
|
+
CLI.run "docker build -t #{image_name} #{build_opts} '#{dir}'"
|
113
|
+
$? && $?.success?
|
114
|
+
end
|
115
|
+
|
116
|
+
def push_image image_name
|
117
|
+
CLI.run "docker push #{image_name}"
|
118
|
+
$? && $?.success?
|
119
|
+
end
|
120
|
+
|
121
|
+
def install_run_script app_dir, image_name, container_name, run_script, run_opts
|
122
|
+
FileUtils.mkdir_p(app_dir / File.dirname(run_script))
|
123
|
+
|
124
|
+
script_path = app_dir / run_script
|
125
|
+
|
126
|
+
File.open script_path, 'w' do |f|
|
127
|
+
f << File.read(DOCKER_DIR / 'run').
|
128
|
+
gsub('{image}', image_name).
|
129
|
+
gsub('{script_path_traversal}', script_path_traversal(run_script)).
|
130
|
+
gsub('{run_opts}', run_opts).
|
131
|
+
gsub('{environments}', container_name.keys.join(' ')).
|
132
|
+
gsub('{container_definitions}', container_definitions(container_name))
|
133
|
+
end
|
134
|
+
|
135
|
+
FileUtils.chmod('+x', script_path)
|
136
|
+
end
|
137
|
+
|
138
|
+
def container_definitions container_name
|
139
|
+
container_name.map do |kv|
|
140
|
+
'[ "$APP_ENV" = "%s" ] && CONTAINER_NAME="%s"' % kv
|
141
|
+
end.join("\n")
|
142
|
+
end
|
143
|
+
|
144
|
+
def script_path_traversal run_script
|
145
|
+
run_script.gsub(/\A\/+|\/+\Z/, '').scan(/\/+/).map {'..'}*'/'
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Docker
|
4
|
+
|
5
|
+
class Install
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
def initialize dir, working_dir_opted: false
|
9
|
+
install(dir, working_dir_opted)
|
10
|
+
make_executable(dir / PREPARE_BUILD_FILE)
|
11
|
+
puts "Done. All files installed into #{dir}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def install dir, working_dir_opted
|
15
|
+
src = working_dir_opted ? DOCKER_DIR.to_path + '/skel/.' : DOCKER_DIR / 'skel'
|
16
|
+
FileUtils.cp_r(src, dir)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Docker
|
4
|
+
|
5
|
+
class Update
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
def initialize dir
|
9
|
+
Dir.chdir DOCKER_DIR / 'skel' do
|
10
|
+
|
11
|
+
Dir['**/*'].select {|e| File.file?(e)}.each do |file|
|
12
|
+
next if File.file?(dir / file)
|
13
|
+
create_dirname_for(dir / file)
|
14
|
+
puts "Installing #{File.basename(dir)}/#{file}"
|
15
|
+
FileUtils.cp(file, dir / file)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
puts "Done"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Docker
|
4
|
+
|
5
|
+
DOCKER_DIR = BASE_DIR / 'docker'
|
6
|
+
|
7
|
+
CONFIG_FILE = './config.yml'.freeze
|
8
|
+
START_FILE = './start.sh'.freeze
|
9
|
+
PREPARE_BUILD_FILE = './prepare_build.sh'.freeze
|
10
|
+
BUILD_FILE = './build.sh'.freeze
|
11
|
+
CLEANUP_FILE = './cleanup.sh'.freeze
|
12
|
+
|
13
|
+
def docker args
|
14
|
+
opted_dir = args[2]
|
15
|
+
assert_directory_provided(opted_dir)
|
16
|
+
dir = expanded_path(opted_dir)
|
17
|
+
|
18
|
+
case instruction = args[1]
|
19
|
+
when 'i', 'install'
|
20
|
+
|
21
|
+
docker_install(dir, working_dir_opted: working_dir_opted?(opted_dir))
|
22
|
+
|
23
|
+
when 'b', 'build'
|
24
|
+
|
25
|
+
docker_build(dir, {
|
26
|
+
update_runner_only: args.find {|a| a == '-u'},
|
27
|
+
push_opted: args.find {|a| a == '-p'}
|
28
|
+
})
|
29
|
+
|
30
|
+
when 'u', 'update'
|
31
|
+
|
32
|
+
docker_update(dir)
|
33
|
+
|
34
|
+
else
|
35
|
+
unknown_instruction_error!(instruction, 'install (or i)', 'build (or b)', 'update (or u)')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def docker_install dir, opts
|
40
|
+
create_dirname_for(dir)
|
41
|
+
assert_installable_dir(dir, opts[:working_dir_opted])
|
42
|
+
Docker::Install.new(dir, opts)
|
43
|
+
end
|
44
|
+
|
45
|
+
def docker_build dir, opts
|
46
|
+
assert_directory_exists(dir)
|
47
|
+
assert_config_file_exists(dir)
|
48
|
+
Docker::Build.new(dir, opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
def docker_update dir
|
52
|
+
assert_is_docker_dir(dir)
|
53
|
+
Docker::Update.new(dir)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
require 'appril-cli/docker/install'
|
60
|
+
require 'appril-cli/docker/build'
|
61
|
+
require 'appril-cli/docker/update'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Generator
|
4
|
+
|
5
|
+
def generator args
|
6
|
+
|
7
|
+
case instruction = args[1]
|
8
|
+
when 'api', 'a'
|
9
|
+
api_name = args[2]
|
10
|
+
assert_valid_api_name_given(api_name)
|
11
|
+
|
12
|
+
app_dir = args[3]
|
13
|
+
assert_directory_provided(app_dir)
|
14
|
+
app_dir = expanded_path(app_dir)
|
15
|
+
assert_is_app_dir(app_dir)
|
16
|
+
|
17
|
+
gen_dir = app_dir / 'generators/api'
|
18
|
+
assert_directory_exists(gen_dir)
|
19
|
+
|
20
|
+
api_dir = app_dir / "base/api/#{api_name}"
|
21
|
+
assert_directory_does_not_exists(api_dir)
|
22
|
+
|
23
|
+
Generator::API.new(gen_dir, api_dir, api_name)
|
24
|
+
else
|
25
|
+
unknown_instruction_error!(instruction, 'api (or a)')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'appril-cli/generator/api'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Appril
|
2
|
+
class CLI
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def display_error error
|
6
|
+
puts "", "\t::: #{error} :::", ""
|
7
|
+
end
|
8
|
+
|
9
|
+
def fatal_error! error, exit_code = 1
|
10
|
+
display_error(error)
|
11
|
+
exit exit_code
|
12
|
+
end
|
13
|
+
|
14
|
+
def expanded_path *path
|
15
|
+
Pathname.new(File.expand_path(File.join(*path.map(&:to_s))))
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_dirname_for dir
|
19
|
+
FileUtils.mkdir_p(File.dirname(dir))
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_executable *entries
|
23
|
+
entries.flatten.each {|e| FileUtils.chmod('+x', e)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def working_dir_opted? opted_dir
|
27
|
+
opted_dir == '.'
|
28
|
+
end
|
29
|
+
|
30
|
+
def extract_namespace args
|
31
|
+
return unless index = args.index('-n')
|
32
|
+
return unless namespace = args[index + 1]
|
33
|
+
if namespace =~ /::/
|
34
|
+
fatal_error! "Nested namespaces not supported"
|
35
|
+
end
|
36
|
+
if namespace =~ /\W/
|
37
|
+
fatal_error! "Namespace may contain only alphanumerics"
|
38
|
+
end
|
39
|
+
unless namespace =~ /\A[A-Z]/
|
40
|
+
fatal_error! "Namespace should start with a capital letter"
|
41
|
+
end
|
42
|
+
namespace
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/appril-cli.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'yaml'
|
4
|
+
require 'pty'
|
5
|
+
|
6
|
+
module Appril
|
7
|
+
class CLI
|
8
|
+
BASE_DIR = Pathname.new(File.expand_path('../..', __FILE__))
|
9
|
+
BOILERPLATE_DIR = BASE_DIR / 'boilerplate'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'appril-cli/version'
|
14
|
+
require 'appril-cli/helpers'
|
15
|
+
require 'appril-cli/assertions'
|
16
|
+
require 'appril-cli/app'
|
17
|
+
require 'appril-cli/generator'
|
18
|
+
require 'appril-cli/docker'
|
19
|
+
|
20
|
+
module Appril
|
21
|
+
class CLI
|
22
|
+
|
23
|
+
include Helpers
|
24
|
+
include Assertions
|
25
|
+
include Docker
|
26
|
+
include App
|
27
|
+
include Generator
|
28
|
+
|
29
|
+
def initialize args
|
30
|
+
case command = args[0]
|
31
|
+
when 'a', 'app'
|
32
|
+
app(args)
|
33
|
+
when 'g', 'gen', 'generate'
|
34
|
+
generator(args)
|
35
|
+
when 'd', 'docker'
|
36
|
+
docker(args)
|
37
|
+
when 'v', '-v', '--version'
|
38
|
+
puts VERSION
|
39
|
+
when nil, '-h', '--help'
|
40
|
+
usage
|
41
|
+
else
|
42
|
+
display_error "Unknown command #{command}"
|
43
|
+
usage
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def usage
|
49
|
+
puts "
|
50
|
+
Arguments in round brackets are required.
|
51
|
+
Arguments in square brackets are optional.
|
52
|
+
|
53
|
+
|
54
|
+
=== Install a new app ===
|
55
|
+
$ appril (app || a) (install || i) (dir || .) [-crudle]
|
56
|
+
* If -crudle option provided it will install a Crudle app
|
57
|
+
|
58
|
+
=== Update existing app ===
|
59
|
+
$ appril (app || a) (update || u) (dir || .)
|
60
|
+
|
61
|
+
=== Generate a new API ===
|
62
|
+
$ appril (generate || g) (api) (api name) (dir || .)
|
63
|
+
|
64
|
+
=== Install Docker builder ===
|
65
|
+
$ appril (docker || d) (install || i) (dir || .)
|
66
|
+
|
67
|
+
=== Update Docker builder ===
|
68
|
+
$ appril (docker || d) (update || u) (dir || .)
|
69
|
+
|
70
|
+
=== Build Docker image and install run script ===
|
71
|
+
$ appril (docker || d) (build || b) (dir || .) [-u] [-p]
|
72
|
+
* If -u option provided it will only update the run script without building the image.
|
73
|
+
* If -p option provided it will try to push the image to Docker registry after successful build.
|
74
|
+
|
75
|
+
=== Usage ===
|
76
|
+
$ appril [-h || --help]
|
77
|
+
".split("\n").map {|l| "\t" + l.strip}.join("\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def unknown_instruction_error! instruction, *available_instructions
|
82
|
+
fatal_error! "Unknown instruction #{instruction}. Use one of #{available_instructions*', '}"
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def self.run cmd
|
87
|
+
puts "", "$ #{cmd}"
|
88
|
+
PTY.spawn cmd do |r, w, pid|
|
89
|
+
begin
|
90
|
+
r.sync
|
91
|
+
r.each_char do |char|
|
92
|
+
print(char)
|
93
|
+
end
|
94
|
+
rescue Errno::EIO => e
|
95
|
+
# simply ignoring this
|
96
|
+
ensure
|
97
|
+
Process.wait(pid)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/sandbox/.gitignore
ADDED
data/sandbox/.pryrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../core/load', __FILE__)
|
data/sandbox/Gemfile
ADDED
data/sandbox/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../core/load', __FILE__)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class BaseController < Appril::BaseController
|
2
|
+
include Helpers
|
3
|
+
|
4
|
+
map Cfg.server_url
|
5
|
+
|
6
|
+
define_layout :layout, file: '../templates/layout'
|
7
|
+
layout :layout
|
8
|
+
engine :Liquid
|
9
|
+
define_template(:get) {''}
|
10
|
+
define_template_var(:client_url, Cfg.client_url)
|
11
|
+
|
12
|
+
def get
|
13
|
+
render
|
14
|
+
end
|
15
|
+
|
16
|
+
error 500 do |e|
|
17
|
+
puts "\e[0;31m%s\e[0m" % e.inspect
|
18
|
+
e.backtrace && e.backtrace.each {|l| puts " \e[0;36m%s\e[0m" % l}
|
19
|
+
e.message
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class RTCPController < Appril::RTCPController
|
2
|
+
map File.join(Cfg.server_url, '__rtcp__')
|
3
|
+
|
4
|
+
private
|
5
|
+
# called after socket connection established
|
6
|
+
def connected
|
7
|
+
end
|
8
|
+
|
9
|
+
# data sent to client after connection established
|
10
|
+
def initialization_data
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
|
14
|
+
# merged into original env when calling a controller
|
15
|
+
def rtcp_env
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
|
19
|
+
# called when socket connection closed
|
20
|
+
def disconnected
|
21
|
+
end
|
22
|
+
end
|
File without changes
|
@@ -0,0 +1,128 @@
|
|
1
|
+
_ =
|
2
|
+
merge: require('lodash/merge')
|
3
|
+
has: require('lodash/has')
|
4
|
+
isFunction: require('lodash/isFunction')
|
5
|
+
#end
|
6
|
+
|
7
|
+
Core = require('appril')
|
8
|
+
Page = require('appril-page')
|
9
|
+
Render = require('appril-ractive')
|
10
|
+
Reporter = require('appril-reporter')
|
11
|
+
require 'appril-polyfills'
|
12
|
+
require 'assets/styles.css'
|
13
|
+
|
14
|
+
CONSIDER_IDLE_AFTER = 5 * 60
|
15
|
+
|
16
|
+
window.Cfg = {}
|
17
|
+
window.Util = {}
|
18
|
+
window.App = {}
|
19
|
+
# window.Alert = require('appril-alert')
|
20
|
+
|
21
|
+
for k, v of require('appril-util')
|
22
|
+
Util[k] = v
|
23
|
+
#end
|
24
|
+
|
25
|
+
# for k, v of require('appril-datetime')
|
26
|
+
# Util[k] = v
|
27
|
+
# #end
|
28
|
+
|
29
|
+
for k, v of require('helpers/application_helpers.coffee')
|
30
|
+
Util[k] = v
|
31
|
+
#end
|
32
|
+
|
33
|
+
Object.freeze(Util)
|
34
|
+
|
35
|
+
Render.default_el = -> '#content'
|
36
|
+
Render.global_data = -> {App: App, Cfg: Cfg, Util: Util}
|
37
|
+
Render.global_handlers = -> {}
|
38
|
+
|
39
|
+
for name, controller of Core.controllers
|
40
|
+
App[name] = controller
|
41
|
+
#end
|
42
|
+
|
43
|
+
Core.on_initialize = (msg) ->
|
44
|
+
if window.Cfg = msg.data.cfg
|
45
|
+
delete msg.data.cfg
|
46
|
+
Object.freeze(Cfg)
|
47
|
+
|
48
|
+
for k, v of msg.data
|
49
|
+
App[k] = v
|
50
|
+
#end
|
51
|
+
|
52
|
+
Reporter CONSIDER_IDLE_AFTER, (status) ->
|
53
|
+
# close connection if user went away
|
54
|
+
Core.disconnect() if status == 'away'
|
55
|
+
#end
|
56
|
+
#end
|
57
|
+
|
58
|
+
templates =
|
59
|
+
none: require('templates/layouts/none.html')
|
60
|
+
main: require('templates/layouts/main.html')
|
61
|
+
access_denied: require('templates/access_denied.html')
|
62
|
+
#end
|
63
|
+
|
64
|
+
partials = {}
|
65
|
+
|
66
|
+
Crudle = require('crudle')
|
67
|
+
CrudleList = require('crudle-list')
|
68
|
+
CrudleEditor = require('crudle-editor')
|
69
|
+
|
70
|
+
deploy_api = (api) ->
|
71
|
+
|
72
|
+
page = new Page
|
73
|
+
env = _.merge({
|
74
|
+
render: Render
|
75
|
+
render_component: Render.component
|
76
|
+
render_string: Render.string
|
77
|
+
}, page)
|
78
|
+
|
79
|
+
crudle = Crudle(api.controller.ws, page)
|
80
|
+
crudle.partials.menu = require('templates/menu.html')
|
81
|
+
crudle.data.url = api.controller.url
|
82
|
+
|
83
|
+
api(
|
84
|
+
env,
|
85
|
+
crudle,
|
86
|
+
CrudleList(api.controller.ws, page),
|
87
|
+
CrudleEditor(api.controller.ws, page)
|
88
|
+
)
|
89
|
+
#end
|
90
|
+
|
91
|
+
previous_api = null
|
92
|
+
Core.on_controller_matched = (controller, context) ->
|
93
|
+
|
94
|
+
controller.load (api) ->
|
95
|
+
context.save()
|
96
|
+
|
97
|
+
api.controller = controller
|
98
|
+
|
99
|
+
if previous_api?.teardown
|
100
|
+
previous_api.teardown()
|
101
|
+
#end
|
102
|
+
previous_api = api
|
103
|
+
|
104
|
+
if _.has(api, 'acl')
|
105
|
+
unless _.isFunction(api.acl)
|
106
|
+
throw new Error("#{controller.name}.acl should be a function")
|
107
|
+
|
108
|
+
if api.acl()
|
109
|
+
deploy_api(api)
|
110
|
+
else
|
111
|
+
Render
|
112
|
+
el: 'body'
|
113
|
+
template: templates.main
|
114
|
+
partials: partials
|
115
|
+
oncomplete: ->
|
116
|
+
Render(template: templates.access_denied)
|
117
|
+
#end
|
118
|
+
|
119
|
+
else
|
120
|
+
deploy_api(api)
|
121
|
+
#end
|
122
|
+
#end
|
123
|
+
#end
|
124
|
+
|
125
|
+
document.addEventListener 'DOMContentLoaded', ->
|
126
|
+
# make sure this matches the RTCPController URL.
|
127
|
+
Core.connect('__rtcp__')
|
128
|
+
#end
|
@@ -0,0 +1 @@
|
|
1
|
+
# this file will be loaded before other files found in helpers/ folder
|