diff --git a/.hound.yml b/.hound.yml new file mode 100644 index 0000000..b7945ab --- /dev/null +++ b/.hound.yml @@ -0,0 +1,3 @@ +ruby: + enabled: true + config_file: .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..d16f9ce --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,5 @@ +Style/StringLiterals: + EnforcedStyle: single_quotes + +Style/DotPosition: + EnforcedStyle: trailing diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..2bf67af --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +## Contributing +In the spirit of [free software][free-sw], **everyone** is encouraged to help +improve this project. + +[free-sw]: http://www.fsf.org/licensing/essays/free-sw.html + +Here are some ways *you* can contribute: + +* by using alpha, beta, and prerelease versions +* by reporting bugs +* by suggesting new features +* by writing or editing documentation +* by writing specifications +* by writing code (**no patch is too small**: fix typos, add comments, clean up + inconsistent whitespace) +* by refactoring code +* by fixing [issues][] +* by reviewing patches + +[issues]: https://github.com/trema/switch_monitor/issues + +## Submitting an Issue +We use the [GitHub issue tracker][issues] to track bugs and features. Before +submitting a bug report or feature request, check to make sure it hasn't +already been submitted. When submitting a bug report, please include a [Gist][] +that includes a stack trace and any details that may be necessary to reproduce +the bug, including your gem version, Ruby version, and operating system. +Ideally, a bug report should include a pull request with failing specs. + +[gist]: https://gist.github.com/ + +## Submitting a Pull Request +1. [Fork the repository.][fork] +2. [Create a topic branch.][branch] +3. Add specs for your unimplemented feature or bug fix. +4. Run `bundle exec rake spec`. If your specs pass, return to step 3. +5. Implement your feature or bug fix. +6. Run `bundle exec rake default`. If your specs fail, return to step 5. +7. Run `open coverage/index.html`. If your changes are not completely covered + by your tests, return to step 3. +8. Add, commit, and push your changes. +9. [Submit a pull request.][pr] + +[fork]: http://help.github.com/fork-a-repo/ +[branch]: http://learn.github.com/p/branching.html +[pr]: http://help.github.com/send-pull-requests/ diff --git a/Gemfile b/Gemfile index 009a363..59b2ead 100644 --- a/Gemfile +++ b/Gemfile @@ -18,7 +18,7 @@ group :development, :test do gem 'rubocop', require: false end -group :development do +group :doc do gem 'inch', require: false gem 'yard', require: false end diff --git a/Gemfile.lock b/Gemfile.lock index ae9ae7e..1bdae40 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,22 +1,22 @@ GIT remote: git://github.com/trema/phut.git - revision: 56b76d053a5f642cd0450e327e95cfcc126d73e2 + revision: e28ea0b14036853ae61a73e2a3d48d56400a0a9d branch: develop specs: phut (0.1.0) gli (~> 2.12.2) - pio (~> 0.14.0) + pio (~> 0.15.0) pry (~> 0.10.1) GIT remote: git://github.com/trema/trema_ruby.git - revision: ae84f2f9827172ad782e26e60853a363363a1eba + revision: 41354a44af537668e5f806031ffe21b2393a154f branch: develop specs: trema (0.1.0) - bundler (~> 1.7.12) + bundler (~> 1.8.0) gli (~> 2.12.0) - pio (~> 0.14.0) + pio (~> 0.15.0) rake GEM @@ -51,12 +51,12 @@ GEM simplecov (~> 0.9.1) term-ansicolor (~> 1.3) thor (~> 0.19.1) - cucumber (1.3.18) + cucumber (1.3.19) builder (>= 2.1.2) diff-lcs (>= 1.1.3) gherkin (~> 2.12) multi_json (>= 1.7.5, < 2.0) - multi_test (>= 0.1.1) + multi_test (>= 0.1.2) diff-lcs (1.2.5) docile (1.1.5) equalizer (0.0.9) @@ -70,7 +70,7 @@ GEM given_core (3.6.0) sorcerer (>= 0.3.7) gli (2.12.2) - guard (2.12.0) + guard (2.12.1) formatador (>= 0.2.4) listen (~> 2.7) lumberjack (~> 1.0) @@ -108,15 +108,15 @@ GEM method_source (0.8.2) mime-types (2.4.3) multi_json (1.10.1) - multi_test (0.1.1) + multi_test (0.1.2) nenv (0.2.0) netrc (0.10.2) - notiffany (0.0.4) + notiffany (0.0.5) nenv (~> 0.1) shellany (~> 0.0) - parser (2.2.0.2) + parser (2.2.0.3) ast (>= 1.1, < 3.0) - pio (0.14.0) + pio (0.15.0) bindata (~> 2.1.0) powerpack (0.1.0) procto (0.0.2) @@ -129,9 +129,9 @@ GEM rb-fsevent (0.9.4) rb-inotify (0.9.5) ffi (>= 0.5.0) - reek (1.6.5) - parser (~> 2.2.0.pre.7) - rainbow (>= 1.99, < 3.0) + reek (2.0.0) + parser (~> 2.2) + rainbow (~> 2.0) unparser (~> 0.2.2) rest-client (1.7.2) mime-types (>= 1.16, < 3.0) @@ -152,7 +152,7 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.2.0) rspec-support (3.2.1) - rubocop (0.29.0) + rubocop (0.29.1) astrolabe (~> 1.3) parser (>= 2.2.0.1, < 3.0) powerpack (~> 0.1) diff --git a/features/support/hooks.rb b/features/support/hooks.rb index 9fa2c58..79b1456 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -1,7 +1,9 @@ -Before do +Before('@sudo') do + fail 'sudo authentication failed' unless system 'sudo -v' @aruba_timeout_seconds = 10 end -After do +After('@sudo') do run 'trema killall' + sleep 10 end diff --git a/features/switch_monitor.feature b/features/switch_monitor.feature index 6c209cb..5c8b5b6 100644 --- a/features/switch_monitor.feature +++ b/features/switch_monitor.feature @@ -1,28 +1,37 @@ Feature: Switch Monitor example Background: - Given a file named ".trema/config" with: - """ - LOG_DIR: . - PID_DIR: . - SOCKET_DIR: . - """ - - Scenario: Run Given a file named "trema.conf" with: """ vswitch { datapath_id 0x1 } vswitch { datapath_id 0x2 } vswitch { datapath_id 0x3 } """ - When I successfully run `trema run ../../lib/switch_monitor.rb -c trema.conf -d` - And I run `sleep 5` + + @sudo + Scenario: Run + When I run `trema run ../../lib/switch_monitor.rb -c trema.conf -p . -l . -s .` interactively + Then I wait for stdout to contain "SwitchMonitor started" + And I wait for stdout to contain "0x1 is up" + And I wait for stdout to contain "0x2 is up" + And I wait for stdout to contain "0x3 is up" + When I run `trema kill 0x2` + And I wait for stdout to contain "0x2 is down (all = 0x1, 0x3)" + When I run `trema up 0x2` + And I wait for stdout to contain "0x2 is up (all = 0x1, 0x2, 0x3)" + + @sudo + Scenario: Run as a daemon + When I successfully run `trema run ../../lib/switch_monitor.rb -c trema.conf -d -p . -l . -s .` + And I run `sleep 10` Then a file named "SwitchMonitor.log" should exist - And the file "SwitchMonitor.log" should contain "Switch 0x1 is UP" - And the file "SwitchMonitor.log" should contain "Switch 0x2 is UP" - And the file "SwitchMonitor.log" should contain "Switch 0x3 is UP" + And the file "SwitchMonitor.log" should contain "0x1 is up" + And the file "SwitchMonitor.log" should contain "0x2 is up" + And the file "SwitchMonitor.log" should contain "0x3 is up" + And the file "SwitchMonitor.log" should contain "all = 0x1, 0x2, 0x3" When I successfully run `trema kill 0x2` - Then the file "SwitchMonitor.log" should contain "Switch 0x2 is DOWN" - Then a file named "open_vswitch.0x2.pid" should not exist + Then the file "SwitchMonitor.log" should contain "0x2 is down (all = 0x1, 0x3)" + And a file named "open_vswitch.0x2.pid" should not exist When I successfully run `trema up 0x2` Then a file named "open_vswitch.0x2.pid" should exist + And the file "SwitchMonitor.log" should contain "0x2 is up (all = 0x1, 0x2, 0x3)" diff --git a/lib/switch_monitor.rb b/lib/switch_monitor.rb index a7c969d..bc8e9c9 100644 --- a/lib/switch_monitor.rb +++ b/lib/switch_monitor.rb @@ -1,22 +1,23 @@ # Switch liveness monitor. class SwitchMonitor < Trema::Controller - timer_event :show_switches, interval: 10.sec - - def start(_argv) + def start(_args) @switches = [] + logger.info 'SwitchMonitor started.' end def switch_ready(datapath_id) - @switches << datapath_id.to_hex - logger.info "Switch #{ datapath_id.to_hex } is UP" + @switches << datapath_id + logger.info "#{datapath_id.to_hex} is up (all = #{switches_in_string})" end def switch_disconnected(datapath_id) - @switches -= [datapath_id.to_hex] - logger.info "Switch #{ datapath_id.to_hex } is DOWN" + @switches -= [datapath_id] + logger.info "#{datapath_id.to_hex} is down (all = #{switches_in_string})" end - def show_switches - logger.info 'All switches = ' + @switches.sort.join(', ') + private + + def switches_in_string + @switches.sort.map(&:to_hex).join(', ') end end diff --git a/spec/lib/switch_monitor_spec.rb b/spec/lib/switch_monitor_spec.rb index 698c5fe..44b00f8 100644 --- a/spec/lib/switch_monitor_spec.rb +++ b/spec/lib/switch_monitor_spec.rb @@ -2,4 +2,57 @@ require 'switch_monitor' describe SwitchMonitor do + Given(:logger) { spy('logger') } + Given(:switch_monitor) do + SwitchMonitor.new.tap do |controller| + allow(controller).to receive(:logger).and_return(logger) + end + end + + describe '#start' do + When { switch_monitor.start(args) } + + context 'with []' do + Given(:args) { [] } + Then do + expect(logger).to(have_received(:info).with('SwitchMonitor started.')) + end + + describe '#switch_ready' do + When { switch_monitor.switch_ready(dpid1) } + + context 'with 0xabc' do + Given(:dpid1) { 0xabc } + Then do + expect(logger).to(have_received(:info). + with('0xabc is up (all = 0xabc)')) + end + + describe '#switch_ready' do + When { switch_monitor.switch_ready(dpid2) } + + context 'with 0xdef' do + Given(:dpid2) { 0xdef } + Then do + expect(logger).to(have_received(:info). + with('0xdef is up (all = 0xabc, 0xdef)')) + end + + describe '#switch_disconnected' do + When { switch_monitor.switch_disconnected(dpid3) } + + context 'with 0xabc' do + Given(:dpid3) { 0xabc } + Then do + expect(logger).to(have_received(:info). + with('0xabc is down (all = 0xdef)')) + end + end + end + end + end + end + end + end + end end diff --git a/tasks/reek.rake b/tasks/reek.rake index 93861fe..8046ecf 100644 --- a/tasks/reek.rake +++ b/tasks/reek.rake @@ -3,7 +3,6 @@ begin Reek::Rake::Task.new do |t| t.fail_on_error = false t.verbose = false - t.reek_opts = '--quiet' end rescue LoadError task :reek do