nutella_framework 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -2
- data/README.md +11 -11
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/framework_components/runs_list_bot/app_runs_list_bot.rb +45 -9
- data/framework_components/runs_list_bot/startup +8 -0
- data/lib/commands/start.rb +3 -0
- data/lib/config/current_app_utils.rb +7 -1
- data/lib/config/runlist.rb +12 -3
- data/nutella_framework.gemspec +11 -12
- data/nutella_lib/framework_core.rb +68 -0
- data/{lib/nutella_lib_framework/api.rb → nutella_lib/framework_net.rb} +205 -43
- data/test/framework_apis/test_framework_api.rb +1 -1
- metadata +11 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ee0147d7ad4b06c602ad742ad464804686a73af
|
4
|
+
data.tar.gz: 5255b9ac953ca5d4a2608943ed6d7fab61cebaaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e93582f785ccdebe69dd852033edd700935bc957a29844633d07d7001459d928e0b20b1d72f9740e67941a68c3fca1ab67f871ac2c9b3a1c8288fe540fe593f6
|
7
|
+
data.tar.gz: 23ac44867911110658384dce2379c8a3336868ce39e7f8cec1d07ff07ed04fb3a2790c22186d218f6cfe39e1e36ccf41c301a95953e340c174f957e21b6fa969
|
data/Gemfile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem 'ansi', '~> 1.4', '>= 1.4.3'
|
4
3
|
gem 'semantic', '~> 1.3', '>=1.3'
|
5
4
|
gem 'logging', '~> 1.8', '>=1.8.2'
|
6
5
|
gem 'git', '~> 1.2', '>=1.2.8'
|
@@ -8,7 +7,7 @@ gem 'sinatra', '~>1.4.5', '>=1.4.5'
|
|
8
7
|
gem 'thin', '~>1.6.3', '>=1.6.3'
|
9
8
|
gem 'nokogiri', '~>1.6.3', '>=1.6.3'
|
10
9
|
gem 'slop', '~>4.0.0', '>=4.0.0'
|
11
|
-
gem 'nutella_lib','~>0.4.
|
10
|
+
gem 'nutella_lib','~>0.4.1', '>=0.4.1'
|
12
11
|
|
13
12
|
|
14
13
|
group :development do
|
data/README.md
CHANGED
@@ -3,18 +3,18 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/nutella-framework/nutella_framework/badges/gpa.svg)](https://codeclimate.com/github/nutella-framework/nutella_framework)
|
5
5
|
|
6
|
-
|
7
|
-
Nutella is a framework to build and run classroom narratives. It's still _very_ under development so any help [finding and fixing bugs](https://github.com/nutella-framework/nutella_framework/issues) will be greatly appreciated!
|
6
|
+
nutella is a framework to build and run RoomApps. It's still _very_ under development so any help [finding and fixing bugs](https://github.com/nutella-framework/nutella_framework/issues) will be greatly appreciated!
|
8
7
|
|
9
8
|
# Installing
|
10
|
-
Nutella is written in ruby but it leverages
|
9
|
+
Nutella is written in ruby but it leverages a bunch of other technologies that need to be installed. You will need:
|
11
10
|
|
12
|
-
1. _ruby_ (version >= 2.1.0). Do yourself a favor and use [RVM](https://rvm.io/rvm/install).
|
13
|
-
1. _git_ (version >= 1.8.0). Do yourself a favor and use [Homebrew](http://brew.sh/) if you are on OSX.
|
14
|
-
1. _tmux_ (version >= 1.8.0). Do yourself a favor and use [Homebrew](http://brew.sh/) if you are on OSX.
|
11
|
+
1. _ruby_ (version >= 2.1.0). Do yourself a favor and use [RVM](https://rvm.io/rvm/install) to install Ruby.
|
12
|
+
1. _git_ (version >= 1.8.0). Do yourself a favor and use [Homebrew](http://brew.sh/) to install git, if you are on OSX.
|
13
|
+
1. _tmux_ (version >= 1.8.0). Do yourself a favor and use [Homebrew](http://brew.sh/) to install tmux, if you are on OSX.
|
15
14
|
1. _node.js_ (version >= 0.10.0). Yes, really, you need to install node becaue we use it to run the broker that handles all communications between all the pieces of the framework. Do yourself a favor and use [nvm](https://github.com/creationix/nvm).
|
15
|
+
1. _mongoDB_ (optional). You'll need mongoDB if you want to use it with `nutella.persist`.
|
16
16
|
|
17
|
-
Once you have all
|
17
|
+
Once you have all of these, to install nutella simply do:
|
18
18
|
```
|
19
19
|
gem install nutella_framework
|
20
20
|
```
|
@@ -23,19 +23,19 @@ Once the installation is complete you should be able to type `nutella` in your s
|
|
23
23
|
## nutella checkup
|
24
24
|
If you are reading this you probably already saw the warning: "Looks like this is a fresh installation of nutella. Please run 'nutella checkup' to check all dependencies are installed".
|
25
25
|
|
26
|
-
|
26
|
+
nutella is written in ruby but it's designed to run bots and interfaces written in virtually any programming language. All communications among these components are handled by an _MQTT broker_ which needs to be installed (together with its dependencies) before nutella can actually work correctly. Therefore **right after your install nutella** you should run:
|
27
27
|
```
|
28
28
|
nutella checkup
|
29
29
|
```
|
30
30
|
This will install the [Mosca](http://www.mosca.io/) MQTT broker and make sure all the dependencies required by nutella are installed as well.
|
31
31
|
|
32
|
-
Congratulations!
|
32
|
+
Congratulations! nutella is ready to use!
|
33
33
|
|
34
34
|
|
35
35
|
# Where next?
|
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
|
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 how? Check out the [man page for the nutella command line tool](https://github.com/nutella-framework/nutella_framework/wiki).
|
37
37
|
|
38
|
-
If you want to create your own application,
|
38
|
+
If you want to create your own application, hold on tight, a tutorial is coming soon.
|
39
39
|
|
40
40
|
|
41
41
|
# Contributing
|
data/Rakefile
CHANGED
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
|
|
17
17
|
gem.name = "nutella_framework"
|
18
18
|
gem.homepage = "https://github.com/nutella-framework/nutella_framework"
|
19
19
|
gem.license = "MIT"
|
20
|
-
gem.summary = %Q{A framework
|
21
|
-
gem.description = %Q{
|
20
|
+
gem.summary = %Q{A rails-inspired framework for RoomApps}
|
21
|
+
gem.description = %Q{utella is a framework to create and run RoomApps}
|
22
22
|
gem.email = "tebemis@gmail.com"
|
23
23
|
gem.authors = ["Alessandro Gnoli"]
|
24
24
|
# dependencies defined in Gemfile
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
@@ -1,15 +1,51 @@
|
|
1
|
-
|
1
|
+
require_relative '../../nutella_lib/framework_core'
|
2
|
+
|
3
|
+
# Define a couple of utility functions to better deal with the runs list
|
4
|
+
def all_apps( runlist_file )
|
5
|
+
runlist_h = JSON.parse(IO.read(runlist_file))
|
6
|
+
runlist_h.keys
|
7
|
+
end
|
8
|
+
|
9
|
+
def runs_for_app( runlist_file, app_id )
|
10
|
+
runlist_h = JSON.parse(IO.read(runlist_file))
|
11
|
+
# If there is no app with this id, then return false and do nothing
|
12
|
+
return [] if runlist_h[app_id].nil?
|
13
|
+
runs = runlist_h[app_id]['runs']
|
14
|
+
runs.nil? ? [] : runs
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# Parse configuration file and runlist from the command line
|
19
|
+
config_file = ARGV[0]
|
20
|
+
runlist_file = ARGV[1]
|
21
|
+
|
22
|
+
# Try to parse both config file and runlist and terminate if we can't
|
23
|
+
begin
|
24
|
+
config_h = JSON.parse(IO.read(config_file))
|
25
|
+
runlist_h = JSON.parse(IO.read(runlist_file))
|
26
|
+
rescue
|
27
|
+
# something went wrong
|
28
|
+
abort 'Impossible to parse configuration and/or runlist files!'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Initialize this bot as framework component
|
32
|
+
nutella.f.init(config_h['broker'], 'app_runs_list_bot')
|
2
33
|
|
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
34
|
|
7
35
|
# Listen for runs_list requests (done by app components when they connect)
|
8
|
-
nutella.net.
|
9
|
-
|
10
|
-
['run_1', 'run_2', 'run_3'] # Return an array of names!
|
36
|
+
nutella.f.net.handle_requests_on_all_apps('app_runs_list', lambda do |req, app_id, from|
|
37
|
+
runs_for_app(runlist_file, app_id)
|
11
38
|
end)
|
12
39
|
|
13
|
-
# Whenever the list is updated, fire an update to the right app
|
14
40
|
|
15
|
-
|
41
|
+
# Whenever the runs list is updated, fire an updated runlist to all the apps
|
42
|
+
p = JSON.parse(IO.read(runlist_file))
|
43
|
+
while sleep .5
|
44
|
+
n = JSON.parse IO.read runlist_file
|
45
|
+
if p!=n
|
46
|
+
all_apps.each do |app_id, _|
|
47
|
+
nutella.f.net.publish_to_app(app_id, 'app_runs_list', runs_for_app(app_id, runlist_h))
|
48
|
+
end
|
49
|
+
p = n
|
50
|
+
end
|
51
|
+
end
|
data/lib/commands/start.rb
CHANGED
@@ -144,6 +144,7 @@ module Nutella
|
|
144
144
|
return false unless start_app_bots(app_id, app_path)
|
145
145
|
# Start all run-level bots
|
146
146
|
false unless start_run_bots( app_path, app_id, run_id, params )
|
147
|
+
true
|
147
148
|
end
|
148
149
|
|
149
150
|
|
@@ -238,6 +239,8 @@ module Nutella
|
|
238
239
|
command = "#{component_dir}/startup #{nutella_config_file} #{runs_list_file}"
|
239
240
|
pid = fork
|
240
241
|
exec(command) if pid.nil?
|
242
|
+
# Give it a second so they can start properly
|
243
|
+
sleep 1
|
241
244
|
# All went well so we return true
|
242
245
|
true
|
243
246
|
end
|
@@ -13,7 +13,13 @@ module Nutella
|
|
13
13
|
nutella_json_file = "#{cur_app_dir}/nutella.json"
|
14
14
|
# Check that there is a nutella.json file in the main directory of the application
|
15
15
|
if File.exist? nutella_json_file
|
16
|
-
|
16
|
+
begin
|
17
|
+
conf = JSON.parse( IO.read(nutella_json_file) )
|
18
|
+
rescue
|
19
|
+
console.warn 'The nutella.json file for this application does not contain properly formatted JSON'
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
17
23
|
if conf['nutella_version'].nil?
|
18
24
|
return false
|
19
25
|
end
|
data/lib/config/runlist.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'config/persisted_hash'
|
2
|
+
require 'tmux/tmux'
|
2
3
|
|
3
4
|
module Nutella
|
4
5
|
|
@@ -21,9 +22,17 @@ module Nutella
|
|
21
22
|
end
|
22
23
|
|
23
24
|
|
24
|
-
# Returns all the
|
25
|
+
# Returns a list of all the apps in the runlist
|
25
26
|
#
|
26
|
-
# @return [Array<String>]
|
27
|
+
# @return [Array<String>] an array containing the app_ids of all the apps in the runlist
|
28
|
+
def all_apps
|
29
|
+
@ph.to_h.keys
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Returns all the +run_id+s for ALL applications (i.e. the runslist)
|
34
|
+
#
|
35
|
+
# @return [Hash] the run list with all app_ids and run_ids
|
27
36
|
def all_runs
|
28
37
|
@ph.to_h
|
29
38
|
end
|
@@ -31,7 +40,7 @@ module Nutella
|
|
31
40
|
|
32
41
|
# Returns all the +run_id+s for a certain application
|
33
42
|
#
|
34
|
-
# @param [String] app_id
|
43
|
+
# @param [String] app_id of the application we want to find run_ids for
|
35
44
|
# @return [Array<String>] list of +run_id+s associated to the specified app_id
|
36
45
|
def runs_for_app( app_id )
|
37
46
|
# If there is no app, then return false and do nothing
|
data/nutella_framework.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: nutella_framework 0.4.
|
5
|
+
# stub: nutella_framework 0.4.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "nutella_framework"
|
9
|
-
s.version = "0.4.
|
9
|
+
s.version = "0.4.1"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Alessandro Gnoli"]
|
14
|
-
s.date = "2015-03-
|
15
|
-
s.description = "
|
14
|
+
s.date = "2015-03-16"
|
15
|
+
s.description = "utella is a framework to create and run RoomApps"
|
16
16
|
s.email = "tebemis@gmail.com"
|
17
17
|
s.executables = ["nutella"]
|
18
18
|
s.extra_rdoc_files = [
|
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
|
|
39
39
|
"framework_components/main_interface/views/not_found_404.erb",
|
40
40
|
"framework_components/order.json.example",
|
41
41
|
"framework_components/runs_list_bot/app_runs_list_bot.rb",
|
42
|
+
"framework_components/runs_list_bot/startup",
|
42
43
|
"lib/commands/broker.rb",
|
43
44
|
"lib/commands/checkup.rb",
|
44
45
|
"lib/commands/compile.rb",
|
@@ -63,9 +64,10 @@ Gem::Specification.new do |s|
|
|
63
64
|
"lib/logging/nutella_logger.rb",
|
64
65
|
"lib/logging/nutella_logging.rb",
|
65
66
|
"lib/nutella_framework.rb",
|
66
|
-
"lib/nutella_lib_framework/api.rb",
|
67
67
|
"lib/tmux/tmux.rb",
|
68
68
|
"nutella_framework.gemspec",
|
69
|
+
"nutella_lib/framework_core.rb",
|
70
|
+
"nutella_lib/framework_net.rb",
|
69
71
|
"test/commands/test_cmd_cli_params_parsing.rb",
|
70
72
|
"test/commands/test_command_template.rb",
|
71
73
|
"test/config/test_current_app_utils.rb",
|
@@ -78,13 +80,12 @@ Gem::Specification.new do |s|
|
|
78
80
|
s.homepage = "https://github.com/nutella-framework/nutella_framework"
|
79
81
|
s.licenses = ["MIT"]
|
80
82
|
s.rubygems_version = "2.4.3"
|
81
|
-
s.summary = "A framework
|
83
|
+
s.summary = "A rails-inspired framework for RoomApps"
|
82
84
|
|
83
85
|
if s.respond_to? :specification_version then
|
84
86
|
s.specification_version = 4
|
85
87
|
|
86
88
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
87
|
-
s.add_runtime_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
88
89
|
s.add_runtime_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
89
90
|
s.add_runtime_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
90
91
|
s.add_runtime_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
@@ -92,7 +93,7 @@ Gem::Specification.new do |s|
|
|
92
93
|
s.add_runtime_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
93
94
|
s.add_runtime_dependency(%q<nokogiri>, [">= 1.6.3", "~> 1.6.3"])
|
94
95
|
s.add_runtime_dependency(%q<slop>, [">= 4.0.0", "~> 4.0.0"])
|
95
|
-
s.add_runtime_dependency(%q<nutella_lib>, [">= 0.4.
|
96
|
+
s.add_runtime_dependency(%q<nutella_lib>, [">= 0.4.1", "~> 0.4.1"])
|
96
97
|
s.add_development_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
97
98
|
s.add_development_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
98
99
|
s.add_development_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
@@ -100,7 +101,6 @@ Gem::Specification.new do |s|
|
|
100
101
|
s.add_development_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0.1"])
|
101
102
|
s.add_development_dependency(%q<simplecov>, [">= 0", "~> 0"])
|
102
103
|
else
|
103
|
-
s.add_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
104
104
|
s.add_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
105
105
|
s.add_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
106
106
|
s.add_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
@@ -108,7 +108,7 @@ Gem::Specification.new do |s|
|
|
108
108
|
s.add_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
109
109
|
s.add_dependency(%q<nokogiri>, [">= 1.6.3", "~> 1.6.3"])
|
110
110
|
s.add_dependency(%q<slop>, [">= 4.0.0", "~> 4.0.0"])
|
111
|
-
s.add_dependency(%q<nutella_lib>, [">= 0.4.
|
111
|
+
s.add_dependency(%q<nutella_lib>, [">= 0.4.1", "~> 0.4.1"])
|
112
112
|
s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
113
113
|
s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
114
114
|
s.add_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
@@ -117,7 +117,6 @@ Gem::Specification.new do |s|
|
|
117
117
|
s.add_dependency(%q<simplecov>, [">= 0", "~> 0"])
|
118
118
|
end
|
119
119
|
else
|
120
|
-
s.add_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
121
120
|
s.add_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
122
121
|
s.add_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
123
122
|
s.add_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
@@ -125,7 +124,7 @@ Gem::Specification.new do |s|
|
|
125
124
|
s.add_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
126
125
|
s.add_dependency(%q<nokogiri>, [">= 1.6.3", "~> 1.6.3"])
|
127
126
|
s.add_dependency(%q<slop>, [">= 4.0.0", "~> 4.0.0"])
|
128
|
-
s.add_dependency(%q<nutella_lib>, [">= 0.4.
|
127
|
+
s.add_dependency(%q<nutella_lib>, [">= 0.4.1", "~> 0.4.1"])
|
129
128
|
s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
130
129
|
s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
131
130
|
s.add_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'nutella_lib'
|
2
|
+
require 'config/runlist'
|
3
|
+
|
4
|
+
# APIs sub-modules
|
5
|
+
require_relative 'framework_net'
|
6
|
+
|
7
|
+
|
8
|
+
module Nutella
|
9
|
+
|
10
|
+
# Accessor to the framework APIs sub-module
|
11
|
+
def Nutella.f
|
12
|
+
Nutella::Framework
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
# Framework-level APIs sub-module
|
18
|
+
module Framework
|
19
|
+
|
20
|
+
# Initializes this component as a framework component
|
21
|
+
# @param [String] broker_hostname
|
22
|
+
# @param [String] component_id
|
23
|
+
def self.init( broker_hostname, component_id )
|
24
|
+
Nutella.app_id = nil
|
25
|
+
Nutella.run_id = nil
|
26
|
+
Nutella.component_id = component_id
|
27
|
+
Nutella.resource_id = nil
|
28
|
+
Nutella.mqtt = SimpleMQTTClient.new broker_hostname
|
29
|
+
end
|
30
|
+
|
31
|
+
# Accessors for sub-modules
|
32
|
+
def self.net; Nutella::Framework::Net; end
|
33
|
+
def self.log; Nutella::Framework::Log; end
|
34
|
+
|
35
|
+
|
36
|
+
# Utility functions
|
37
|
+
|
38
|
+
|
39
|
+
# Parse command line arguments for framework level components
|
40
|
+
#
|
41
|
+
# @param [Array] args command line arguments array
|
42
|
+
# @return [String] broker
|
43
|
+
def self.parse_args(args)
|
44
|
+
if args.length < 1
|
45
|
+
STDERR.puts 'Couldn\'t read broker address from the command line, impossible to initialize component!'
|
46
|
+
return
|
47
|
+
end
|
48
|
+
return args[0]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Extracts the component name from the folder where the code for this component is located
|
52
|
+
#
|
53
|
+
# @return [String] the component name
|
54
|
+
def self.extract_component_id
|
55
|
+
Nutella.extract_component_id
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sets the resource id
|
59
|
+
#
|
60
|
+
# @param [String] resource_id the resource id (i.e. the particular instance of this component)
|
61
|
+
def self.set_resource_id( resource_id )
|
62
|
+
Nutella.set_resource_id resource_id
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -1,43 +1,8 @@
|
|
1
|
-
require 'nutella_lib'
|
2
|
-
require 'config/runlist'
|
3
|
-
|
4
1
|
module Nutella
|
5
2
|
|
3
|
+
module Framework
|
6
4
|
|
7
|
-
|
8
|
-
# @param [String] broker_hostname
|
9
|
-
# @param [String] component_id
|
10
|
-
def self.init_as_f_component( broker_hostname, component_id )
|
11
|
-
@app_id = nil
|
12
|
-
@run_id = nil
|
13
|
-
@component_id = component_id
|
14
|
-
@resource_id = nil
|
15
|
-
@mqtt = SimpleMQTTClient.new broker_hostname
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
# Parse command line arguments for framework level components
|
20
|
-
#
|
21
|
-
# @param [Array] args command line arguments array
|
22
|
-
# @return [String] broker
|
23
|
-
def self.parse_f_component_args(args)
|
24
|
-
if args.length < 1
|
25
|
-
STDERR.puts 'Couldn\'t read broker address from the command line, impossible to initialize component!'
|
26
|
-
return
|
27
|
-
end
|
28
|
-
return args[0]
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
module Net
|
33
|
-
|
34
|
-
# Provides access to the net.app sub-module
|
35
|
-
def Net.f; Nutella::Net::Framework end
|
36
|
-
|
37
|
-
|
38
|
-
# This module implements the pub/sub and request/response APIs at the framework-level
|
39
|
-
module Framework
|
40
|
-
|
5
|
+
module Net
|
41
6
|
|
42
7
|
# @!group Framework-level communication APIs
|
43
8
|
|
@@ -287,7 +252,7 @@ module Nutella
|
|
287
252
|
# Only handle requests that have proper id set
|
288
253
|
return if type!='request' || id.nil?
|
289
254
|
# Execute callback and send response
|
290
|
-
m = Net.prepare_message_for_response( callback.call( payload, app_id, run_id, from), id )
|
255
|
+
m = Nutella::Net.prepare_message_for_response( callback.call( payload, app_id, run_id, from), id )
|
291
256
|
Nutella.mqtt.publish( mqtt_channel, m )
|
292
257
|
rescue JSON::ParserError
|
293
258
|
# Make sure that request contains JSON, if not drop the message
|
@@ -307,7 +272,83 @@ module Nutella
|
|
307
272
|
|
308
273
|
# @!group Framework-level APIs to communicate at the application-level
|
309
274
|
|
310
|
-
|
275
|
+
|
276
|
+
# Allows framework-level APIs to subscribe to an app-level channel within a specific run
|
277
|
+
#
|
278
|
+
# @param [String] app_id the specific application we are subscribing to
|
279
|
+
# @param [String] channel the run-level channel we are subscribing to. Can be wildcard.
|
280
|
+
# @param [Proc] callback the callback that is fired whenever a message is received on the channel.
|
281
|
+
# The passed callback takes the following parameters:
|
282
|
+
# - [String] message: the received message. Messages that are not JSON are discarded.
|
283
|
+
# - [String] channel: the framework-level channel the message was received on (optional, only for wildcard subscriptions)
|
284
|
+
# - [Hash] from: the sender's identifiers (run_id, app_id, component_id and optionally resource_id)
|
285
|
+
def self.subscribe_to_app(app_id, channel, callback)
|
286
|
+
Nutella::Net.subscribe_to(channel, callback, app_id, nil)
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
# Allows framework-level APIs to unsubscribe from an app-level channel within a specific run
|
291
|
+
#
|
292
|
+
# @param [String] app_id the specific application we are un-subscribing from
|
293
|
+
# @param [String] run_id the specific run we are un-subscribing from
|
294
|
+
# @param [String] channel the run-level channel we want to unsubscribe from. Can contain wildcard(s).
|
295
|
+
def self.unsubscribe_to_app( app_id, channel )
|
296
|
+
Nutella::Net.unsubscribe_to(channel, app_id, nil)
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
# Allows framework-level APIs to publish to an app-level channel within a specific run
|
301
|
+
#
|
302
|
+
# @param [String] app_id the specific application we are publishing to
|
303
|
+
# @param [String] channel the run-level channel we want to publish the message to. *CANNOT* contain wildcard(s)!
|
304
|
+
# @param [String] message the message we are publishing. This can be,
|
305
|
+
# nil/empty (default), a string, a hash and, in general, anything with a .to_json method.
|
306
|
+
def self.publish_to_app(app_id, channel, message)
|
307
|
+
Nutella::Net.publish_to(channel, message, app_id, nil)
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
# Allows framework-level APIs to make a synchronous request to a run-level channel within a specific run
|
312
|
+
#
|
313
|
+
# @param [String] app_id the specific application we are making the request to
|
314
|
+
# @param [String] run_id the specific run we are making the request to
|
315
|
+
# @param [String] channel the channel we want to make the request to. *CANNOT* contain wildcard(s)!
|
316
|
+
# @param [Object] request the body of request. This can be,
|
317
|
+
# nil/empty (default), a string, a hash and, in general, anything with a .to_json method.
|
318
|
+
def self.sync_request_to_app( app_id, channel, request)
|
319
|
+
Nutella::Net.sync_request_to(channel, request, app_id, nil)
|
320
|
+
end
|
321
|
+
|
322
|
+
|
323
|
+
# Allows framework-level APIs to make an asynchronous request to a run-level channel within a specific run
|
324
|
+
#
|
325
|
+
# @param [String] app_id the specific application we are making the request to
|
326
|
+
# @param [String] run_id the specific run we are making the request to
|
327
|
+
# @param [String] channel the channel we want to make the request to. *CANNOT* contain wildcard(s)!
|
328
|
+
# @param [Object] request the body of request. This can be,
|
329
|
+
# nil/empty (default), a string, a hash and, in general, anything with a .to_json method.
|
330
|
+
# @param [Proc] callback the callback that is fired whenever a response is received. It takes one parameter (response).
|
331
|
+
def self.async_request_to_app( app_id, channel, request, callback)
|
332
|
+
Nutella::Net.async_request_to(channel, request, callback, app_id, nil)
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
# Allows framework-level APIs to handle requests on a run-level channel within a specific run
|
337
|
+
#
|
338
|
+
# @param [String] app_id the specific application requests are coming from
|
339
|
+
# @param [String] run_id the specific run requests are coming from
|
340
|
+
# @param [String] channel we want to listen for requests on. Can contain wildcard(s).
|
341
|
+
# @param [Proc] callback a lambda expression that is fired whenever a message is received.
|
342
|
+
# The passed callback takes the following parameters:
|
343
|
+
# - [String] the received message (payload). Messages that are not JSON are discarded.
|
344
|
+
# - [Hash] the sender's identifiers (run_id, app_id, component_id and optionally resource_id)
|
345
|
+
# - [*returns* Hash] The response sent back to the client that performed the request. Whatever is returned by the callback is marshaled into a JSON string and sent via MQTT.
|
346
|
+
def self.handle_requests_on_app(app_id, channel, callback)
|
347
|
+
Nutella::Net.handle_requests_on(channel, callback, app_id, nil)
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
|
311
352
|
|
312
353
|
# @!endgroup
|
313
354
|
|
@@ -315,10 +356,125 @@ module Nutella
|
|
315
356
|
|
316
357
|
# @!group Framework-level APIs to communicate at the application-level (broadcast)
|
317
358
|
|
318
|
-
|
359
|
+
|
360
|
+
# Allows framework-level APIs to subscribe to an app-level channel *for ALL apps*
|
361
|
+
#
|
362
|
+
# @param [String] channel the app-level channel we are subscribing to. Can be wildcard.
|
363
|
+
# @param [Proc] callback the callback that is fired whenever a message is received on the channel.
|
364
|
+
# The passed callback takes the following parameters:
|
365
|
+
# - [String] message: the received message. Messages that are not JSON are discarded.
|
366
|
+
# - [String] app_id: the app_id of the channel the message was sent on
|
367
|
+
# - [Hash] from: the sender's identifiers (run_id, app_id, component_id and optionally resource_id)
|
368
|
+
def self.subscribe_to_all_apps(channel, callback)
|
369
|
+
# Check the passed callback has the right number of arguments
|
370
|
+
raise 'You need to pass a callback with 3 parameters (payload, app_id, from) when subscribing to all apps!' if callback.parameters.length!=3
|
371
|
+
# Pad channel
|
372
|
+
padded_channel = Nutella::Net.pad_channel(channel, '+', nil)
|
373
|
+
mqtt_cb = lambda do |mqtt_message, mqtt_channel|
|
374
|
+
begin
|
375
|
+
type, from, payload, _ = Nutella::Net.extract_fields_from_message mqtt_message
|
376
|
+
app_id = self.extract_app_id mqtt_channel
|
377
|
+
callback.call(payload, app_id, from) if type=='publish'
|
378
|
+
rescue JSON::ParserError
|
379
|
+
# Make sure the message is JSON, if not drop the message
|
380
|
+
return
|
381
|
+
rescue
|
382
|
+
# Check the passed callback has the right number of arguments
|
383
|
+
STDERR.puts "The callback you passed to subscribe has the #{$!}: it needs 'payload', 'app_id' and 'from'"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
# Add to subscriptions, save mqtt callback and subscribe
|
387
|
+
Nutella::Net.subscriptions.push padded_channel
|
388
|
+
Nutella::Net.callbacks.push mqtt_cb
|
389
|
+
Nutella.mqtt.subscribe( padded_channel, mqtt_cb )
|
390
|
+
end
|
391
|
+
|
392
|
+
|
393
|
+
# Allows framework-level APIs to unsubscribe from an app-level channel *for ALL apps*
|
394
|
+
#
|
395
|
+
# @param [String] channel the run-level channel we want to unsubscribe from. Can contain wildcard(s).
|
396
|
+
def self.unsubscribe_from_all_apps( channel )
|
397
|
+
Nutella::Net.unsubscribe_to(channel, '+', nil)
|
398
|
+
end
|
399
|
+
|
400
|
+
|
401
|
+
# Allows framework-level APIs to publish a message to an app-level channel *for ALL apps*
|
402
|
+
#
|
403
|
+
# @param [String] channel the app-level channel we want to publish the message to. *CANNOT* contain wildcard(s)!
|
404
|
+
# @param [Object] message the message we are publishing. This can be,
|
405
|
+
# nil/empty (default), a string, a hash and, in general, anything with a .to_json method.
|
406
|
+
def self.publish_to_all_apps(channel, message)
|
407
|
+
Nutella.runlist.all_runs.each do |app_id, _|
|
408
|
+
Nutella::Net.publish_to(channel, message, app_id, nil)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
# Allows framework-level APIs to send a request to a run-level channel *for ALL runs*
|
414
|
+
#
|
415
|
+
# @param [String] channel the app-level channel we want to make the request to. *CANNOT* contain wildcard(s)!
|
416
|
+
# @param [Object] request the body of request. This can be,
|
417
|
+
# nil/empty (default), a string, a hash and, in general, anything with a .to_json method.
|
418
|
+
# @param [Proc] callback the callback that is fired whenever a response is received. It takes one parameter (response).
|
419
|
+
def self.async_request_to_all_apps(channel, request, callback)
|
420
|
+
Nutella.runlist.all_runs.each do |app_id, _|
|
421
|
+
Nutella::Net.async_request_to(channel, request, callback, app_id, nil)
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
|
426
|
+
# Allows framework-level APIs to handle requests to a run-level channel *for ALL runs*
|
427
|
+
#
|
428
|
+
# @param [String] channel tha app-level channel we want to listen for requests on. Can contain wildcard(s).
|
429
|
+
# @param [Proc] callback a lambda expression that is fired whenever a message is received.
|
430
|
+
# The passed callback takes the following parameters:
|
431
|
+
# - [String] the received message (request). Messages that are not JSON are discarded.
|
432
|
+
# - [String] app_id: the app_id of the channel the request was sent on
|
433
|
+
# - [Hash] the sender's identifiers (from containing, run_id, app_id, component_id and optionally resource_id)
|
434
|
+
# - [*returns* Hash] The response sent back to the client that performed the request. Whatever is returned by the callback is marshaled into a JSON string and sent via MQTT.
|
435
|
+
def self.handle_requests_on_all_apps(channel, callback)
|
436
|
+
# Check the passed callback has the right number of arguments
|
437
|
+
raise 'You need to pass a callback with 3 parameters (request, run_id, from) when handling requests!' if callback.parameters.length!=3
|
438
|
+
# Pad channel
|
439
|
+
padded_channel = Nutella::Net.pad_channel(channel, '+', nil)
|
440
|
+
mqtt_cb = lambda do |request, mqtt_channel|
|
441
|
+
begin
|
442
|
+
# Extract nutella fields
|
443
|
+
type, from, payload, id = Nutella::Net.extract_fields_from_message request
|
444
|
+
app_id = self.extract_app_id mqtt_channel
|
445
|
+
# Only handle requests that have proper id set
|
446
|
+
return if type!='request' || id.nil?
|
447
|
+
# Execute callback and send response
|
448
|
+
m = Nutella::Net.prepare_message_for_response( callback.call( payload, app_id, from), id )
|
449
|
+
Nutella.mqtt.publish( mqtt_channel, m )
|
450
|
+
rescue JSON::ParserError
|
451
|
+
# Make sure that request contains JSON, if not drop the message
|
452
|
+
return
|
453
|
+
rescue
|
454
|
+
# Check the passed callback has the right number of arguments
|
455
|
+
STDERR.puts "The callback you passed to subscribe has the #{$!}: it needs 'request', 'app_id' and 'from'"
|
456
|
+
end
|
457
|
+
end
|
458
|
+
# Subscribe to the channel
|
459
|
+
Nutella.mqtt.subscribe( padded_channel, mqtt_cb )
|
460
|
+
end
|
319
461
|
|
320
462
|
# @!endgroup
|
321
463
|
|
464
|
+
# ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
465
|
+
|
466
|
+
# Listens for incoming messages. All this function
|
467
|
+
# does is to put the thread to sleep and wait for something to
|
468
|
+
# happen over the network to wake up.
|
469
|
+
def self.listen
|
470
|
+
begin
|
471
|
+
sleep
|
472
|
+
rescue Interrupt
|
473
|
+
# Simply returns once interrupted
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
|
322
478
|
private
|
323
479
|
|
324
480
|
def self.extract_run_id_and_app_id( mqtt_channel )
|
@@ -327,7 +483,13 @@ module Nutella
|
|
327
483
|
end
|
328
484
|
|
329
485
|
|
330
|
-
|
486
|
+
def self.extract_app_id( mqtt_channel )
|
487
|
+
sp = mqtt_channel.sub('/nutella/apps/', '').split('/')
|
488
|
+
return sp[0]
|
489
|
+
end
|
490
|
+
|
491
|
+
end # net
|
492
|
+
|
493
|
+
end # framework
|
331
494
|
|
332
|
-
|
333
|
-
end
|
495
|
+
end # nutella
|
metadata
CHANGED
@@ -1,35 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nutella_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Gnoli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: ansi
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.4.3
|
20
|
-
- - "~>"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '1.4'
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.4.3
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '1.4'
|
33
13
|
- !ruby/object:Gem::Dependency
|
34
14
|
name: semantic
|
35
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,20 +156,20 @@ dependencies:
|
|
176
156
|
requirements:
|
177
157
|
- - ">="
|
178
158
|
- !ruby/object:Gem::Version
|
179
|
-
version: 0.4.
|
159
|
+
version: 0.4.1
|
180
160
|
- - "~>"
|
181
161
|
- !ruby/object:Gem::Version
|
182
|
-
version: 0.4.
|
162
|
+
version: 0.4.1
|
183
163
|
type: :runtime
|
184
164
|
prerelease: false
|
185
165
|
version_requirements: !ruby/object:Gem::Requirement
|
186
166
|
requirements:
|
187
167
|
- - ">="
|
188
168
|
- !ruby/object:Gem::Version
|
189
|
-
version: 0.4.
|
169
|
+
version: 0.4.1
|
190
170
|
- - "~>"
|
191
171
|
- !ruby/object:Gem::Version
|
192
|
-
version: 0.4.
|
172
|
+
version: 0.4.1
|
193
173
|
- !ruby/object:Gem::Dependency
|
194
174
|
name: shoulda
|
195
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -310,7 +290,7 @@ dependencies:
|
|
310
290
|
- - "~>"
|
311
291
|
- !ruby/object:Gem::Version
|
312
292
|
version: '0'
|
313
|
-
description:
|
293
|
+
description: utella is a framework to create and run RoomApps
|
314
294
|
email: tebemis@gmail.com
|
315
295
|
executables:
|
316
296
|
- nutella
|
@@ -338,6 +318,7 @@ files:
|
|
338
318
|
- framework_components/main_interface/views/not_found_404.erb
|
339
319
|
- framework_components/order.json.example
|
340
320
|
- framework_components/runs_list_bot/app_runs_list_bot.rb
|
321
|
+
- framework_components/runs_list_bot/startup
|
341
322
|
- lib/commands/broker.rb
|
342
323
|
- lib/commands/checkup.rb
|
343
324
|
- lib/commands/compile.rb
|
@@ -362,9 +343,10 @@ files:
|
|
362
343
|
- lib/logging/nutella_logger.rb
|
363
344
|
- lib/logging/nutella_logging.rb
|
364
345
|
- lib/nutella_framework.rb
|
365
|
-
- lib/nutella_lib_framework/api.rb
|
366
346
|
- lib/tmux/tmux.rb
|
367
347
|
- nutella_framework.gemspec
|
348
|
+
- nutella_lib/framework_core.rb
|
349
|
+
- nutella_lib/framework_net.rb
|
368
350
|
- test/commands/test_cmd_cli_params_parsing.rb
|
369
351
|
- test/commands/test_command_template.rb
|
370
352
|
- test/config/test_current_app_utils.rb
|
@@ -396,5 +378,5 @@ rubyforge_project:
|
|
396
378
|
rubygems_version: 2.4.3
|
397
379
|
signing_key:
|
398
380
|
specification_version: 4
|
399
|
-
summary: A framework
|
381
|
+
summary: A rails-inspired framework for RoomApps
|
400
382
|
test_files: []
|