nutella_framework 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -3
- data/VERSION +1 -1
- data/actors/main_interface/main_interface_bot.rb +148 -0
- data/actors/main_interface/public/index.html +47 -0
- data/actors/main_interface/startup +5 -0
- data/actors/main_interface/views/index.erb +45 -0
- data/actors/main_interface/views/not_found_404.erb +37 -0
- data/lib/cli/nutella_cli.rb +24 -15
- data/lib/config/config.rb +5 -67
- data/lib/config/current_project.rb +58 -0
- data/lib/config/persisted_hash.rb +114 -0
- data/lib/config/runlist.rb +19 -83
- data/lib/core/command.rb +2 -2
- data/lib/core/commands/broker.rb +23 -24
- data/lib/core/commands/checkup.rb +36 -37
- data/lib/core/commands/help.rb +3 -3
- data/lib/core/commands/install.rb +3 -4
- data/lib/core/commands/new.rb +26 -28
- data/lib/core/commands/runs.rb +22 -31
- data/lib/core/commands/start.rb +134 -121
- data/lib/core/commands/stop.rb +62 -48
- data/lib/core/nutella_core.rb +23 -12
- data/lib/core/run_command.rb +44 -0
- data/lib/core/tmux.rb +20 -18
- data/lib/logging/nutella_logging.rb +5 -5
- data/lib/nutella_framework.rb +8 -6
- data/nutella_framework.gemspec +15 -12
- data/test/config/test_config.rb +23 -22
- data/test/config/test_project.rb +13 -12
- data/test/config/test_runlist.rb +30 -22
- metadata +15 -12
- data/lib/config/project.rb +0 -53
- data/lib/extra/config.ru +0 -2
- data/lib/extra/interfaces_list.erubis +0 -14
- data/lib/extra/main_interface.rb +0 -9
- data/test/test_nutella_framework.rb +0 -31
data/lib/config/runlist.rb
CHANGED
@@ -1,96 +1,32 @@
|
|
1
|
-
|
2
|
-
# The list is uniquely maintained inside a file
|
3
|
-
require 'singleton'
|
4
|
-
require 'json'
|
5
|
-
require 'set'
|
1
|
+
require 'config/persisted_hash'
|
6
2
|
|
7
3
|
module Nutella
|
8
4
|
|
9
|
-
class
|
10
|
-
|
11
|
-
RUN_LIST_FILE=File.dirname(__FILE__)+"/../../runlist.json"
|
12
|
-
|
13
|
-
include Singleton
|
14
|
-
|
15
|
-
def add?(runid)
|
16
|
-
begin
|
17
|
-
result = JSON.parse(IO.read(RUN_LIST_FILE)).to_set.add? runid
|
18
|
-
rescue
|
19
|
-
# No file, create one
|
20
|
-
result = [runid].to_set
|
21
|
-
end
|
22
|
-
writeFile(result)
|
23
|
-
end
|
24
|
-
|
25
|
-
def delete?(runid)
|
26
|
-
begin
|
27
|
-
result = JSON.parse(IO.read(RUN_LIST_FILE)).to_set.delete? runid
|
28
|
-
rescue
|
29
|
-
removeRunListFile
|
30
|
-
result = nil # List is empty, so nil
|
31
|
-
end
|
32
|
-
writeFile(result)
|
33
|
-
end
|
5
|
+
class RunListHash < PersistedHash
|
34
6
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
7
|
+
# Returns the +run_id+ names for a certain project
|
8
|
+
# If no project is specified, +run_id+s for all projects are returned
|
9
|
+
# @param [String] project_name the name of the project we want to find run names for
|
10
|
+
# @return [Array<String>] list of +run_id+s associated to the specified project
|
11
|
+
def runs_by_project( project_name=nil )
|
12
|
+
(project_name == nil) ? keys : keys.select { |run| run.start_with?(project_name) }
|
41
13
|
end
|
42
14
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_a(projectName=nil)
|
52
|
-
begin
|
53
|
-
list = JSON.parse(IO.read(RUN_LIST_FILE))
|
54
|
-
# filter by project
|
55
|
-
if projectName == nil
|
56
|
-
return list
|
57
|
-
else
|
58
|
-
return list.select { |run| run.start_with?(projectName) }
|
59
|
-
end
|
60
|
-
rescue
|
61
|
-
Array.new # There is no file or something went wrong
|
62
|
-
end
|
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
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def removeRunListFile
|
76
|
-
File.delete(RUN_LIST_FILE) if File.exist?(RUN_LIST_FILE)
|
77
|
-
end
|
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
|
15
|
+
# Extracts the +run_id+ from the run name (specified at command line)
|
16
|
+
# @param [String] run_name
|
17
|
+
# @return [String] the +run_id+ which is either the +project_name+ (if no +run_name+
|
18
|
+
# was specified) or the concatenation of +project_name+ and +run_name+
|
19
|
+
def extract_run_id( run_name )
|
20
|
+
run_name.to_s.empty? ? Nutella.current_project.config['name'] : "#{Nutella.current_project.config['name']}_#{run_name}"
|
87
21
|
end
|
88
22
|
|
23
|
+
|
89
24
|
end
|
90
|
-
|
91
|
-
|
25
|
+
|
26
|
+
# Calling this method (Nutella.runlist) simply returns and instance of
|
27
|
+
# RunListHash linked to file runlist.json in the nutella home directory
|
92
28
|
def Nutella.runlist
|
93
|
-
|
29
|
+
RunListHash.new( "#{File.dirname(__FILE__)}/../../runlist.json" )
|
94
30
|
end
|
95
31
|
|
96
32
|
end
|
data/lib/core/command.rb
CHANGED
@@ -5,8 +5,8 @@ module Nutella
|
|
5
5
|
class << self; attr_accessor :description end
|
6
6
|
|
7
7
|
# Commands overload this method to execute
|
8
|
-
def run
|
9
|
-
console.error
|
8
|
+
def run( args=nil )
|
9
|
+
console.error 'Running the generic command!!! WAT?'
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/core/commands/broker.rb
CHANGED
@@ -3,53 +3,52 @@ require 'socket'
|
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class Broker < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Displays information about the broker and allows to change it'
|
7
7
|
|
8
8
|
def run(args=nil)
|
9
|
-
|
9
|
+
|
10
|
+
# If no argument then we just display info about the broker
|
10
11
|
if args==nil || args.empty?
|
11
|
-
|
12
|
+
print_broker_info
|
12
13
|
return
|
13
14
|
end
|
14
15
|
# If there are arguments we are doing manipulations
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# startBroker
|
20
|
-
# when "stop"
|
21
|
-
# stopBroker
|
16
|
+
sub_command = args[0]
|
17
|
+
sum_command_param = args[1]
|
18
|
+
if sub_command=='set'
|
19
|
+
change_broker sum_command_param
|
22
20
|
else
|
23
|
-
console.warn "Unknown
|
21
|
+
console.warn "Unknown 'nutella broker' option #{sub_command}. Try 'nutella broker' or 'nutella broker set <new_broker>' instead"
|
24
22
|
end
|
25
|
-
|
26
23
|
end
|
27
24
|
|
28
25
|
private
|
29
26
|
|
30
|
-
def
|
31
|
-
if Nutella.config[
|
32
|
-
console.warn
|
27
|
+
def print_broker_info
|
28
|
+
if Nutella.config['broker'].nil?
|
29
|
+
console.warn 'No broker has been specified yet. Please, run `nutella broker set <broker>` to specify a broker'
|
33
30
|
else
|
34
|
-
console.info"Currently using broker: #{Nutella.config[
|
31
|
+
console.info "Currently using broker: #{Nutella.config['broker']}"
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
38
35
|
|
39
|
-
def
|
36
|
+
def change_broker( new_broker )
|
40
37
|
# Check that there are no runs hinging on this broker
|
41
|
-
|
42
|
-
console.warn
|
38
|
+
unless Nutella.runlist.empty?
|
39
|
+
console.warn 'You are currently running some projects on this broker. You can\'t change the broker while running.'
|
43
40
|
return
|
44
41
|
end
|
45
|
-
#
|
42
|
+
# Try to parse the hostname and switch to the new broker
|
46
43
|
begin
|
47
|
-
IPSocket.getaddress
|
44
|
+
IPSocket.getaddress new_broker
|
48
45
|
rescue
|
49
|
-
console.warn "
|
46
|
+
console.warn "#{new_broker} is not a valid hostname for a broker"
|
47
|
+
return
|
50
48
|
end
|
51
|
-
Nutella.config[
|
52
|
-
|
49
|
+
Nutella.config['broker'] = new_broker
|
50
|
+
# Print a confirmation message
|
51
|
+
console.success "Now using broker: #{Nutella.config['broker']}"
|
53
52
|
end
|
54
53
|
|
55
54
|
end
|
@@ -3,51 +3,53 @@ require 'semantic'
|
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class Checkup < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Checks that all the dependencies are installed and prepares nutella to run'
|
7
7
|
|
8
|
-
def run(args=nil)
|
8
|
+
def run( args=nil )
|
9
|
+
|
9
10
|
# First check that we have all the tools we need to run nutella
|
10
|
-
|
11
|
-
return
|
12
|
-
end
|
11
|
+
return unless all_dependencies_installed?
|
13
12
|
|
14
|
-
# Check if we have a broker
|
15
|
-
if
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
# Check if we have a local broker installed
|
14
|
+
# and install one if we don't
|
15
|
+
if File.directory? Nutella.config['broker_dir']
|
16
|
+
console.info 'You have a local broker installed. Yay!'
|
17
|
+
else
|
18
|
+
console.warn 'You don\'t seem to have a local broker installed so we are going to go ahead and install one for you. This might take some time...'
|
19
|
+
unless install_local_broker
|
20
|
+
console.error 'Whoops...something went wrong while installing the broker'
|
19
21
|
return
|
20
22
|
end
|
21
|
-
else
|
22
|
-
console.info "You have a local broker installed. Yay!"
|
23
23
|
end
|
24
24
|
|
25
|
-
# Set
|
26
|
-
Nutella.config[
|
27
|
-
|
25
|
+
# Set ready flag in config.json
|
26
|
+
Nutella.config['ready'] = true
|
27
|
+
|
28
|
+
# Output success message
|
29
|
+
console.success 'All systems go! You are ready to use nutella!'
|
28
30
|
end
|
29
31
|
|
30
32
|
|
31
33
|
private
|
32
34
|
|
33
35
|
|
34
|
-
def
|
36
|
+
def install_local_broker
|
35
37
|
# Clone, cd and npm install
|
36
|
-
out1 = system "git clone git://github.com/mcollina/mosca.git #{Nutella.config[
|
37
|
-
Dir.chdir(Nutella.config[
|
38
|
-
out2 = system
|
38
|
+
out1 = system "git clone git://github.com/mcollina/mosca.git #{Nutella.config['broker_dir']} > /dev/null 2>&1"
|
39
|
+
Dir.chdir(Nutella.config['broker_dir'])
|
40
|
+
out2 = system 'npm install > /dev/null 2>&1'
|
39
41
|
|
40
|
-
# Add startup script
|
41
|
-
File.open(
|
42
|
-
File.chmod(0755,
|
42
|
+
# Add startup script and make it executable
|
43
|
+
File.open('startup', 'w') { |file| file.write("#!/bin/sh\n\nBASEDIR=$(dirname $0)\n$BASEDIR/bin/mosca --http-port 1884 &\necho $! > $BASEDIR/bin/.pid\n") }
|
44
|
+
File.chmod( 0755, 'startup' )
|
43
45
|
|
44
|
-
#
|
45
|
-
Nutella.config[
|
46
|
-
|
46
|
+
# Write configuration into config.json
|
47
|
+
Nutella.config['broker'] = 'localhost'
|
48
|
+
out1 && out2
|
47
49
|
end
|
48
50
|
|
49
51
|
|
50
|
-
def
|
52
|
+
def all_dependencies_installed?
|
51
53
|
# Node version lambda
|
52
54
|
node_semver = lambda do
|
53
55
|
out = `node --version`
|
@@ -67,34 +69,31 @@ module Nutella
|
|
67
69
|
Semantic::Version.new "#{out[0..2]}.0"
|
68
70
|
end
|
69
71
|
# Check versions
|
70
|
-
if
|
71
|
-
|
72
|
-
and checkVersion?("tmux", "1.8.0", tmux_semver)
|
73
|
-
return true
|
74
|
-
end
|
72
|
+
return true if check_version?('node', '0.10.0', node_semver) && check_version?('git', '1.8.0', git_semver) && check_version?('tmux', '1.8.0', tmux_semver)
|
73
|
+
# If even one of the checks fails, return false
|
75
74
|
false
|
76
75
|
end
|
77
76
|
|
78
77
|
|
79
|
-
def
|
78
|
+
def check_version?(dep, req_version, lambda)
|
80
79
|
begin
|
81
80
|
actual_version = lambda.call
|
82
81
|
rescue
|
83
|
-
console.warn "Doesn't look like #{dep} is installed in your system. " +
|
84
|
-
"
|
82
|
+
console.warn "Doesn't look like #{dep} is installed in your system. " +
|
83
|
+
"Unfortunately nutella can't do much unless all the dependencies are installed :("
|
85
84
|
return
|
86
85
|
end
|
87
86
|
required_version = Semantic::Version.new req_version
|
88
87
|
if actual_version < required_version
|
89
88
|
console.warn "Your version of #{dep} is a little old (#{actual_version}). Nutella requires #{required_version}. Please upgrade!"
|
90
|
-
|
89
|
+
false
|
91
90
|
else
|
92
91
|
console.info "Your #{dep} version is #{actual_version}. Yay!"
|
93
92
|
true
|
94
93
|
end
|
95
94
|
end
|
96
|
-
|
97
|
-
|
95
|
+
|
98
96
|
end
|
97
|
+
|
99
98
|
end
|
100
99
|
|
data/lib/core/commands/help.rb
CHANGED
@@ -3,11 +3,11 @@ require 'core/command'
|
|
3
3
|
module Nutella
|
4
4
|
|
5
5
|
class Help < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Displays what every command does and how to use it'
|
7
7
|
|
8
8
|
def run(args=nil)
|
9
|
-
message=
|
10
|
-
Dir[File.dirname(__FILE__)
|
9
|
+
message=''
|
10
|
+
Dir["#{File.dirname(__FILE__)}/*.rb"].each do |file|
|
11
11
|
message += "#{File.basename(file, File.extname(file))}\t\t"
|
12
12
|
message += Object::const_get("Nutella::#{File.basename(file, File.extname(file)).capitalize}").description
|
13
13
|
message += "\n"
|
@@ -10,7 +10,7 @@ module Nutella
|
|
10
10
|
|
11
11
|
def run(args=nil)
|
12
12
|
# Is current directory a nutella prj?
|
13
|
-
return unless Nutella.
|
13
|
+
return unless Nutella.current_project.exist?
|
14
14
|
|
15
15
|
# Check args
|
16
16
|
if args.empty?
|
@@ -21,7 +21,7 @@ module Nutella
|
|
21
21
|
destination_dir = args.length==2 ? args[1] : nil
|
22
22
|
|
23
23
|
# Extract project directory
|
24
|
-
prj_dir = Nutella.
|
24
|
+
prj_dir = Nutella.current_project.dir
|
25
25
|
|
26
26
|
# What kind of template are we handling?
|
27
27
|
if is_template_a_local_dir? template
|
@@ -91,10 +91,9 @@ module Nutella
|
|
91
91
|
# If all is good, copy the template to dest_dir...
|
92
92
|
FileUtils.copy_entry template_dir, dest_dir
|
93
93
|
|
94
|
-
# ... and remove nutella.json
|
94
|
+
# ... and remove nutella.json and .git folder if they exist
|
95
95
|
File.delete "#{dest_dir}/nutella.json" if File.exist? "#{dest_dir}/nutella.json"
|
96
96
|
FileUtils.rm_rf "#{dest_dir}/.git"
|
97
|
-
File.delete "#{dest_dir}/.gitignore" if File.exist? "#{dest_dir}/.gitignore"
|
98
97
|
|
99
98
|
# Make the user feel happy and accomplished! :)
|
100
99
|
console.success("Installed template: #{template} as #{dest_dir_name}")
|
data/lib/core/commands/new.rb
CHANGED
@@ -3,60 +3,58 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class New < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Creates a new project'
|
7
7
|
|
8
8
|
def run(args=nil)
|
9
|
-
|
9
|
+
cur_prj_dir = args[0]
|
10
10
|
|
11
11
|
# If no other arguments, show help and quit here
|
12
12
|
if args.empty?
|
13
|
-
console.warn
|
13
|
+
console.warn 'You need to specify a name for your new project'
|
14
14
|
return
|
15
15
|
end
|
16
16
|
|
17
|
-
#
|
18
|
-
if
|
19
|
-
|
20
|
-
|
17
|
+
# Check that a directory (i.e. project) with the same name doesn't already exist
|
18
|
+
# If it does it looks into it to see if there is a nutella.json file and displays
|
19
|
+
# the proper error message
|
20
|
+
if File.directory? cur_prj_dir
|
21
|
+
if File.exist? "#{cur_prj_dir}/nutella.json"
|
22
|
+
console.warn "A project named #{cur_prj_dir} already exists"
|
21
23
|
return
|
22
24
|
else
|
23
|
-
console.warn "A directory named #{
|
25
|
+
console.warn "A directory named #{cur_prj_dir} already exists"
|
24
26
|
return
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
Dir.chdir @prj_dir # CD into the project
|
30
|
+
# If all seems good, generate the project structure
|
31
|
+
create_dir_structure cur_prj_dir
|
32
|
+
|
32
33
|
# Display a nice success message and return
|
33
|
-
console.success "Your new project #{
|
34
|
+
console.success "Your new project #{cur_prj_dir} is ready!"
|
34
35
|
end
|
35
36
|
|
36
37
|
|
37
38
|
private
|
38
39
|
|
39
40
|
|
40
|
-
def
|
41
|
-
|
42
|
-
FileUtils.mkdir_p("#{
|
43
|
-
FileUtils.mkdir_p("#{
|
44
|
-
#
|
41
|
+
def create_dir_structure( cur_prj_dir )
|
42
|
+
# Create directories
|
43
|
+
FileUtils.mkdir_p("#{cur_prj_dir}/bots")
|
44
|
+
FileUtils.mkdir_p("#{cur_prj_dir}/interfaces")
|
45
|
+
# Create nutella.json hash
|
45
46
|
config_file_hash = {
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
:name => cur_prj_dir,
|
48
|
+
:version => '0.1.0',
|
49
|
+
:nutella_version => File.open("#{NUTELLA_HOME}VERSION", 'rb').read,
|
50
|
+
:type => 'project',
|
51
|
+
:description => 'A quick description of your project'
|
49
52
|
}
|
50
|
-
|
53
|
+
# Write nutella.json hash
|
54
|
+
File.open("#{cur_prj_dir}/nutella.json", 'w') do |f|
|
51
55
|
f.write(JSON.pretty_generate(config_file_hash))
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
|
-
def removeDirStructure
|
56
|
-
Dir.chdir @cur_dir
|
57
|
-
console.info "Removing project #{@prj_dir}"
|
58
|
-
FileUtils.rm_rf(@prj_dir)
|
59
|
-
end
|
60
|
-
|
61
59
|
end
|
62
60
|
end
|
data/lib/core/commands/runs.rb
CHANGED
@@ -3,18 +3,18 @@ require 'core/command'
|
|
3
3
|
|
4
4
|
module Nutella
|
5
5
|
class Runs < Command
|
6
|
-
@description =
|
6
|
+
@description = 'Displays list of runs for current project or all projects'
|
7
7
|
|
8
8
|
def run(args=nil)
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
# If invoked with "all" it will show all the runs under this instance of nutella
|
11
|
+
if args[0]=='all'
|
12
|
+
display_all_runs
|
12
13
|
else
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
displayProjectRuns
|
14
|
+
# If current dir is not a nutella project, return
|
15
|
+
return unless Nutella.current_project.exist?
|
16
|
+
# Display list of runs for current nutella project
|
17
|
+
display_project_runs
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -22,35 +22,26 @@ module Nutella
|
|
22
22
|
private
|
23
23
|
|
24
24
|
|
25
|
-
def
|
25
|
+
def display_all_runs
|
26
26
|
if Nutella.runlist.empty?
|
27
|
-
console.info
|
27
|
+
console.info 'You are not running any projects'
|
28
28
|
else
|
29
|
-
console.info
|
30
|
-
Nutella.runlist.
|
29
|
+
console.info 'Currently running:'
|
30
|
+
Nutella.runlist.runs_by_project.each { |run| console.info " #{run}" }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
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)
|
34
|
+
def display_project_runs
|
35
|
+
project_name = Nutella.current_project.config['name']
|
36
|
+
runs = Nutella.runlist.runs_by_project project_name
|
47
37
|
console.info "Currently running #{runs.length} instances of project #{project_name}:"
|
48
|
-
runs.
|
49
|
-
run.
|
50
|
-
|
51
|
-
|
38
|
+
runs.each do |run|
|
39
|
+
run_id = run.dup
|
40
|
+
run_id.slice! "#{project_name}_"
|
41
|
+
if run_id.empty?
|
42
|
+
console.info " #{project_name}"
|
52
43
|
else
|
53
|
-
console.info " #{run}"
|
44
|
+
console.info " #{run}"
|
54
45
|
end
|
55
46
|
end
|
56
47
|
end
|