nutella_framework 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/README.md +3 -4
- data/VERSION +1 -1
- data/data/startup +3 -3
- data/framework_components/example_framework_interface/dandelion-flowers-card.jpg +0 -0
- data/framework_components/example_framework_interface/index.html +18 -0
- data/framework_components/main_interface/main_interface_bot.rb +183 -0
- data/framework_components/main_interface/public/index.html +54 -0
- data/framework_components/main_interface/views/index.erb +63 -0
- data/framework_components/order.json.example +6 -0
- data/framework_components/runs_list_bot/app_runs_list_bot.rb +15 -0
- data/lib/{core/commands → commands}/broker.rb +2 -2
- data/lib/{core/commands → commands}/checkup.rb +2 -2
- data/lib/commands/compile.rb +13 -0
- data/lib/commands/dependencies.rb +13 -0
- data/lib/commands/help.rb +35 -0
- data/lib/{core/commands → commands}/install.rb +19 -15
- data/lib/commands/meta/command.rb +19 -0
- data/lib/commands/meta/run_command.rb +114 -0
- data/lib/{core → commands/meta}/template_command.rb +1 -1
- data/lib/commands/new.rb +60 -0
- data/lib/commands/runs.rb +54 -0
- data/lib/commands/start.rb +321 -0
- data/lib/commands/stop.rb +101 -0
- data/lib/{core/commands → commands}/template.rb +59 -39
- data/lib/config/current_app_utils.rb +51 -0
- data/lib/config/persisted_hash.rb +14 -12
- data/lib/config/runlist.rb +116 -16
- data/lib/{cli → core}/nutella_cli.rb +1 -1
- data/lib/core/nutella_core.rb +2 -6
- data/lib/nutella_framework.rb +5 -3
- data/lib/nutella_lib_framework/api.rb +333 -0
- data/lib/tmux/tmux.rb +76 -0
- data/nutella_framework.gemspec +42 -29
- data/test/commands/test_cmd_cli_params_parsing.rb +56 -0
- data/test/commands/test_command_template.rb +31 -0
- data/test/config/test_current_app_utils.rb +34 -0
- data/test/config/test_persisted_hash.rb +48 -0
- data/test/config/test_runlist.rb +15 -23
- data/test/framework_apis/test_framework_api.rb +74 -0
- metadata +74 -27
- data/actors/main_interface/main_interface_bot.rb +0 -163
- data/actors/main_interface/public/index.html +0 -51
- data/actors/main_interface/views/index.erb +0 -45
- data/lib/config/current_project.rb +0 -58
- data/lib/core/command.rb +0 -12
- data/lib/core/commands/compile.rb +0 -21
- data/lib/core/commands/dependencies.rb +0 -21
- data/lib/core/commands/help.rb +0 -28
- data/lib/core/commands/new.rb +0 -60
- data/lib/core/commands/runs.rb +0 -52
- data/lib/core/commands/start.rb +0 -271
- data/lib/core/commands/stop.rb +0 -100
- data/lib/core/run_command.rb +0 -106
- data/lib/core/tmux.rb +0 -38
- data/test/config/test_config.rb +0 -48
- data/test/config/test_project.rb +0 -34
- data/test/test_run_command.rb +0 -54
- /data/{actors → framework_components}/main_interface/startup +0 -0
- /data/{actors → framework_components}/main_interface/views/not_found_404.erb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98a1d74bc599d78623959deb2d80d7ef4b5527b0
|
4
|
+
data.tar.gz: 229db1d35c9f3000f6510fa44e075878e21b7f07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0673b2e12cd08dd77e2359b3aa05f7d0d9d6b36e415de55f0df13ef201887fd5c1e0303e695bef502cc2b877df6b72a4aa405d358375ff0498635a4178337322
|
7
|
+
data.tar.gz: 274b0ea11c7671bb8cb42f1d1179026f5a6cfb04d3af52a60d91b3e3a8d97d804457b248203733b821cc2b75bd7ff390c2e1089822627a5525bbea7a8640ae74
|
data/Gemfile
CHANGED
@@ -5,8 +5,10 @@ gem 'semantic', '~> 1.3', '>=1.3'
|
|
5
5
|
gem 'logging', '~> 1.8', '>=1.8.2'
|
6
6
|
gem 'git', '~> 1.2', '>=1.2.8'
|
7
7
|
gem 'sinatra', '~>1.4.5', '>=1.4.5'
|
8
|
+
gem 'thin', '~>1.6.3', '>=1.6.3'
|
8
9
|
gem 'nokogiri', '~>1.6.3', '>=1.6.3'
|
9
10
|
gem 'slop', '~>4.0.0', '>=4.0.0'
|
11
|
+
gem 'nutella_lib','~>0.4.0', '>=0.4.0'
|
10
12
|
|
11
13
|
|
12
14
|
group :development do
|
@@ -20,4 +22,5 @@ end
|
|
20
22
|
|
21
23
|
group :test do
|
22
24
|
gem 'rake'
|
25
|
+
gem 'fakefs', '~> 0.6.7', '>= 0.6'
|
23
26
|
end
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/nutella_framework.svg)](http://badge.fury.io/rb/nutella_framework)
|
3
|
-
[![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
|
4
|
-
[![Dependency Status](https://gemnasium.com/nutella-framework/nutella_framework.svg)](https://gemnasium.com/nutella-framework/nutella_framework)
|
3
|
+
[![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
|
5
4
|
[![Code Climate](https://codeclimate.com/github/nutella-framework/nutella_framework/badges/gpa.svg)](https://codeclimate.com/github/nutella-framework/nutella_framework)
|
6
5
|
|
7
6
|
# Nutella
|
@@ -34,9 +33,9 @@ Congratulations! Nutella is ready to use!
|
|
34
33
|
|
35
34
|
|
36
35
|
# Where next?
|
37
|
-
If you already have
|
36
|
+
If you already have an application you want to tinker with (like [RoomQuake](https://github.com/ltg-uic/roomquake)) simply checkout the application to a local folder, `cd /to/my/local/folder` and start tinkering away. Not sure what to do? Check out our [nutella Command Line Tool man page](https://github.com/nutella-framework/nutella_framework/wiki/Nutella-Command-Line-Interface).
|
38
37
|
|
39
|
-
If you want to create your own
|
38
|
+
If you want to create your own application, check out the [new app tutorial](https://github.com/nutella-framework/nutella_framework/wiki/New-application-tutorial).
|
40
39
|
|
41
40
|
|
42
41
|
# Contributing
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/data/startup
CHANGED
@@ -6,8 +6,8 @@
|
|
6
6
|
BASEDIR=$(dirname $0)
|
7
7
|
|
8
8
|
|
9
|
-
# Remember
|
10
|
-
# command line parameters that you can access via $1 and $
|
9
|
+
# Remember: nutella passes the `broker address`, the `app_id` and the `run_id`
|
10
|
+
# as command line parameters that you can access via $1, $2 and $3 respectively.
|
11
11
|
|
12
12
|
# Start your bot here with something like (example in ruby):
|
13
|
-
# ruby $BASEDIR/my_bot.rb $1 $2
|
13
|
+
# ruby $BASEDIR/my_bot.rb $1 $2 $3
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head lang="en">
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title>Example framework interface</title>
|
6
|
+
<!-- The description of this interfaces here -->
|
7
|
+
<meta name="description" content="This is an example framework interface">
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<h1>Example framework interface</h1>
|
11
|
+
<p>This is an example of a framework interface. It really doesn't belong here but for now this
|
12
|
+
is ok. Once we'll have real framework interfaces this is going to be be moved to a template.
|
13
|
+
</p>
|
14
|
+
<p>And just to make sure we are loading not just the index, here is a picture of dandelions</p>
|
15
|
+
<img src="dandelion-flowers-card.jpg" width="500">
|
16
|
+
|
17
|
+
</body>
|
18
|
+
</html>
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
# Configuration file and runlist (runlist as global)
|
6
|
+
config_file = ARGV[0]
|
7
|
+
$runlist_file = ARGV[1]
|
8
|
+
|
9
|
+
# Try to parse the both config file and runlist and terminate if we can't
|
10
|
+
begin
|
11
|
+
config_h = JSON.parse(IO.read(config_file))
|
12
|
+
JSON.parse(IO.read($runlist_file))
|
13
|
+
rescue
|
14
|
+
# something went wrong
|
15
|
+
abort 'Impossible to parse configuration and/or runlist files!'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set Sinatra to run in production mode
|
19
|
+
set :environment, :production
|
20
|
+
|
21
|
+
# Set Sinatra's port to nutella's main_interface_port
|
22
|
+
set :port, config_h['main_interface_port']
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
# Display the form to input the app_id and run_id
|
28
|
+
get '/' do
|
29
|
+
send_file 'public/index.html'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Redirect if there is no slash after the run_id
|
33
|
+
get '/:app_id/:run_id' do
|
34
|
+
redirect "#{request.url}/"
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Renders the interfaces summary page for the run
|
39
|
+
get '/:app_id/:run_id/' do
|
40
|
+
# Parse the app_id and run_id from URL and extract the run path from runlist.json
|
41
|
+
@app_id = params[:app_id]
|
42
|
+
@run_id = params[:run_id]
|
43
|
+
@app_path = get_app_path @app_id
|
44
|
+
# If there is no app with this name, render error page
|
45
|
+
return erb( :not_found_404, :locals => {:not_found_type => 'run'} ) if @app_path.nil?
|
46
|
+
# To generate the 'index.erb' we need to load a bunch of details
|
47
|
+
# (folder, title/name, description) for each interface
|
48
|
+
@interfaces = load_interfaces_details @app_path
|
49
|
+
@framework_interfaces = load_framework_interfaces
|
50
|
+
# Render the interfaces summary page
|
51
|
+
erb :index
|
52
|
+
end
|
53
|
+
|
54
|
+
# Redirect if there is a slash after the interface
|
55
|
+
get '/:app_id/:run_id/:interface/' do
|
56
|
+
redirect "#{request.url[0..-2]}"
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Serves the index.html file for each individual interface augmented with nutella query string parameters
|
61
|
+
get '/:app_id/:run_id/runs/:interface' do
|
62
|
+
# Parse the app_id and run_id from URL and extract the run path from runlist.json
|
63
|
+
app_id = params[:app_id]
|
64
|
+
run_id = params[:run_id]
|
65
|
+
interface = params[:interface]
|
66
|
+
app_path = get_app_path app_id
|
67
|
+
# Compose the path of interface index file passing the nutella parameters
|
68
|
+
index_file_path = "#{app_path}/interfaces/#{interface}/index.html"
|
69
|
+
# If the index file doesn't exist, render error page
|
70
|
+
return erb( :not_found_404, :locals => {:not_found_type => 'idx'} ) unless File.exist? index_file_path
|
71
|
+
# If the index file exists, compose query string and redirect
|
72
|
+
index_with_query_url = "#{request.path}/index.html?broker=#{config_h['broker']}&app_id=#{app_id}&run_id=#{run_id}"
|
73
|
+
redirect index_with_query_url
|
74
|
+
end
|
75
|
+
|
76
|
+
# Serves the files contained in each interface folder
|
77
|
+
get '/:app_id/:run_id/runs/:interface/*' do
|
78
|
+
# Parse the run_id, the interface name and the file_path from URL
|
79
|
+
app_id = params[:app_id]
|
80
|
+
interface = params[:interface]
|
81
|
+
relative_file_path = params[:splat][0]
|
82
|
+
app_path = get_app_path app_id
|
83
|
+
# Compose the path of the file we are trying to serve
|
84
|
+
file_path = "#{app_path}/interfaces/#{interface}/#{relative_file_path}"
|
85
|
+
# If the file we are trying to serve doesn't exist, render error page
|
86
|
+
return erb( :not_found_404, :locals => {:not_found_type => 'file'} ) unless File.exist? file_path
|
87
|
+
# If the file exists, render it
|
88
|
+
send_file file_path
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
# Serve the index file for a framework interface passing the nutella parameters
|
93
|
+
get '/:app_id/:run_id/framework/:interface' do
|
94
|
+
app_id = params[:app_id]
|
95
|
+
run_id = params[:run_id]
|
96
|
+
# Filesystem path to the index file
|
97
|
+
index_file_path = "#{File.dirname(__FILE__)}/../#{params[:interface]}/index.html"
|
98
|
+
# If the index file doesn't exist, render error page
|
99
|
+
return erb( :not_found_404, :locals => {:not_found_type => 'idx'} ) unless File.exist? index_file_path
|
100
|
+
# If the index file exists, compose query string and redirect
|
101
|
+
index_with_query_url = "#{request.path}/index.html?broker=#{config_h['broker']}&app_id=#{app_id}&run_id=#{run_id}"
|
102
|
+
redirect index_with_query_url
|
103
|
+
end
|
104
|
+
|
105
|
+
# Serves the files contained in each framework interface folder
|
106
|
+
get '/:app_id/:run_id/framework/:interface/*' do
|
107
|
+
# Fetch the relative file path
|
108
|
+
relative_file_path = params[:splat][0]
|
109
|
+
# Compose the path of the file we are trying to serve
|
110
|
+
file_path = "#{File.dirname(__FILE__)}/../#{params[:interface]}/#{relative_file_path}"
|
111
|
+
# If the file we are trying to serve doesn't exist, render error page
|
112
|
+
return erb( :not_found_404, :locals => {:not_found_type => 'file'} ) unless File.exist? file_path
|
113
|
+
# If the file exists, render it
|
114
|
+
send_file file_path
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# Utility functions -------------------------------------------------------------------------
|
119
|
+
|
120
|
+
# Utility function:
|
121
|
+
# Gets the path associated with a certain application
|
122
|
+
def get_app_path( app_id )
|
123
|
+
begin
|
124
|
+
runs_h = JSON.parse(IO.read($runlist_file))
|
125
|
+
runs_h[app_id]['path']
|
126
|
+
rescue
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Utility function:
|
132
|
+
# Loads all the details for all interfaces and stores them into an array of hashes
|
133
|
+
def load_interfaces_details( app_path )
|
134
|
+
interfaces = Array.new
|
135
|
+
interfaces_path = "#{app_path}/interfaces/"
|
136
|
+
Dir.entries(interfaces_path).select {|entry| File.directory?(File.join(interfaces_path, entry)) && !(entry =='.' || entry == '..') }.each do |iface_dir|
|
137
|
+
interfaces.push extract_interface_info( interfaces_path, iface_dir )
|
138
|
+
end
|
139
|
+
interfaces
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def load_framework_interfaces
|
144
|
+
interfaces = Array.new
|
145
|
+
components_directory = "#{File.dirname(__FILE__)}/../"
|
146
|
+
Dir.entries(components_directory).select {|entry| File.directory?(File.join(components_directory, entry)) && !(entry =='.' || entry == '..') }.each do |iface_dir|
|
147
|
+
interfaces.push(extract_interface_info( components_directory, iface_dir)) if File.exist?("#{components_directory}#{iface_dir}/index.html")
|
148
|
+
end
|
149
|
+
interfaces
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
# Utility function:
|
154
|
+
# Extracts name, description and folder for a single interface from it's index.html
|
155
|
+
def extract_interface_info( interfaces_path, iface_dir )
|
156
|
+
iface_properties = Hash.new
|
157
|
+
index_path = "#{interfaces_path}#{iface_dir}/index.html"
|
158
|
+
unless File.exist? index_path
|
159
|
+
iface_properties[:name] = iface_dir
|
160
|
+
iface_properties[:description] = 'My designer was a bit lazy and didn\'t include an index.html file in the main interface directory :('
|
161
|
+
return iface_properties
|
162
|
+
end
|
163
|
+
|
164
|
+
# If file exists, parse it and extract info
|
165
|
+
f = File.open index_path
|
166
|
+
doc = Nokogiri::HTML f
|
167
|
+
f.close
|
168
|
+
# Extract interface name from title
|
169
|
+
iface_properties[:name] = (doc.css('title').empty? || doc.css('title').text.empty? ) ? iface_dir : doc.css('title').text
|
170
|
+
# Extract description from meta description tag
|
171
|
+
if doc.css("meta[name='description']").empty?
|
172
|
+
iface_properties[:description] = 'My designer was a bit lazy and didn\'t include a <meta name="description" content="Description of this interface"> tag in the index.html file :('
|
173
|
+
else
|
174
|
+
if doc.css("meta[name='description']").attribute('content').nil?
|
175
|
+
iface_properties[:description] = 'There was no attribute content in <meta name="description" content="Description of this interface"> tag in the index.html file :('
|
176
|
+
else
|
177
|
+
iface_properties[:description] = doc.css("meta[name='description']").attribute('content').text
|
178
|
+
end
|
179
|
+
end
|
180
|
+
# Extract URL from interface dir
|
181
|
+
iface_properties[:url] = iface_dir
|
182
|
+
iface_properties
|
183
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<title>Welcome to nutella</title>
|
8
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
9
|
+
|
10
|
+
<style type="text/css">
|
11
|
+
div {
|
12
|
+
margin-top: 4em;
|
13
|
+
text-align: center;
|
14
|
+
font-size: 3em;
|
15
|
+
}
|
16
|
+
.form-control {
|
17
|
+
height: 50px;
|
18
|
+
width: 20%;
|
19
|
+
text-align: center;
|
20
|
+
font-size: .7em;
|
21
|
+
display: inline-block;
|
22
|
+
}
|
23
|
+
.center form {
|
24
|
+
display:inline-block;
|
25
|
+
}
|
26
|
+
</style>
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
|
30
|
+
<!-- Content -->
|
31
|
+
<div>
|
32
|
+
<p>What is your app id?
|
33
|
+
<input id="app_id_input" type="text" value="" class="form-control" autofocus>
|
34
|
+
</p>
|
35
|
+
<br />
|
36
|
+
<p>What is your run id?
|
37
|
+
<input id="run_id_input" type="text" value="" class="form-control" >
|
38
|
+
</p>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<!-- Scripts -->
|
42
|
+
<script>
|
43
|
+
app_id_el = document.getElementById('app_id_input');
|
44
|
+
run_id_el = document.getElementById('run_id_input');
|
45
|
+
run_id_el.addEventListener('change', function() {
|
46
|
+
var url = location.href
|
47
|
+
if (url.substr(url.length - 1)=="/")
|
48
|
+
window.location = url + app_id_el.value + '/' + this.value + '/';
|
49
|
+
else
|
50
|
+
window.location = url + '/' + app_id_el.value + '/'+ this.value + '/';
|
51
|
+
});
|
52
|
+
</script>
|
53
|
+
</body>
|
54
|
+
</html>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
+
<title><%= @app_id %> interfaces</title>
|
8
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
9
|
+
|
10
|
+
<style type="text/css">
|
11
|
+
.row {
|
12
|
+
margin-bottom: 20px;
|
13
|
+
}
|
14
|
+
</style>
|
15
|
+
</head>
|
16
|
+
<body>
|
17
|
+
|
18
|
+
<!-- Content -->
|
19
|
+
<div class="container">
|
20
|
+
|
21
|
+
<!-- Title and prompt -->
|
22
|
+
<div class="page-header">
|
23
|
+
<% if @run_id == 'default' %>
|
24
|
+
<h1>Welcome to <em><%= @app_id %></em></h1>
|
25
|
+
<% else %>
|
26
|
+
<h1>Welcome to <em><%= @app_id %></em>, run <em><%= @run_id %></em></h1>
|
27
|
+
<% end %>
|
28
|
+
<p class="lead">Use the buttons below to launch a specific interface</p>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<!-- Run level interfaces -->
|
32
|
+
<% @interfaces.each do |i| %>
|
33
|
+
<div class="row">
|
34
|
+
<div class="col-xs-1 col-sm-1 col-lg-1"><a href="runs/<%= i[:url] %>" target="_blank" type="button" class="btn btn-danger">Launch!</a></div>
|
35
|
+
<div class="col-xs-2 col-sm-2 col-lg-2 text-center"><strong><%= i[:name] %></strong></div>
|
36
|
+
<div class="col-xs-9 col-sm-9 col-lg-9"><%= i[:description] %></div>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
|
40
|
+
<!-- Framework level interfaces -->
|
41
|
+
|
42
|
+
<hr>
|
43
|
+
<div class="row">
|
44
|
+
<h2>Framework level interfaces</h2>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<% @framework_interfaces.each do |i| %>
|
48
|
+
<div class="row">
|
49
|
+
<div class="col-xs-1 col-sm-1 col-lg-1"><a href="framework/<%= i[:url] %>" target="_blank" type="button" class="btn btn-danger">Launch!</a></div>
|
50
|
+
<div class="col-xs-2 col-sm-2 col-lg-2 text-center"><strong><%= i[:name] %></strong></div>
|
51
|
+
<div class="col-xs-9 col-sm-9 col-lg-9"><%= i[:description] %></div>
|
52
|
+
</div>
|
53
|
+
<% end %>
|
54
|
+
|
55
|
+
|
56
|
+
</div>
|
57
|
+
|
58
|
+
<!-- Scripts -->
|
59
|
+
<script>
|
60
|
+
|
61
|
+
</script>
|
62
|
+
</body>
|
63
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'nutella_lib'
|
2
|
+
|
3
|
+
# This needs to be initialized as framework component like so:
|
4
|
+
# nutella.init_as_app_component('localhost', 'app_runs_list_bot')
|
5
|
+
nutella.init('localhost', 'my_app_id', 'no_run_id', 'app_runs_list_bot')
|
6
|
+
|
7
|
+
# Listen for runs_list requests (done by app components when they connect)
|
8
|
+
nutella.net.app.handle_requests('app_runs_list', lambda do |req, from|
|
9
|
+
from['app_id'] # Use this info to fetch the appropriate runs
|
10
|
+
['run_1', 'run_2', 'run_3'] # Return an array of names!
|
11
|
+
end)
|
12
|
+
|
13
|
+
# Whenever the list is updated, fire an update to the right app
|
14
|
+
|
15
|
+
nutella.net.listen
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'commands/meta/command'
|
2
2
|
require 'socket'
|
3
3
|
|
4
4
|
module Nutella
|
@@ -36,7 +36,7 @@ module Nutella
|
|
36
36
|
def change_broker( new_broker )
|
37
37
|
# Check that there are no runs hinging on this broker
|
38
38
|
unless Nutella.runlist.empty?
|
39
|
-
console.warn 'You are currently running some
|
39
|
+
console.warn 'You are currently running some nutella applications on this broker. You can\'t change the broker while running.'
|
40
40
|
return
|
41
41
|
end
|
42
42
|
# Try to parse the hostname and switch to the new broker
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'commands/meta/command'
|
2
2
|
require 'semantic'
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class Checkup < Command
|
6
|
-
@description = 'Checks that all the dependencies are installed
|
6
|
+
@description = 'Checks that all the framework dependencies are installed'
|
7
7
|
|
8
8
|
def run( args=nil )
|
9
9
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'commands/meta/run_command'
|
2
|
+
require 'tmux/tmux'
|
3
|
+
|
4
|
+
module Nutella
|
5
|
+
class Compile < RunCommand
|
6
|
+
@description = 'Compiles all the components that need compilation in the application'
|
7
|
+
|
8
|
+
def run(args=nil)
|
9
|
+
compile_and_dependencies 'compile', 'Compiling', 'components compiled'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'commands/meta/command'
|
2
|
+
require 'tmux/tmux'
|
3
|
+
|
4
|
+
module Nutella
|
5
|
+
class Dependencies < RunCommand
|
6
|
+
@description = 'Installs the dependencies for all components in the application'
|
7
|
+
|
8
|
+
def run(args=nil)
|
9
|
+
compile_and_dependencies 'dependencies', 'Installing dependencies for', 'dependencies installed'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'commands/meta/command'
|
2
|
+
|
3
|
+
module Nutella
|
4
|
+
|
5
|
+
class Help < Command
|
6
|
+
@description = 'Displays what every command does and how to use it'
|
7
|
+
|
8
|
+
def run(args=nil)
|
9
|
+
message=''
|
10
|
+
Dir["#{File.dirname(__FILE__)}/*.rb"].each do |file|
|
11
|
+
message += add_cmd_help(file)
|
12
|
+
end
|
13
|
+
console.info message
|
14
|
+
console.success 'For more details on individual commands, see https://github.com/nutella-framework/nutella_framework/wiki/Nutella-Command-Line-Interface'
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def add_cmd_help(file)
|
20
|
+
command = File.basename(file, File.extname(file))
|
21
|
+
if command.length > 7
|
22
|
+
message = "#{command}\t"
|
23
|
+
else
|
24
|
+
message = "#{command}\t\t"
|
25
|
+
end
|
26
|
+
message += Object::const_get("Nutella::#{command.capitalize}").description
|
27
|
+
message += "\n"
|
28
|
+
message
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
@@ -1,15 +1,19 @@
|
|
1
|
-
require '
|
1
|
+
require 'commands/meta/template_command'
|
2
2
|
require 'git'
|
3
3
|
require 'net/http'
|
4
4
|
|
5
5
|
module Nutella
|
6
6
|
|
7
7
|
class Install < TemplateCommand
|
8
|
-
@description = 'Copies an arbitrary template (from central DB, directory or URL) into the current
|
8
|
+
@description = 'Copies an arbitrary template (from central DB, directory or URL) into the current application'
|
9
9
|
|
10
10
|
def run(args=nil)
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
# If the current directory is not a nutella application, return
|
13
|
+
unless Nutella.current_app.exist?
|
14
|
+
console.warn 'The current directory is not a nutella application'
|
15
|
+
return
|
16
|
+
end
|
13
17
|
|
14
18
|
# Check args
|
15
19
|
if args.empty?
|
@@ -19,16 +23,16 @@ module Nutella
|
|
19
23
|
template = args[0]
|
20
24
|
destination_dir = args.length==2 ? args[1] : nil
|
21
25
|
|
22
|
-
# Extract
|
23
|
-
|
26
|
+
# Extract application directory
|
27
|
+
app_path =Dir.pwd
|
24
28
|
|
25
29
|
# What kind of template are we handling?
|
26
30
|
if is_template_a_local_dir? template
|
27
|
-
add_local_template( template, template,
|
31
|
+
add_local_template( template, template, app_path, destination_dir )
|
28
32
|
elsif is_template_a_git_repo? template
|
29
|
-
add_remote_template( template,
|
33
|
+
add_remote_template( template, app_path, destination_dir)
|
30
34
|
elsif is_template_in_db? template
|
31
|
-
add_central_template( template,
|
35
|
+
add_central_template( template, app_path, destination_dir)
|
32
36
|
else
|
33
37
|
console.warn 'The specified template is not a valid nutella template'
|
34
38
|
end
|
@@ -55,7 +59,7 @@ module Nutella
|
|
55
59
|
tmp_dest_dir = template_git_url[template_git_url.rindex('/')+1 .. template_git_url.length]
|
56
60
|
end
|
57
61
|
clone_template_from_repo_to( template_git_url, tmp_dest_dir )
|
58
|
-
return validate_template "#{Nutella
|
62
|
+
return validate_template "#{Nutella::NUTELLA_TMP}/#{tmp_dest_dir}"
|
59
63
|
rescue
|
60
64
|
return false
|
61
65
|
end
|
@@ -106,21 +110,21 @@ module Nutella
|
|
106
110
|
|
107
111
|
def add_remote_template ( template, prj_dir, dest_dir)
|
108
112
|
template_name = template[template.rindex('/')+1 .. template.length-5]
|
109
|
-
template_dir = "#{Nutella
|
113
|
+
template_dir = "#{Nutella::NUTELLA_TMP}/#{template_name}"
|
110
114
|
add_local_template( template, template_dir, prj_dir, dest_dir )
|
111
115
|
end
|
112
116
|
|
113
117
|
|
114
118
|
def add_central_template( template_name, prj_dir, dest_dir)
|
115
|
-
template_dir = "#{Nutella
|
119
|
+
template_dir = "#{Nutella::NUTELLA_TMP}/#{template_name}"
|
116
120
|
add_local_template( template_name, template_dir, prj_dir, dest_dir )
|
117
121
|
end
|
118
122
|
|
119
123
|
|
120
124
|
def clone_template_from_repo_to(template, dest_dir)
|
121
125
|
clean_tmp_dir
|
122
|
-
Dir.mkdir Nutella
|
123
|
-
Git.clone(template, dest_dir, :path => Nutella
|
126
|
+
Dir.mkdir Nutella::NUTELLA_TMP unless Dir.exists? Nutella::NUTELLA_TMP
|
127
|
+
Git.clone(template, dest_dir, :path => Nutella::NUTELLA_TMP)
|
124
128
|
end
|
125
129
|
|
126
130
|
|
@@ -132,7 +136,7 @@ module Nutella
|
|
132
136
|
|
133
137
|
|
134
138
|
def clean_tmp_dir
|
135
|
-
FileUtils.rm_rf "#{Nutella
|
139
|
+
FileUtils.rm_rf "#{Nutella::NUTELLA_TMP}"
|
136
140
|
end
|
137
141
|
|
138
142
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Nutella
|
4
|
+
|
5
|
+
# Nutella command
|
6
|
+
class Command
|
7
|
+
|
8
|
+
class << self;
|
9
|
+
attr_accessor :description
|
10
|
+
end
|
11
|
+
|
12
|
+
# Commands overload this method to execute
|
13
|
+
def run( args=nil )
|
14
|
+
console.error 'Running the generic command!!! WAT? https://www.destroyallsoftware.com/talks/wat'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|