nutella_framework 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.document +5 -0
- data/Gemfile +5 -0
- data/README.md +41 -5
- data/Rakefile +3 -10
- data/VERSION +1 -1
- data/lib/config/config.rb +1 -0
- data/lib/config/runlist.rb +20 -12
- data/lib/core/commands/checkup.rb +10 -1
- data/lib/core/commands/install.rb +77 -71
- data/lib/core/commands/runs.rb +41 -22
- data/lib/core/commands/start.rb +90 -34
- data/lib/core/commands/stop.rb +37 -29
- data/lib/core/tmux.rb +19 -5
- data/lib/extra/config.ru +2 -0
- data/lib/extra/interfaces_list.erubis +14 -0
- data/lib/extra/main_interface.rb +9 -0
- data/nutella_framework.gemspec +114 -0
- data/test/config/test_project.rb +1 -0
- data/test/test_nutella_framework.rb +19 -18
- metadata +108 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b06d936ef60bf41dac3eb872609ba9906a50cecd
|
4
|
+
data.tar.gz: e7a51bdbff02a0fa306eaf5267f80168c3563e30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23c35cb1768d1469bd29bd27b3eb4b8686c911082ec233556e9526188b544beee945bc2ff8005f588d64f0ed25f97fb41a4e3bafbd8b8c2be22a71f97003f67b
|
7
|
+
data.tar.gz: 23aa14c916de0d105faf807bf548ea9f6c1249868609a80756d4ba7a53b578a77f330c08080408a6bda34eaccaf920a8687514a052462ea5d8cd593ddaa351a6
|
data/.document
ADDED
data/Gemfile
CHANGED
@@ -3,9 +3,14 @@ source "http://rubygems.org"
|
|
3
3
|
gem 'ansi', '~> 1.4', '>= 1.4.3'
|
4
4
|
gem 'semantic', '~> 1.3', '>=1.3'
|
5
5
|
gem 'logging', '~> 1.8', '>=1.8.2'
|
6
|
+
gem 'git', '~> 1.2', '>=1.2.8'
|
7
|
+
gem 'thin', '~> 1.6.3', '>= 1.6.3'
|
8
|
+
gem 'sinatra', '~>1.4.5', '>=1.4.5'
|
9
|
+
gem 'erubis', '~>2.7.0', '>=2.7.0'
|
6
10
|
|
7
11
|
group :development do
|
8
12
|
gem 'shoulda', '~> 3', '>= 3'
|
13
|
+
gem "yard", '~> 0.8', '>= 0.8.7'
|
9
14
|
gem 'rdoc', '~> 4.0', '>= 4.0'
|
10
15
|
gem 'bundler', '~> 1.0', '>= 1.0'
|
11
16
|
gem 'jeweler', '~> 2.0.1', '>= 2.0.1'
|
data/README.md
CHANGED
@@ -1,11 +1,47 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
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)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/nutella-framework/nutella_framework/badges/gpa.svg)](https://codeclimate.com/github/nutella-framework/nutella_framework)
|
6
|
+
|
7
|
+
# Nutella
|
8
|
+
Nutella is a framework to build and run "Internet of Things"-like learning applications. It's still _very_ under development so keep an eye on new versions and help fix the bugs you find by [submitting issues](https://waffle.io/nutella-framework/nutella_framework). Nutella's goal is to be for the "Internet of Things" what Ruby on Rails has been for web applications. Ambitious? You bet, but where is the fun if the challenge is trivial?
|
9
|
+
|
10
|
+
# Installing
|
11
|
+
Nutella is a ruby gem so to install it we do:
|
12
|
+
```
|
13
|
+
gem install nutella_framework
|
14
|
+
```
|
15
|
+
If all goes as expected you should be able to type `nutella` in your shell and get a welcome message (yay!) together with a warnining (booooo!). Let's see why...
|
16
|
+
|
17
|
+
Nutella is written in ruby but is designed to run bots and interfaces written in virtually any programming language. All communications among these components are routed through 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:
|
18
|
+
```
|
19
|
+
nutella checkup
|
20
|
+
```
|
21
|
+
in order to make sure all the dependencies have been correctly installed.
|
22
|
+
|
4
23
|
|
5
24
|
# Hello world
|
6
|
-
|
7
|
-
|
25
|
+
So what does nutella do for me? Suppose we want to create a new application called "crepe" (because I like nutella crêpes). Let's do that:
|
26
|
+
```
|
27
|
+
nutella new crepe
|
28
|
+
```
|
29
|
+
Nutella will create the basic project structure in a directory called `crepe`. Now that we have created a basic project, we can
|
30
|
+
```
|
31
|
+
cd crepe
|
32
|
+
```
|
33
|
+
and start our new project by doing
|
34
|
+
```
|
35
|
+
nutella start
|
36
|
+
```
|
37
|
+
Pretty boring isn't it? Nothing is happeninig! Why? Well, because the project we just created is simply an empty shell. Let's spice things up a bit and throw some cinnamon into this crêpe!
|
38
|
+
|
39
|
+
## Templates
|
40
|
+
What are templates? Templates are simply [boilerplate code](http://en.wikipedia.org/wiki/Boilerplate_code) that you don't have to write. Templates are there to simplify your life. Let's see how. Our new application is a ...
|
41
|
+
**This tutorial is a work in progress**
|
42
|
+
|
8
43
|
|
44
|
+
For a complete guide on how to use Nutella, please refer to [this wiki](https://github.com/nutella-framework/nutella_framework/wiki).
|
9
45
|
|
10
46
|
# Building & contributing
|
11
|
-
Clone the repo,
|
47
|
+
Clone the repo, `bundle install` to take care of the dependencies and then `rake` to run all the tests. If you want to perform some fancier task simply type `rake -T` for a list of awesomeness.
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ require 'jeweler'
|
|
15
15
|
Jeweler::Tasks.new do |gem|
|
16
16
|
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
17
17
|
gem.name = "nutella_framework"
|
18
|
-
gem.homepage = "https://github.com/
|
18
|
+
gem.homepage = "https://github.com/nutella-framework/nutella_framework"
|
19
19
|
gem.license = "MIT"
|
20
20
|
gem.summary = %Q{IoT-like learning applications framework}
|
21
21
|
gem.description = %Q{Nutella is a framework to build and run "Internet of Things"-like learning applications}
|
@@ -40,12 +40,5 @@ end
|
|
40
40
|
|
41
41
|
task :default => :test
|
42
42
|
|
43
|
-
require '
|
44
|
-
Rake::
|
45
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
46
|
-
|
47
|
-
rdoc.rdoc_dir = 'rdoc'
|
48
|
-
rdoc.title = "nutella_framework #{version}"
|
49
|
-
rdoc.rdoc_files.include('README*')
|
50
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
-
end
|
43
|
+
require 'yard'
|
44
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/config/config.rb
CHANGED
data/lib/config/runlist.rb
CHANGED
@@ -19,12 +19,7 @@ module Nutella
|
|
19
19
|
# No file, create one
|
20
20
|
result = [runid].to_set
|
21
21
|
end
|
22
|
-
|
23
|
-
File.open(RUN_LIST_FILE, "w+") do |f|
|
24
|
-
f.write(JSON.pretty_generate(result.to_a))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
result
|
22
|
+
writeFile(result)
|
28
23
|
end
|
29
24
|
|
30
25
|
def delete?(runid)
|
@@ -34,12 +29,7 @@ module Nutella
|
|
34
29
|
removeRunListFile
|
35
30
|
result = nil # List is empty, so nil
|
36
31
|
end
|
37
|
-
|
38
|
-
File.open(RUN_LIST_FILE, "w+") do |f|
|
39
|
-
f.write(JSON.pretty_generate(result.to_a))
|
40
|
-
end
|
41
|
-
end
|
42
|
-
result
|
32
|
+
writeFile(result)
|
43
33
|
end
|
44
34
|
|
45
35
|
def include?(runid)
|
@@ -71,6 +61,14 @@ module Nutella
|
|
71
61
|
Array.new # There is no file or something went wrong
|
72
62
|
end
|
73
63
|
end
|
64
|
+
|
65
|
+
def length
|
66
|
+
to_a.length
|
67
|
+
end
|
68
|
+
|
69
|
+
def extractRunId(run)
|
70
|
+
run.to_s.empty? ? Nutella.currentProject.config["name"] : Nutella.currentProject.config["name"] + "_" + run
|
71
|
+
end
|
74
72
|
|
75
73
|
private
|
76
74
|
|
@@ -78,6 +76,16 @@ module Nutella
|
|
78
76
|
File.delete(RUN_LIST_FILE) if File.exist?(RUN_LIST_FILE)
|
79
77
|
end
|
80
78
|
|
79
|
+
def writeFile(result)
|
80
|
+
if result!=nil
|
81
|
+
File.open(RUN_LIST_FILE, "w+") do |f|
|
82
|
+
f.write(JSON.pretty_generate(result.to_a))
|
83
|
+
end
|
84
|
+
File.chmod(0777, RUN_LIST_FILE)
|
85
|
+
end
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
81
89
|
end
|
82
90
|
|
83
91
|
|
@@ -46,6 +46,7 @@ module Nutella
|
|
46
46
|
return out1 && out2
|
47
47
|
end
|
48
48
|
|
49
|
+
|
49
50
|
def allDependenciesInstalled?
|
50
51
|
# Node version lambda
|
51
52
|
node_semver = lambda do
|
@@ -59,8 +60,16 @@ module Nutella
|
|
59
60
|
out.slice!(0,12)
|
60
61
|
Semantic::Version.new out[0..4]
|
61
62
|
end
|
63
|
+
# Tmux version lambda
|
64
|
+
tmux_semver = lambda do
|
65
|
+
out = `tmux -V`
|
66
|
+
out.slice!(0,5)
|
67
|
+
Semantic::Version.new "#{out[0..2]}.0"
|
68
|
+
end
|
62
69
|
# Check versions
|
63
|
-
if checkVersion?("node", "0.10.0", node_semver)
|
70
|
+
if checkVersion?("node", "0.10.0", node_semver) \
|
71
|
+
and checkVersion?("git", "1.8.0", git_semver) \
|
72
|
+
and checkVersion?("tmux", "1.8.0", tmux_semver)
|
64
73
|
return true
|
65
74
|
end
|
66
75
|
false
|
@@ -6,36 +6,32 @@ require 'net/http'
|
|
6
6
|
module Nutella
|
7
7
|
|
8
8
|
class Install < Command
|
9
|
-
@description =
|
9
|
+
@description = 'Copies an arbitrary template (from central DB, directory or URL) into the current project'
|
10
10
|
|
11
11
|
def run(args=nil)
|
12
12
|
# Is current directory a nutella prj?
|
13
|
-
|
14
|
-
return
|
15
|
-
end
|
13
|
+
return unless Nutella.currentProject.exist?
|
16
14
|
|
17
15
|
# Check args
|
18
16
|
if args.empty?
|
19
|
-
console.warn
|
17
|
+
console.warn 'You need to specify a template name, directory or URL'
|
20
18
|
return
|
21
19
|
end
|
22
|
-
|
23
|
-
|
24
|
-
@destinationFolder = args[1]
|
25
|
-
end
|
20
|
+
template = args[0]
|
21
|
+
destination_dir = args.length==2 ? args[1] : nil
|
26
22
|
|
27
23
|
# Extract project directory
|
28
|
-
|
29
|
-
|
24
|
+
prj_dir = Nutella.currentProject.dir
|
25
|
+
|
30
26
|
# What kind of template are we handling?
|
31
|
-
if
|
32
|
-
|
33
|
-
elsif
|
34
|
-
|
35
|
-
elsif
|
36
|
-
|
27
|
+
if is_template_a_local_dir? template
|
28
|
+
add_local_template( template, template, prj_dir, destination_dir )
|
29
|
+
elsif is_template_a_git_repo? template
|
30
|
+
add_remote_template( template, prj_dir, destination_dir)
|
31
|
+
elsif is_template_in_db? template
|
32
|
+
add_central_template( template, prj_dir, destination_dir)
|
37
33
|
else
|
38
|
-
console.warn
|
34
|
+
console.warn 'The specified template is not a valid nutella template'
|
39
35
|
end
|
40
36
|
|
41
37
|
end
|
@@ -44,107 +40,117 @@ module Nutella
|
|
44
40
|
private
|
45
41
|
|
46
42
|
|
47
|
-
def
|
43
|
+
def is_template_a_local_dir?( template_path )
|
48
44
|
# Does the specified directory exist?
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
return validateTemplate @template
|
45
|
+
return false unless File.directory? template_path
|
46
|
+
validate_template template_path
|
53
47
|
end
|
54
48
|
|
55
49
|
|
56
|
-
def
|
50
|
+
def is_template_a_git_repo?( template_git_url )
|
57
51
|
begin
|
58
|
-
|
59
|
-
|
60
|
-
return
|
52
|
+
tmp_dest_dir = template_git_url[template_git_url.rindex('/')+1 .. template_git_url.length-5]
|
53
|
+
clone_template_from_repo_to( template_git_url, tmp_dest_dir )
|
54
|
+
return validate_template "#{Nutella.config['tmp_dir']}/#{tmp_dest_dir}"
|
61
55
|
rescue
|
62
56
|
return false
|
63
57
|
end
|
64
|
-
false
|
65
58
|
end
|
66
59
|
|
67
60
|
|
68
|
-
def
|
69
|
-
uri = URI.parse("https://raw.githubusercontent.com/ltg-uic/nutella/templates-database/" + @template + ".json")
|
61
|
+
def is_template_in_db?( template_name )
|
70
62
|
begin
|
71
|
-
|
72
|
-
|
73
|
-
@template = nutella_json["repo"]
|
74
|
-
return isTemplateAGitRepo?
|
75
|
-
end
|
63
|
+
repo = extract_remote_repo_url template_name
|
64
|
+
return is_template_a_git_repo? repo
|
76
65
|
rescue
|
77
66
|
return false
|
78
67
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
68
|
+
end
|
69
|
+
|
82
70
|
|
83
|
-
def
|
84
|
-
|
71
|
+
def add_local_template ( template, template_dir, prj_dir, dest_dir_name)
|
72
|
+
template_nutella_file_json = JSON.parse(IO.read("#{template_dir}/nutella.json"))
|
85
73
|
|
86
74
|
# If destination is not specified, set it to the template name
|
87
|
-
if
|
88
|
-
|
75
|
+
if dest_dir_name.nil?
|
76
|
+
dest_dir_name = template_nutella_file_json['name']
|
89
77
|
end
|
90
|
-
|
91
78
|
# Am I trying to copy onto a template that already exists?
|
92
|
-
if
|
79
|
+
if template_nutella_file_json['type']=='bot'
|
93
80
|
# Look into bots folder
|
94
|
-
dest_dir = "#{
|
81
|
+
dest_dir = "#{prj_dir}/bots/#{dest_dir_name}"
|
95
82
|
else
|
96
83
|
# Look into interfaces folder
|
97
|
-
dest_dir = "#{
|
84
|
+
dest_dir = "#{prj_dir}/interfaces/#{dest_dir_name}"
|
98
85
|
end
|
99
86
|
if File.directory?(dest_dir)
|
100
|
-
console.error("
|
87
|
+
console.error("Destination folder #{dest_dir} already exists! Can't add template #{template}")
|
101
88
|
return
|
102
89
|
end
|
103
|
-
|
104
|
-
|
90
|
+
|
91
|
+
# If all is good, copy the template to dest_dir...
|
92
|
+
FileUtils.copy_entry template_dir, dest_dir
|
93
|
+
|
94
|
+
# ... and remove nutella.json, .git folder and .gitignore file if they exist
|
95
|
+
File.delete "#{dest_dir}/nutella.json" if File.exist? "#{dest_dir}/nutella.json"
|
96
|
+
FileUtils.rm_rf "#{dest_dir}/.git"
|
97
|
+
File.delete "#{dest_dir}/.gitignore" if File.exist? "#{dest_dir}/.gitignore"
|
98
|
+
|
99
|
+
# Make the user feel happy and accomplished! :)
|
100
|
+
console.success("Installed template: #{template} as #{dest_dir_name}")
|
105
101
|
end
|
106
102
|
|
107
103
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
104
|
+
def add_remote_template ( template, prj_dir, dest_dir)
|
105
|
+
template_name = template[template.rindex('/')+1 .. template.length-5]
|
106
|
+
template_dir = "#{Nutella.config['tmp_dir']}/#{template_name}"
|
107
|
+
add_local_template( template, template_dir, prj_dir, dest_dir )
|
111
108
|
end
|
112
109
|
|
113
110
|
|
114
|
-
def
|
115
|
-
|
111
|
+
def add_central_template( template_name, prj_dir, dest_dir)
|
112
|
+
template_dir = "#{Nutella.config['tmp_dir']}/#{template_name}"
|
113
|
+
add_local_template( template_name, template_dir, prj_dir, dest_dir )
|
116
114
|
end
|
117
115
|
|
118
116
|
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
124
|
-
Git.clone(@template, dest_dir, :path => Nutella.config["tmp_dir"])
|
117
|
+
def clone_template_from_repo_to(template, dest_dir)
|
118
|
+
clean_tmp_dir
|
119
|
+
Dir.mkdir Nutella.config['tmp_dir'] unless Dir.exists? Nutella.config['tmp_dir']
|
120
|
+
Git.clone(template, dest_dir, :path => Nutella.config['tmp_dir'])
|
125
121
|
end
|
126
122
|
|
127
123
|
|
128
|
-
def
|
124
|
+
def validate_template( dir )
|
129
125
|
# Parse the template's nutella.json file
|
130
126
|
begin
|
131
|
-
|
127
|
+
template_nutella_file_json = JSON.parse(IO.read("#{dir}/nutella.json"))
|
132
128
|
rescue
|
133
129
|
return false
|
134
130
|
end
|
135
|
-
# If template is a bot, perform
|
136
|
-
if
|
137
|
-
# Is there a
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
131
|
+
# If template is a bot, perform the appropriate checks
|
132
|
+
if template_nutella_file_json['type']=='bot'
|
133
|
+
# Is there a mandatory 'startup' script and is it executable
|
134
|
+
return false unless File.executable? "#{dir}/startup"
|
135
|
+
end
|
136
|
+
# If template is an interface, perform the appropriate checks
|
137
|
+
if template_nutella_file_json['type']=='interface'
|
138
|
+
# Is there the mandatory index.html file
|
139
|
+
return false unless File.exist? "#{dir}/index.html"
|
140
|
+
end
|
142
141
|
true
|
143
142
|
end
|
143
|
+
|
144
|
+
|
145
|
+
def extract_remote_repo_url( template_name )
|
146
|
+
uri = URI.parse "https://raw.githubusercontent.com/nutella-framework/nutella_framework/templates-database/#{template_name}.json"
|
147
|
+
nutella_json = JSON.parse Net::HTTP.get uri
|
148
|
+
nutella_json['repo']
|
149
|
+
end
|
144
150
|
|
145
151
|
|
146
|
-
def
|
147
|
-
FileUtils.rm_rf Nutella.config[
|
152
|
+
def clean_tmp_dir
|
153
|
+
FileUtils.rm_rf "#{Nutella.config['tmp_dir']}"
|
148
154
|
end
|
149
155
|
|
150
156
|
end
|
data/lib/core/commands/runs.rb
CHANGED
@@ -8,35 +8,54 @@ module Nutella
|
|
8
8
|
def run(args=nil)
|
9
9
|
# If invoked with "--all" it will show all the runs under this instance of nutella
|
10
10
|
if args[0]=="--all"
|
11
|
-
|
12
|
-
|
13
|
-
else
|
14
|
-
console.info "Currently running:"
|
15
|
-
Nutella.runlist.to_a.each { |run| console.info " #{run}" }
|
16
|
-
end
|
17
|
-
else # Just show the runs associated with this project
|
11
|
+
displayGlobalRuns
|
12
|
+
else
|
18
13
|
# Is current directory a nutella prj?
|
19
14
|
if !Nutella.currentProject.exist?
|
20
15
|
return
|
21
16
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
displayProjectRuns
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
|
25
|
+
def displayGlobalRuns
|
26
|
+
if Nutella.runlist.empty?
|
27
|
+
console.info "You are not running any projects"
|
28
|
+
else
|
29
|
+
console.info "Currently running:"
|
30
|
+
Nutella.runlist.to_a.each { |run| console.info " #{run}" }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def displayProjectRuns
|
36
|
+
project_name = Nutella.currentProject.config["name"]
|
37
|
+
runs = Nutella.runlist.to_a project_name
|
38
|
+
if runs.empty?
|
39
|
+
console.info "Currently running #{runs.length} instances of project #{project_name}"
|
40
|
+
return
|
41
|
+
end
|
42
|
+
printProjectRuns(project_name, runs)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def printProjectRuns(project_name, runs)
|
47
|
+
console.info "Currently running #{runs.length} instances of project #{project_name}:"
|
48
|
+
runs.to_a.each do |run|
|
49
|
+
run.slice! "#{project_name}_"
|
50
|
+
if run.empty?
|
51
|
+
console.info "progetto (default)"
|
52
|
+
else
|
53
|
+
console.info " #{run}"
|
27
54
|
end
|
28
|
-
console.info "Currently running #{runs.length} instances of project #{project_name}:"
|
29
|
-
runs.to_a.each { |run|
|
30
|
-
run.slice! "#{project_name}_"
|
31
|
-
if run.empty?
|
32
|
-
console.info "progetto (default)"
|
33
|
-
else
|
34
|
-
console.info " #{run}"
|
35
|
-
end
|
36
|
-
}
|
37
55
|
end
|
38
56
|
end
|
57
|
+
|
58
|
+
|
39
59
|
end
|
40
|
-
|
41
60
|
end
|
42
61
|
|
data/lib/core/commands/start.rb
CHANGED
@@ -3,57 +3,47 @@ require 'core/tmux'
|
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class Start < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Starts all or some of the bots in the current project'
|
7
7
|
|
8
8
|
def run(args=nil)
|
9
9
|
# Is current directory a nutella prj?
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# Extract runid
|
15
|
-
runid = args[0].to_s.empty? ? Nutella.currentProject.config["name"] : Nutella.currentProject.config["name"] + "_" + args[0]
|
16
|
-
|
17
|
-
# Add to the list of runs and check the runId is unique
|
18
|
-
if !Nutella.runlist.add?(runid)
|
19
|
-
console.error "Impossible to start project: an instance of this project with the same name is already running!"
|
20
|
-
console.error "You might want to kill it with 'nutella stop "+ runid + "'"
|
21
|
-
return;
|
22
|
-
end
|
23
|
-
|
10
|
+
return unless Nutella.currentProject.exist?
|
11
|
+
run_id = Nutella.runlist.extractRunId args[0]
|
12
|
+
# Check the runId is unique and add to the list of runs
|
13
|
+
return unless addToRunsList run_id
|
24
14
|
# Extract project directory
|
25
15
|
@prj_dir = Nutella.currentProject.dir
|
26
|
-
|
27
16
|
# If running on internal broker, start it
|
28
|
-
if Nutella.config[
|
17
|
+
if Nutella.config['broker'] == 'localhost' # Are we using the internal broker
|
29
18
|
startBroker
|
30
19
|
end
|
31
|
-
|
32
20
|
# Create .botsconfig file
|
33
21
|
deleteBotsConfig
|
34
22
|
createBotsConfig
|
35
|
-
|
36
|
-
|
37
23
|
# Start all the bots
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
24
|
+
installBotsDependencies(run_id)
|
25
|
+
compileBots(run_id)
|
26
|
+
startBots(run_id)
|
27
|
+
# Start all interfaces
|
28
|
+
ports = start_interfaces
|
29
|
+
# Start all "hidden bots"
|
30
|
+
start_hidden_bots
|
47
31
|
# Output success message
|
48
|
-
|
49
|
-
console.success "Project " + Nutella.currentProject.config["name"] + " started"
|
50
|
-
else
|
51
|
-
console.success "Project " + Nutella.currentProject.config["name"] + ", run " + args[0] + " started"
|
52
|
-
end
|
32
|
+
outputSuccessMessage(run_id, args[0])
|
53
33
|
end
|
54
34
|
|
55
35
|
|
56
36
|
private
|
37
|
+
|
38
|
+
|
39
|
+
def addToRunsList(runid)
|
40
|
+
if !Nutella.runlist.add?(runid)
|
41
|
+
console.error 'Impossible to start project: an instance of this project with the same name is already running!'
|
42
|
+
console.error "You might want to kill it with 'nutella stop "+ runid + "'"
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
return true
|
46
|
+
end
|
57
47
|
|
58
48
|
|
59
49
|
def startBroker
|
@@ -94,6 +84,72 @@ module Nutella
|
|
94
84
|
File.delete("#{@prj_dir}/.botsconfig.json") if File.exist?("#{@prj_dir}/.botsconfig.json")
|
95
85
|
end
|
96
86
|
|
87
|
+
def installBotsDependencies(runid)
|
88
|
+
Dir.entries("#{@prj_dir}/bots").select {|entry| File.directory?(File.join("#{@prj_dir}/bots",entry)) and !(entry =='.' || entry == '..') }.each do |bot|
|
89
|
+
if !File.exist?("#{@prj_dir}/bots/#{bot}/dependencies")
|
90
|
+
next
|
91
|
+
end
|
92
|
+
console.info "Installing dependencies for bot #{bot}."
|
93
|
+
cur_dir = Dir.pwd
|
94
|
+
Dir.chdir "#{@prj_dir}/bots/#{bot}"
|
95
|
+
system "./dependencies"
|
96
|
+
Dir.chdir cur_dir
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def compileBots(runid)
|
101
|
+
Dir.entries("#{@prj_dir}/bots").select {|entry| File.directory?(File.join("#{@prj_dir}/bots",entry)) and !(entry =='.' || entry == '..') }.each do |bot|
|
102
|
+
if !File.exist?("#{@prj_dir}/bots/#{bot}/compile")
|
103
|
+
next
|
104
|
+
end
|
105
|
+
console.info "Compiling bot #{bot}."
|
106
|
+
cur_dir = Dir.pwd
|
107
|
+
Dir.chdir "#{@prj_dir}/bots/#{bot}"
|
108
|
+
system "./compile"
|
109
|
+
Dir.chdir cur_dir
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def startBots(runid)
|
114
|
+
@tmux = Tmux.new(runid)
|
115
|
+
Dir.entries("#{@prj_dir}/bots").select {|entry| File.directory?(File.join("#{@prj_dir}/bots",entry)) and !(entry =='.' || entry == '..') }.each do |bot|
|
116
|
+
if !File.exist?("#{@prj_dir}/bots/#{bot}/startup")
|
117
|
+
console.warn "Impossible to start bot #{bot}. Couldn't locate 'startup' script."
|
118
|
+
next
|
119
|
+
end
|
120
|
+
@tmux.new_bot_window(bot)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def start_interfaces
|
125
|
+
ports = Hash.new
|
126
|
+
Dir.entries("#{@prj_dir}/interfaces").select {|entry| File.directory?(File.join("#{@prj_dir}/interfaces",entry)) and !(entry =='.' || entry == '..') }.each do |iface|
|
127
|
+
if !File.exist?("#{@prj_dir}/interfaces/#{iface}/index.html")
|
128
|
+
console.warn "Impossible to start interface #{iface}. Couldn't locate 'index.html' file."
|
129
|
+
next
|
130
|
+
end
|
131
|
+
ports[iface] = @tmux.new_interface_window(iface)
|
132
|
+
end
|
133
|
+
ports
|
134
|
+
end
|
135
|
+
|
136
|
+
def start_hidden_bots
|
137
|
+
# p ports
|
138
|
+
# puts run_id
|
139
|
+
# Nutella.runlist.length
|
140
|
+
# Nutella.config['broker']
|
141
|
+
# Create the webpage for all interfaces
|
142
|
+
# Start the web_server serving the whole interfaces directory
|
143
|
+
# Output message that shows the port where we are connecting
|
144
|
+
end
|
145
|
+
|
146
|
+
def outputSuccessMessage(runid, run)
|
147
|
+
if runid == Nutella.currentProject.config["name"]
|
148
|
+
console.success "Project " + Nutella.currentProject.config["name"] + " started. Do `tmux attach-session -t #{Nutella.currentProject.config["name"]}` to monitor your bots."
|
149
|
+
else
|
150
|
+
console.success "Project " + Nutella.currentProject.config["name"] + ", run " + run + " started"
|
151
|
+
end
|
152
|
+
end
|
97
153
|
|
98
154
|
end
|
99
155
|
|
data/lib/core/commands/stop.rb
CHANGED
@@ -4,46 +4,41 @@ require 'core/tmux'
|
|
4
4
|
module Nutella
|
5
5
|
class Stop < Command
|
6
6
|
@description = "Stops all or some of the bots in the current project"
|
7
|
-
|
7
|
+
# Is current directory a nutella prj?
|
8
8
|
def run(args=nil)
|
9
|
-
|
10
|
-
if !Nutella.currentProject.exist?
|
11
|
-
return
|
12
|
-
end
|
13
|
-
|
14
|
-
# Extract runid
|
15
|
-
runid = args[0].to_s.empty? ? Nutella.currentProject.config["name"] : Nutella.currentProject.config["name"] + "_" + args[0]
|
16
|
-
|
17
|
-
# Remove from the list of runs
|
18
|
-
if Nutella.runlist.delete?(runid).nil?
|
19
|
-
console.warn "Run #{runid} doesn't exist. Impossible to stop it."
|
9
|
+
if !Nutella.currentProject.exist?
|
20
10
|
return
|
21
11
|
end
|
22
|
-
|
12
|
+
runid = Nutella.runlist.extractRunId args[0]
|
13
|
+
# Removes the run from the list of runs if it exists
|
14
|
+
removeRunfromList(runid, args[0])
|
15
|
+
# Stop broker if needed
|
23
16
|
if Nutella.runlist.empty? and Nutella.config['broker'] == "localhost"
|
24
17
|
stopBroker
|
25
18
|
end
|
26
|
-
|
27
|
-
# Extract project directory
|
28
|
-
@prj_dir = Nutella.currentProject.dir
|
29
|
-
|
30
19
|
# Stops all the bots
|
31
|
-
Tmux.killSession(runid)
|
32
|
-
|
20
|
+
Tmux.killSession(runid)
|
33
21
|
# Deletes bots config file if it exists
|
34
|
-
|
35
|
-
|
22
|
+
deleteBotsConfigFile
|
36
23
|
# Output success message
|
37
|
-
|
38
|
-
console.success "Project #{Nutella.currentProject.config["name"]} stopped"
|
39
|
-
else
|
40
|
-
console.success "Project #{Nutella.currentProject.config["name"]}, run #{args[0]} stopped"
|
41
|
-
end
|
24
|
+
outputSuccessMessage(runid, args[0])
|
42
25
|
end
|
43
26
|
|
44
27
|
|
45
28
|
private
|
46
|
-
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
def removeRunfromList(runid, run)
|
33
|
+
if Nutella.runlist.delete?(runid).nil?
|
34
|
+
if runid == Nutella.currentProject.config["name"]
|
35
|
+
console.warn "Run #{runid} doesn't exist. Impossible to stop it."
|
36
|
+
else
|
37
|
+
console.warn "Run #{run} doesn't exist. Impossible to stop it."
|
38
|
+
end
|
39
|
+
return
|
40
|
+
end
|
41
|
+
end
|
47
42
|
|
48
43
|
def stopBroker
|
49
44
|
pidFile = "#{Nutella.config["broker_dir"]}/bin/.pid"
|
@@ -55,8 +50,21 @@ module Nutella
|
|
55
50
|
File.delete(pidFile)
|
56
51
|
end
|
57
52
|
end
|
53
|
+
|
54
|
+
def deleteBotsConfigFile
|
55
|
+
prj_dir = Nutella.currentProject.dir
|
56
|
+
if File.exist?("#{prj_dir}/.botsconfig.json")
|
57
|
+
File.delete("#{prj_dir}/.botsconfig.json")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def outputSuccessMessage(runid, run)
|
62
|
+
if runid == Nutella.currentProject.config["name"]
|
63
|
+
console.success "Project #{Nutella.currentProject.config["name"]} stopped"
|
64
|
+
else
|
65
|
+
console.success "Project #{Nutella.currentProject.config["name"]}, run #{run} stopped"
|
66
|
+
end
|
67
|
+
end
|
58
68
|
|
59
69
|
end
|
60
|
-
|
61
|
-
|
62
70
|
end
|
data/lib/core/tmux.rb
CHANGED
@@ -6,13 +6,13 @@ module Nutella
|
|
6
6
|
@runId = runId
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def new_bot_window(bot)
|
10
10
|
if !defined?(@sessions)
|
11
|
-
# If
|
11
|
+
# If there is no sessions, let's create one and, at the same time, create a new window for the bot
|
12
12
|
`tmux new-session -d -s #{@runId} -n #{bot} &> /dev/null`
|
13
13
|
@sessions = [bot]
|
14
14
|
else
|
15
|
-
# Create new window `bot`
|
15
|
+
# Create new window for `bot`
|
16
16
|
# -k destroys it if it can't be created
|
17
17
|
# Pring info about creation of window
|
18
18
|
`tmux new-window -kP -n #{bot} &> /dev/null`
|
@@ -21,9 +21,23 @@ module Nutella
|
|
21
21
|
# Select window
|
22
22
|
`tmux select-window -t #{@runId}:#{@sessions.length-1} &> /dev/null`
|
23
23
|
# Start bot
|
24
|
-
`tmux send-keys "cd bots/#{bot};./startup #{@runId}" C-m`
|
24
|
+
`tmux send-keys "cd bots/#{bot};./startup #{@runId} #{Nutella.config["broker"]}" C-m`
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
|
+
def new_interface_window( iface )
|
28
|
+
# Create new window for `iface`
|
29
|
+
# note: -k option destroys it if it can't be created
|
30
|
+
# hide window creation info
|
31
|
+
`tmux new-window -kP -n #{iface} &> /dev/null`
|
32
|
+
@sessions.push(iface)
|
33
|
+
# Select window
|
34
|
+
`tmux select-window -t #{@runId}:#{@sessions.length-1} &> /dev/null`
|
35
|
+
port = 57880+@sessions.length
|
36
|
+
# Start serving interface
|
37
|
+
`tmux send-keys "cd interfaces/#{iface};thin -R #{Nutella.config['nutella_home']}/lib/extra/config.ru -p #{port.to_s} start" C-m`
|
38
|
+
port
|
39
|
+
end
|
40
|
+
|
27
41
|
def self.killSession(runId)
|
28
42
|
`tmux kill-session -t #{runId} &> /dev/null`
|
29
43
|
end
|
data/lib/extra/config.ru
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: nutella_framework 0.1.2 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "nutella_framework"
|
9
|
+
s.version = "0.1.2"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Alessandro Gnoli"]
|
14
|
+
s.date = "2014-11-14"
|
15
|
+
s.description = "Nutella is a framework to build and run \"Internet of Things\"-like learning applications"
|
16
|
+
s.email = "tebemis@gmail.com"
|
17
|
+
s.executables = ["nutella"]
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE",
|
20
|
+
"README.md"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".travis.yml",
|
25
|
+
"Gemfile",
|
26
|
+
"LICENSE",
|
27
|
+
"README.md",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"bin/nutella",
|
31
|
+
"lib/cli/nutella_cli.rb",
|
32
|
+
"lib/config/config.rb",
|
33
|
+
"lib/config/project.rb",
|
34
|
+
"lib/config/runlist.rb",
|
35
|
+
"lib/core/command.rb",
|
36
|
+
"lib/core/commands/broker.rb",
|
37
|
+
"lib/core/commands/checkup.rb",
|
38
|
+
"lib/core/commands/help.rb",
|
39
|
+
"lib/core/commands/install.rb",
|
40
|
+
"lib/core/commands/new.rb",
|
41
|
+
"lib/core/commands/runs.rb",
|
42
|
+
"lib/core/commands/start.rb",
|
43
|
+
"lib/core/commands/stop.rb",
|
44
|
+
"lib/core/nutella_core.rb",
|
45
|
+
"lib/core/tmux.rb",
|
46
|
+
"lib/extra/config.ru",
|
47
|
+
"lib/extra/interfaces_list.erubis",
|
48
|
+
"lib/extra/main_interface.rb",
|
49
|
+
"lib/logging/nutella_logger-remote.rb",
|
50
|
+
"lib/logging/nutella_logger.rb",
|
51
|
+
"lib/logging/nutella_logging.rb",
|
52
|
+
"lib/nutella_framework.rb",
|
53
|
+
"nutella_framework.gemspec",
|
54
|
+
"test/config/test_config.rb",
|
55
|
+
"test/config/test_project.rb",
|
56
|
+
"test/config/test_runlist.rb",
|
57
|
+
"test/helper.rb",
|
58
|
+
"test/logging/test_logging.rb",
|
59
|
+
"test/test_nutella_framework.rb"
|
60
|
+
]
|
61
|
+
s.homepage = "https://github.com/nutella-framework/nutella_framework"
|
62
|
+
s.licenses = ["MIT"]
|
63
|
+
s.rubygems_version = "2.2.2"
|
64
|
+
s.summary = "IoT-like learning applications framework"
|
65
|
+
|
66
|
+
if s.respond_to? :specification_version then
|
67
|
+
s.specification_version = 4
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_runtime_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
71
|
+
s.add_runtime_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
72
|
+
s.add_runtime_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
73
|
+
s.add_runtime_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
74
|
+
s.add_runtime_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
75
|
+
s.add_runtime_dependency(%q<sinatra>, [">= 1.4.5", "~> 1.4.5"])
|
76
|
+
s.add_runtime_dependency(%q<erubis>, [">= 2.7.0", "~> 2.7.0"])
|
77
|
+
s.add_development_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
78
|
+
s.add_development_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
79
|
+
s.add_development_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
80
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0", "~> 1.0"])
|
81
|
+
s.add_development_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0.1"])
|
82
|
+
s.add_development_dependency(%q<simplecov>, [">= 0", "~> 0"])
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
85
|
+
s.add_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
86
|
+
s.add_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
87
|
+
s.add_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
88
|
+
s.add_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
89
|
+
s.add_dependency(%q<sinatra>, [">= 1.4.5", "~> 1.4.5"])
|
90
|
+
s.add_dependency(%q<erubis>, [">= 2.7.0", "~> 2.7.0"])
|
91
|
+
s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
92
|
+
s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
93
|
+
s.add_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
94
|
+
s.add_dependency(%q<bundler>, [">= 1.0", "~> 1.0"])
|
95
|
+
s.add_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0.1"])
|
96
|
+
s.add_dependency(%q<simplecov>, [">= 0", "~> 0"])
|
97
|
+
end
|
98
|
+
else
|
99
|
+
s.add_dependency(%q<ansi>, [">= 1.4.3", "~> 1.4"])
|
100
|
+
s.add_dependency(%q<semantic>, [">= 1.3", "~> 1.3"])
|
101
|
+
s.add_dependency(%q<logging>, [">= 1.8.2", "~> 1.8"])
|
102
|
+
s.add_dependency(%q<git>, [">= 1.2.8", "~> 1.2"])
|
103
|
+
s.add_dependency(%q<thin>, [">= 1.6.3", "~> 1.6.3"])
|
104
|
+
s.add_dependency(%q<sinatra>, [">= 1.4.5", "~> 1.4.5"])
|
105
|
+
s.add_dependency(%q<erubis>, [">= 2.7.0", "~> 2.7.0"])
|
106
|
+
s.add_dependency(%q<shoulda>, [">= 3", "~> 3"])
|
107
|
+
s.add_dependency(%q<yard>, [">= 0.8.7", "~> 0.8"])
|
108
|
+
s.add_dependency(%q<rdoc>, [">= 4.0", "~> 4.0"])
|
109
|
+
s.add_dependency(%q<bundler>, [">= 1.0", "~> 1.0"])
|
110
|
+
s.add_dependency(%q<jeweler>, [">= 2.0.1", "~> 2.0.1"])
|
111
|
+
s.add_dependency(%q<simplecov>, [">= 0", "~> 0"])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
data/test/config/test_project.rb
CHANGED
@@ -3,27 +3,28 @@ require 'helper'
|
|
3
3
|
module Nutella
|
4
4
|
class TestNutellaFramework < MiniTest::Test
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def setup
|
7
|
+
Nutella.init
|
8
|
+
end
|
9
|
+
|
10
|
+
# The test works but it takes to long to run it all the time
|
11
|
+
# should "install remote interface template correctly" do
|
12
|
+
# Dir.chdir NUTELLA_HOME
|
13
|
+
# prj_dir = "#{Dir.pwd}/test_prj"
|
14
|
+
# # create new project and cs into it
|
15
|
+
# Nutella.executeCommand "new", ["test_prj"]
|
16
|
+
# Dir.chdir prj_dir
|
17
|
+
# Nutella.executeCommand "install", ["basic-web-interface"]
|
18
|
+
# # Cleanup
|
19
|
+
# Dir.chdir NUTELLA_HOME
|
20
|
+
# FileUtils.rm_rf prj_dir
|
21
|
+
# end
|
11
22
|
|
12
|
-
# should "Verify the installation" do
|
13
|
-
# Nutella.init
|
14
|
-
# Nutella.executeCommand "checkup"
|
15
|
-
# # e = assert_raises HelpOutException do
|
16
|
-
# # Nutella.executeCommand "checkup"
|
17
|
-
# # end
|
18
|
-
# end
|
19
23
|
|
24
|
+
def teardown
|
25
|
+
Nutella.config.send(:removeConfigFile)
|
26
|
+
end
|
20
27
|
|
21
|
-
# should "read the broker parameter correctly" do
|
22
|
-
# Nutella.store_constants
|
23
|
-
# $stdout = StringIO.new
|
24
|
-
# NutellaCLI.executeCommand("broker")
|
25
|
-
# assert_equal "Currently using broker: localhost\n", $stdout.string
|
26
|
-
# end
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nutella_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Gnoli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ansi
|
@@ -70,6 +70,86 @@ dependencies:
|
|
70
70
|
- - "~>"
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: '1.8'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: git
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.2.8
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.2'
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.2.8
|
90
|
+
- - "~>"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '1.2'
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: thin
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 1.6.3
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.6.3
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.6.3
|
110
|
+
- - "~>"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.6.3
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: sinatra
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 1.4.5
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.4.5
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 1.4.5
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.4.5
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: erubis
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 2.7.0
|
140
|
+
- - "~>"
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 2.7.0
|
143
|
+
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 2.7.0
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 2.7.0
|
73
153
|
- !ruby/object:Gem::Dependency
|
74
154
|
name: shoulda
|
75
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +170,26 @@ dependencies:
|
|
90
170
|
- - "~>"
|
91
171
|
- !ruby/object:Gem::Version
|
92
172
|
version: '3'
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: yard
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: 0.8.7
|
180
|
+
- - "~>"
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0.8'
|
183
|
+
type: :development
|
184
|
+
prerelease: false
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: 0.8.7
|
190
|
+
- - "~>"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0.8'
|
93
193
|
- !ruby/object:Gem::Dependency
|
94
194
|
name: rdoc
|
95
195
|
requirement: !ruby/object:Gem::Requirement
|
@@ -180,6 +280,7 @@ extra_rdoc_files:
|
|
180
280
|
- LICENSE
|
181
281
|
- README.md
|
182
282
|
files:
|
283
|
+
- ".document"
|
183
284
|
- ".travis.yml"
|
184
285
|
- Gemfile
|
185
286
|
- LICENSE
|
@@ -202,17 +303,21 @@ files:
|
|
202
303
|
- lib/core/commands/stop.rb
|
203
304
|
- lib/core/nutella_core.rb
|
204
305
|
- lib/core/tmux.rb
|
306
|
+
- lib/extra/config.ru
|
307
|
+
- lib/extra/interfaces_list.erubis
|
308
|
+
- lib/extra/main_interface.rb
|
205
309
|
- lib/logging/nutella_logger-remote.rb
|
206
310
|
- lib/logging/nutella_logger.rb
|
207
311
|
- lib/logging/nutella_logging.rb
|
208
312
|
- lib/nutella_framework.rb
|
313
|
+
- nutella_framework.gemspec
|
209
314
|
- test/config/test_config.rb
|
210
315
|
- test/config/test_project.rb
|
211
316
|
- test/config/test_runlist.rb
|
212
317
|
- test/helper.rb
|
213
318
|
- test/logging/test_logging.rb
|
214
319
|
- test/test_nutella_framework.rb
|
215
|
-
homepage: https://github.com/
|
320
|
+
homepage: https://github.com/nutella-framework/nutella_framework
|
216
321
|
licenses:
|
217
322
|
- MIT
|
218
323
|
metadata: {}
|