james_bond-core 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +36 -0
- data/README.md +6 -0
- data/bin/bond +6 -0
- data/james_bond-core.gemspec +25 -0
- data/lib/james_bond/core/command.rb +28 -0
- data/lib/james_bond/core/config.rb +33 -0
- data/lib/james_bond/core/default_missions.rb +1 -0
- data/lib/james_bond/core/help_mission.rb +24 -0
- data/lib/james_bond/core/mission/undefined_variable_error.rb +8 -0
- data/lib/james_bond/core/mission.rb +70 -0
- data/lib/james_bond/core/mission_loader.rb +57 -0
- data/lib/james_bond/core/mission_pool.rb +30 -0
- data/lib/james_bond/core/version.rb +5 -0
- data/lib/james_bond/core.rb +30 -0
- data/lib/james_bond.rb +4 -0
- data/spec/lib/james_bond/core/command_spec.rb +78 -0
- data/spec/lib/james_bond/core/mission_loader_spec.rb +17 -0
- data/spec/lib/james_bond/core/mission_spec.rb +210 -0
- data/spec/spec_helper.rb +7 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d450b6cebf1c2945eefc6600f1239d73c3a9e192
|
4
|
+
data.tar.gz: 80fad6427c8f721a7a59fb4f17ed4ef3c405a83c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: afb4dee9af6d4252b62701d26e39c7fff2cc88f92977448a36fa7cf58c19841ae08bc2ee924f1fe2b4f9dabc5cc9e2fb832d1d66706d394dc5c29715187576a8
|
7
|
+
data.tar.gz: 0a18d95bb13b183963cb7e57d750cd8c23fd90ee55074e0742c96849d756ac1699b29ecb906b65e51fcc3e1a47dbfc822293f4572c485466768ad7a9b6d943e7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
james_bond-core
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.0
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
james_bond-core (0.0.1)
|
5
|
+
slop (= 4.4.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
byebug (9.0.5)
|
11
|
+
diff-lcs (1.2.5)
|
12
|
+
rspec (3.4.0)
|
13
|
+
rspec-core (~> 3.4.0)
|
14
|
+
rspec-expectations (~> 3.4.0)
|
15
|
+
rspec-mocks (~> 3.4.0)
|
16
|
+
rspec-core (3.4.4)
|
17
|
+
rspec-support (~> 3.4.0)
|
18
|
+
rspec-expectations (3.4.0)
|
19
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
20
|
+
rspec-support (~> 3.4.0)
|
21
|
+
rspec-mocks (3.4.1)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.4.0)
|
24
|
+
rspec-support (3.4.1)
|
25
|
+
slop (4.4.1)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
byebug (= 9.0.5)
|
32
|
+
james_bond-core!
|
33
|
+
rspec (= 3.4.0)
|
34
|
+
|
35
|
+
BUNDLED WITH
|
36
|
+
1.12.5
|
data/README.md
ADDED
data/bin/bond
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "james_bond/core/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "james_bond-core"
|
7
|
+
gem.version = JamesBond::Core::VERSION
|
8
|
+
gem.date = "2016-08-18"
|
9
|
+
gem.summary = "Fully automation, from development to deploy"
|
10
|
+
gem.description = "Fully automation, from development to deploy. Let a professional help you!"
|
11
|
+
gem.authors = ["Airton Sobral", "Guilherme Cavalcanti"]
|
12
|
+
gem.email = ["airtonsobral@gmail.com", "guiocavalcanti@gmail.com"]
|
13
|
+
gem.require_paths = %w[lib]
|
14
|
+
gem.files = `git ls-files -z`.split("\x0")
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^spec/})
|
17
|
+
gem.extra_rdoc_files = %w[README.md]
|
18
|
+
gem.homepage = "http://rubygemgem.org/gems/james_bond"
|
19
|
+
gem.license = "MIT"
|
20
|
+
|
21
|
+
gem.required_ruby_version = ">= 2.1"
|
22
|
+
gem.add_dependency "slop", "4.4.1"
|
23
|
+
gem.add_development_dependency "rspec", "3.4.0"
|
24
|
+
gem.add_development_dependency "byebug", "9.0.5"
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module JamesBond
|
2
|
+
module Core
|
3
|
+
class Command
|
4
|
+
RESERVED_COMMANDS = ["env", "run", "server", "test", "deploy", "console"].freeze
|
5
|
+
|
6
|
+
attr_accessor :argv,
|
7
|
+
:user_command,
|
8
|
+
:main_command,
|
9
|
+
:raw_arguments,
|
10
|
+
:arguments_string,
|
11
|
+
:env,
|
12
|
+
:options
|
13
|
+
|
14
|
+
def initialize(argv:, env:)
|
15
|
+
@argv = argv
|
16
|
+
@user_command = argv.join(" ")
|
17
|
+
@main_command = argv.first
|
18
|
+
@raw_arguments = argv.drop(1)
|
19
|
+
@arguments_string = @raw_arguments.join(" ")
|
20
|
+
@env = env
|
21
|
+
end
|
22
|
+
|
23
|
+
def empty?
|
24
|
+
@argv.empty?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module JamesBond
|
4
|
+
module Core
|
5
|
+
class Config
|
6
|
+
ENV_PLACEHOLDER = ":env".freeze
|
7
|
+
RESERVED_COMMANDS = ["env", "run", "server", "test", "deploy", "console"].freeze
|
8
|
+
|
9
|
+
attr_accessor :yaml_path,
|
10
|
+
:raw_hash,
|
11
|
+
:missions
|
12
|
+
|
13
|
+
def initialize(params={})
|
14
|
+
@yaml_path = params[:yaml_path]
|
15
|
+
|
16
|
+
extract_config_from_yaml(@yaml_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def extract_config_from_yaml(yaml_path)
|
22
|
+
@raw_hash = YAML.load(File.read(yaml_path))
|
23
|
+
@missions = @raw_hash["missions"]
|
24
|
+
|
25
|
+
validate_config
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_config
|
29
|
+
raise "Please provide at least one mission to work with 007!" if !@missions || @missions.empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "james_bond/core/help_mission"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "james_bond/core/mission"
|
2
|
+
|
3
|
+
module JamesBond
|
4
|
+
module Core
|
5
|
+
class HelpMission
|
6
|
+
include JamesBond::Core::Mission
|
7
|
+
|
8
|
+
MISSION_NAME = "help"
|
9
|
+
MISSION_MAIN_COMMANDS = ["help"]
|
10
|
+
|
11
|
+
def build(config, params)
|
12
|
+
config.name = MISSION_NAME
|
13
|
+
config.main_commands = MISSION_MAIN_COMMANDS
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_help_command(command:, mission_pool:)
|
17
|
+
mission_pool.mission_list.each do |mission|
|
18
|
+
puts mission.core_mission_config.name
|
19
|
+
puts mission.option_rules
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "james_bond/core/mission/undefined_variable_error"
|
2
|
+
|
3
|
+
module JamesBond
|
4
|
+
module Core
|
5
|
+
module Mission
|
6
|
+
MissionConfig = Struct.new("MissionConfig", :name, :main_commands)
|
7
|
+
|
8
|
+
attr_accessor :core_mission_options,
|
9
|
+
:core_mission_config
|
10
|
+
|
11
|
+
attr_reader :option_rules
|
12
|
+
|
13
|
+
def initialize(params={})
|
14
|
+
@core_mission_config = MissionConfig.new
|
15
|
+
@core_mission_options = {}
|
16
|
+
|
17
|
+
build(@core_mission_config, params)
|
18
|
+
check_variables_definitions
|
19
|
+
check_main_command_methods
|
20
|
+
end
|
21
|
+
|
22
|
+
def build(config, params)
|
23
|
+
raise(NotImplementedError, "The method \"build\" must be implemented for the #{self.class} class")
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_command(command: , mission_pool:)
|
27
|
+
@core_mission_options = command.options = parse_arguments(command) if @option_rules
|
28
|
+
command.options = parse_arguments(command) if @option_rules
|
29
|
+
self.send(
|
30
|
+
build_command_method_name(command.main_command),
|
31
|
+
{ command: command, mission_pool: mission_pool }
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def arguments_parser(&block)
|
36
|
+
require "slop"
|
37
|
+
@option_rules = Slop::Options.new
|
38
|
+
yield(@option_rules)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_arguments(command)
|
44
|
+
arguments_array = command.raw_arguments
|
45
|
+
Slop::Parser.new(@option_rules).parse(arguments_array)
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_command_method_name(main_command)
|
49
|
+
"run_#{main_command}_command"
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_variables_definitions
|
53
|
+
raise(UndefinedVariableError,
|
54
|
+
"The mission name must be defined in the build method. " \
|
55
|
+
+ "Try calling config.name = \"MissionName\" inside the build method") if !@core_mission_config.name
|
56
|
+
raise(UndefinedVariableError,
|
57
|
+
"The main commands must be defined in the build method. " \
|
58
|
+
+ "Try calling config.main_commands = [\"cmd\", \"dmc\"] inside the build method") if !@core_mission_config.main_commands
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_main_command_methods
|
62
|
+
@core_mission_config.main_commands.each do |main_command|
|
63
|
+
expected_command_method = build_command_method_name(main_command)
|
64
|
+
raise(NotImplementedError,
|
65
|
+
"The method \"#{expected_command_method}\" must be implemented for the #{self.class}") if !self.respond_to?(expected_command_method)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "james_bond/core/mission_pool"
|
2
|
+
require "james_bond/core/default_missions"
|
3
|
+
|
4
|
+
module JamesBond
|
5
|
+
module Core
|
6
|
+
module MissionLoader
|
7
|
+
|
8
|
+
def self.default_missions
|
9
|
+
@default_missions ||= %w(JamesBond::Core::HelpMission)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default_missions=(list)
|
13
|
+
@default_missions = list
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load_missions(mission_names)
|
17
|
+
missions_loaded = mission_names.map do |mission_name|
|
18
|
+
load_mission(mission_name)
|
19
|
+
end
|
20
|
+
missions_loaded = append_default_missions(missions_loaded)
|
21
|
+
|
22
|
+
JamesBond::Core::MissionPool.new(mission_list: missions_loaded)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.load_mission(mission_name)
|
26
|
+
gem_name = "james_bond-#{sanitize_mission_name(mission_name)}_mission"
|
27
|
+
require_name = generate_gem_require_name(gem_name)
|
28
|
+
constant_name = constantize_gem_name(gem_name)
|
29
|
+
|
30
|
+
require require_name
|
31
|
+
klass = Object.const_get(constant_name)
|
32
|
+
klass.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.append_default_missions(mission_list)
|
36
|
+
mission_list + default_missions.map do |mission_class|
|
37
|
+
klass = Object.const_get(mission_class)
|
38
|
+
klass.new
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.constantize_gem_name(gem_name)
|
43
|
+
class_name = (gem_name || "").split("-")
|
44
|
+
.map { |split| split.split("_").collect(&:capitalize).join }
|
45
|
+
.join("::")
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.generate_gem_require_name(gem_name)
|
49
|
+
gem_name.gsub("-", "/")
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.sanitize_mission_name(mission_name)
|
53
|
+
mission_name.gsub(/[^0-9a-z\_\-]/i, "")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module JamesBond
|
2
|
+
module Core
|
3
|
+
class MissionPool
|
4
|
+
attr_accessor :mission_list, :mission_by_main_command
|
5
|
+
|
6
|
+
def initialize(params={})
|
7
|
+
@mission_list = params[:mission_list]
|
8
|
+
build_mission_by_main_command
|
9
|
+
end
|
10
|
+
|
11
|
+
def decide_mission(command)
|
12
|
+
@mission_by_main_command[command.main_command]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def build_mission_by_main_command
|
18
|
+
@mission_by_main_command = {}
|
19
|
+
@mission_list.each do |mission|
|
20
|
+
mission.core_mission_config.main_commands.each do |main_command|
|
21
|
+
another_mission = @mission_by_main_command[main_command]
|
22
|
+
raise "Mission conflict! Two missions (\"#{another_mission.name}\" and \"#{mission.name}\") " \
|
23
|
+
+ "are assigned for the same command (\"#{main_command}\")" if another_mission
|
24
|
+
@mission_by_main_command[main_command] = mission
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "james_bond/core/version"
|
2
|
+
require "james_bond/core/config"
|
3
|
+
require "james_bond/core/mission_loader"
|
4
|
+
require "james_bond/core/command"
|
5
|
+
require "james_bond/core/mission"
|
6
|
+
|
7
|
+
module JamesBond
|
8
|
+
module Core
|
9
|
+
DEFAULT_ENVIRONMENT = "dev".freeze
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def run_command(argv, env=DEFAULT_ENVIRONMENT)
|
13
|
+
config = load_config
|
14
|
+
mission_pool = MissionLoader.load_missions(config.missions)
|
15
|
+
command = Command.new(argv: argv, env: env)
|
16
|
+
command = Command.new(argv: ["help"], env: env) if command.empty?
|
17
|
+
|
18
|
+
winning_mission = mission_pool.decide_mission(command)
|
19
|
+
winning_mission.run_command(command: command, mission_pool: mission_pool)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def load_config
|
25
|
+
yaml_path = File.join(Dir.pwd, "config", "james_bond.yml")
|
26
|
+
JamesBond::Core::Config.new(yaml_path: yaml_path)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/james_bond.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JamesBond::Core::Command do
|
4
|
+
describe "#argv" do
|
5
|
+
it "should return the argv received" do
|
6
|
+
argv = ["charizard", "papai", "noel", "--delta", "-t"]
|
7
|
+
instance = described_class.new(argv: ["charizard", "papai", "noel", "--delta", "-t"],
|
8
|
+
env: "dev")
|
9
|
+
expect(instance.argv).to eq(argv)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#user_command" do
|
14
|
+
it "should return the argv as one string" do
|
15
|
+
instance = described_class.new(argv: ["charizard", "papai", "noel", "--delta", "-t"],
|
16
|
+
env: "dev")
|
17
|
+
expect(instance.user_command).to eq("charizard papai noel --delta -t")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#main_command" do
|
22
|
+
it "should return the first command" do
|
23
|
+
instance = described_class.new(argv: ["charizard"], env: "dev")
|
24
|
+
expect(instance.main_command).to eq("charizard")
|
25
|
+
instance = described_class.new(argv: ["charizard", "delta"], env: "dev")
|
26
|
+
expect(instance.main_command).to eq("charizard")
|
27
|
+
instance = described_class.new(argv: ["charizard", "delta", "-t", "--gama"], env: "dev")
|
28
|
+
expect(instance.main_command).to eq("charizard")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#raw_arguments" do
|
33
|
+
it "should return the arguments array without the main_command" do
|
34
|
+
instance = described_class.new(argv: ["charizard"], env: "dev")
|
35
|
+
expect(instance.raw_arguments).to eq([])
|
36
|
+
instance = described_class.new(argv: ["charizard", "delta"], env: "dev")
|
37
|
+
expect(instance.raw_arguments).to eq(["delta"])
|
38
|
+
instance = described_class.new(argv: ["charizard", "delta", "-t", "--gama"], env: "dev")
|
39
|
+
expect(instance.raw_arguments).to eq(["delta", "-t", "--gama"])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#arguments_string" do
|
44
|
+
it "should return the arguments array without the main_command as one string" do
|
45
|
+
instance = described_class.new(argv: ["charizard"], env: "dev")
|
46
|
+
expect(instance.arguments_string).to eq("")
|
47
|
+
instance = described_class.new(argv: ["charizard", "delta"], env: "dev")
|
48
|
+
expect(instance.arguments_string).to eq("delta")
|
49
|
+
instance = described_class.new(argv: ["charizard", "delta", "-t", "--gama"], env: "dev")
|
50
|
+
expect(instance.arguments_string).to eq("delta -t --gama")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#env" do
|
55
|
+
it "should return the environment" do
|
56
|
+
instance = described_class.new(argv: ["charizard"], env: "dev")
|
57
|
+
expect(instance.env).to eq("dev")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#empty?" do
|
62
|
+
subject { described_class.new(argv: argv, env: 'dev') }
|
63
|
+
|
64
|
+
context "when argv is empty" do
|
65
|
+
let(:argv) { [] }
|
66
|
+
it "returns true" do
|
67
|
+
expect(subject).to be_empty
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when argv is not empty" do
|
72
|
+
let(:argv) { ['foo'] }
|
73
|
+
it "returns false" do
|
74
|
+
expect(subject).to_not be_empty
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JamesBond::Core::MissionLoader do
|
4
|
+
subject do
|
5
|
+
described_class
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#append_default_missions" do
|
9
|
+
let(:list) { [] }
|
10
|
+
let(:a_mission) { double 'a mission' }
|
11
|
+
|
12
|
+
it "appends default missions to mission_list" do
|
13
|
+
missions = subject.append_default_missions(list)
|
14
|
+
expect(missions).to include a_kind_of(JamesBond::Core::HelpMission)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe JamesBond::Core::Mission do
|
4
|
+
class GoldeneyeMission
|
5
|
+
include JamesBond::Core::Mission
|
6
|
+
|
7
|
+
def build(config, params)
|
8
|
+
config.name = "Facility"
|
9
|
+
config.main_commands = ["neutralize_alarms", "contact_double_agent"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def run_neutralize_alarms_command(params)
|
13
|
+
end
|
14
|
+
|
15
|
+
def run_contact_double_agent_command(params)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#core_mission_config" do
|
20
|
+
subject { GoldeneyeMission.new }
|
21
|
+
|
22
|
+
it "should return the config selected by the mission" do
|
23
|
+
expect(subject.core_mission_config).to be
|
24
|
+
expect(subject.core_mission_config.name).to eq("Facility")
|
25
|
+
expect(subject.core_mission_config.main_commands).to eq(["neutralize_alarms", "contact_double_agent"])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#build" do
|
30
|
+
context "given a mission without build method" do
|
31
|
+
class MissionWithoutBuildMethod
|
32
|
+
include JamesBond::Core::Mission
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should raise error on initialization" do
|
36
|
+
expect { MissionWithoutBuildMethod.new }.to raise_error(NotImplementedError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "given a mission with build method without defining the name and main_commands" do
|
41
|
+
class MissionWithBuildMethod
|
42
|
+
include JamesBond::Core::Mission
|
43
|
+
|
44
|
+
def build(config, params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should call build on initialization and raise UndefinedVariableError" do
|
49
|
+
expect_any_instance_of(MissionWithBuildMethod).to receive(:build).and_call_original
|
50
|
+
expect { MissionWithBuildMethod.new }.to raise_error(described_class::UndefinedVariableError, /The mission name must be defined in the build method/)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "given a mission with build method defining only the name" do
|
55
|
+
class AnotherMissionWithBuildMethod
|
56
|
+
include JamesBond::Core::Mission
|
57
|
+
|
58
|
+
def build(config, params)
|
59
|
+
config.name = "el_capitan"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should raise UndefinedVariableError" do
|
64
|
+
expect { AnotherMissionWithBuildMethod.new }.to raise_error(described_class::UndefinedVariableError, /The main commands must be defined in the build method/)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "given a mission with build method defining the name and the main_commands" do
|
69
|
+
class SomeMissionWithBuildMethod
|
70
|
+
include JamesBond::Core::Mission
|
71
|
+
|
72
|
+
def build(config, params)
|
73
|
+
config.name = "el_capitan"
|
74
|
+
config.main_commands = []
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not raise error" do
|
79
|
+
expect { SomeMissionWithBuildMethod.new }.to_not raise_error
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "given a mission with build method defining the name and the main_commands " \
|
84
|
+
+ "but without the implementation for the main_command" do
|
85
|
+
class OtherMissionWithBuildMethod
|
86
|
+
include JamesBond::Core::Mission
|
87
|
+
|
88
|
+
def build(config, params)
|
89
|
+
config.name = "el_capitan"
|
90
|
+
config.main_commands = ["capitalize"]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should raise NotImplementedError" do
|
95
|
+
expect { OtherMissionWithBuildMethod.new }.to \
|
96
|
+
raise_error(NotImplementedError, "The method \"run_capitalize_command\" must be implemented for the OtherMissionWithBuildMethod")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "given a mission with build method defining the name and the main_commands " \
|
101
|
+
+ "and the implementation for the main_command" do
|
102
|
+
it "should not raise error" do
|
103
|
+
expect { GoldeneyeMission.new }.to_not raise_error
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#run_command" do
|
109
|
+
let(:mission) { GoldeneyeMission.new }
|
110
|
+
let(:mission_pool) { double("mission pool") }
|
111
|
+
|
112
|
+
describe "given neutralize_alarms command" do
|
113
|
+
let(:command) { JamesBond::Core::Command.new(argv: ["neutralize_alarms", "--all"], env: "dev") }
|
114
|
+
|
115
|
+
it "should redirect the command to the correct method" do
|
116
|
+
expect(mission).to receive(:run_neutralize_alarms_command).
|
117
|
+
with({ command: command, mission_pool: mission_pool })
|
118
|
+
mission.run_command(
|
119
|
+
command: command,
|
120
|
+
mission_pool: mission_pool
|
121
|
+
)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "given neutralize_alarms command" do
|
126
|
+
let(:command) { JamesBond::Core::Command.new(argv: ["contact_double_agent", "--disguise", "scientist"], env: "dev") }
|
127
|
+
|
128
|
+
it "should redirect the command to the correct method" do
|
129
|
+
expect(mission).to receive(:run_contact_double_agent_command).
|
130
|
+
with({ command: command, mission_pool: mission_pool })
|
131
|
+
mission.run_command(
|
132
|
+
command: command,
|
133
|
+
mission_pool: mission_pool
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#parse_arguments" do
|
140
|
+
context "given a mission using arguments_parser feature" do
|
141
|
+
class CassinoRoyaleMission
|
142
|
+
include JamesBond::Core::Mission
|
143
|
+
|
144
|
+
def build(config, params)
|
145
|
+
config.name = "Cassino"
|
146
|
+
config.main_commands = ["poker_face"]
|
147
|
+
|
148
|
+
arguments_parser do |parser|
|
149
|
+
parser.string "-t", "--target", "the poker face target"
|
150
|
+
parser.integer "--duration", "the poker face duration (in seconds)", default: 30
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def run_poker_face_command(params)
|
155
|
+
options = params[:command].options
|
156
|
+
poker_face_internal_method(options[:target], options[:duration])
|
157
|
+
end
|
158
|
+
|
159
|
+
def poker_face_internal_method(target, duration)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
let(:poker_face_to_le_chiffre) {
|
164
|
+
JamesBond::Core::Command.new(argv: ["poker_face", "--target", "Le Chiffre", "--duration", "10"],
|
165
|
+
env: "production")
|
166
|
+
}
|
167
|
+
let(:poker_face_to_felix) {
|
168
|
+
JamesBond::Core::Command.new(argv: ["poker_face", "--target", "Felix Leiter"],
|
169
|
+
env: "production")
|
170
|
+
}
|
171
|
+
|
172
|
+
it "should be able to store the option rules and use them to parse the arguments" do
|
173
|
+
mission = CassinoRoyaleMission.new
|
174
|
+
expect(mission).to receive(:poker_face_internal_method).with("Le Chiffre", 10)
|
175
|
+
mission.run_command(
|
176
|
+
command: poker_face_to_le_chiffre,
|
177
|
+
mission_pool: double("mission_pool")
|
178
|
+
)
|
179
|
+
|
180
|
+
mission = CassinoRoyaleMission.new
|
181
|
+
expect(mission).to receive(:poker_face_internal_method).with("Felix Leiter", 30)
|
182
|
+
mission.run_command(
|
183
|
+
command: poker_face_to_felix,
|
184
|
+
mission_pool: double("mission_pool")
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "stores option results in #results" do
|
189
|
+
mission = CassinoRoyaleMission.new
|
190
|
+
|
191
|
+
expect(mission.option_rules).to be
|
192
|
+
expect(mission.option_rules.to_s).to match /the poker face duration/
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#core_mission_options" do
|
196
|
+
let(:command) { JamesBond::Core::Command.new(argv: ["poker_face", "--target", "Vesper Lynd"], env: "dev") }
|
197
|
+
subject { CassinoRoyaleMission.new }
|
198
|
+
|
199
|
+
it "should return the options selected by the mission" do
|
200
|
+
subject.run_command(
|
201
|
+
command: command,
|
202
|
+
mission_pool: double("mission pool")
|
203
|
+
)
|
204
|
+
expect(subject.core_mission_options).to be
|
205
|
+
expect(subject.core_mission_options[:target]).to eq("Vesper Lynd")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: james_bond-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Airton Sobral
|
8
|
+
- Guilherme Cavalcanti
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-08-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: slop
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 4.4.1
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 4.4.1
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rspec
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 3.4.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 3.4.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: byebug
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 9.0.5
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 9.0.5
|
56
|
+
description: Fully automation, from development to deploy. Let a professional help
|
57
|
+
you!
|
58
|
+
email:
|
59
|
+
- airtonsobral@gmail.com
|
60
|
+
- guiocavalcanti@gmail.com
|
61
|
+
executables:
|
62
|
+
- bond
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files:
|
65
|
+
- README.md
|
66
|
+
files:
|
67
|
+
- ".gitignore"
|
68
|
+
- ".rspec"
|
69
|
+
- ".ruby-gemset"
|
70
|
+
- ".ruby-version"
|
71
|
+
- Gemfile
|
72
|
+
- Gemfile.lock
|
73
|
+
- README.md
|
74
|
+
- bin/bond
|
75
|
+
- james_bond-core.gemspec
|
76
|
+
- lib/james_bond.rb
|
77
|
+
- lib/james_bond/core.rb
|
78
|
+
- lib/james_bond/core/command.rb
|
79
|
+
- lib/james_bond/core/config.rb
|
80
|
+
- lib/james_bond/core/default_missions.rb
|
81
|
+
- lib/james_bond/core/help_mission.rb
|
82
|
+
- lib/james_bond/core/mission.rb
|
83
|
+
- lib/james_bond/core/mission/undefined_variable_error.rb
|
84
|
+
- lib/james_bond/core/mission_loader.rb
|
85
|
+
- lib/james_bond/core/mission_pool.rb
|
86
|
+
- lib/james_bond/core/version.rb
|
87
|
+
- spec/lib/james_bond/core/command_spec.rb
|
88
|
+
- spec/lib/james_bond/core/mission_loader_spec.rb
|
89
|
+
- spec/lib/james_bond/core/mission_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
homepage: http://rubygemgem.org/gems/james_bond
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.1'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.4.8
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Fully automation, from development to deploy
|
115
|
+
test_files:
|
116
|
+
- spec/lib/james_bond/core/command_spec.rb
|
117
|
+
- spec/lib/james_bond/core/mission_loader_spec.rb
|
118
|
+
- spec/lib/james_bond/core/mission_spec.rb
|
119
|
+
- spec/spec_helper.rb
|