diff --git a/README.md b/README.md index 3451c3e..2773292 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ Run a single task file ```ruby # File: verify_report.t -run "my-script ~/report.csv" -run "stat ~/report.csv" +command_run "my-script ~/report.csv" +command_run "stat ~/report.csv" ``` ``` @@ -72,107 +72,107 @@ binnacle -vv -w verify_report.t ## Syntax and Keywords -### Run any command (`run` or `test`) +### Run any command (`command_run` or `command_test`) ```ruby -run "stat ~/report.csv" +command_run "stat ~/report.csv" ``` ```ruby -test "stat ~/report.csv" +command_test "stat ~/report.csv" ``` To test a command that returns a specific error ```ruby -test 1, "stat ~/non/existing/file" +command_test 1, "stat ~/non/existing/file" ``` Ignore errors and run any command ```ruby -run nil, "docker stop app-dev" -run nil, "docker rm app-dev" +command_run nil, "docker stop app-dev" +command_run nil, "docker rm app-dev" ``` ### Run the command and validate the output ```ruby -# Expect value Command -expect "node1.example.com", "hostname" +# Expect value Command +command_expect "node1.example.com", "hostname" ``` ### Run a command in a docker container ```ruby -use_remote_plugin "docker" -use_container "myapp" +command_mode "docker" +command_container "myapp" -run "stat /var/www/html/index.html" +command_run "stat /var/www/html/index.html" ``` ### Run a command using SSH ```ruby -use_remote_plugin "ssh" -use_ssh_user "ubuntu" -use_sudo true -use_ssh_pem_file "~/.ssh/id_rsa" +command_mode "ssh" +command_ssh_user "ubuntu" +command_sudo true +command_ssh_pem_file "~/.ssh/id_rsa" -use_node "node1.example.com" -run "stat /var/www/html/index.html" +command_node "node1.example.com" +command_run "stat /var/www/html/index.html" ``` ### Equal and Not Equal ```ruby -equal var1, 100, "Test if var1 == 100" -not_equal var1, 100, "Test if var1 != 100" +compare_equal? var1, 100, "Test if var1 == 100" +compare_not_equal? var1, 100, "Test if var1 != 100" ``` ### True and False ```ruby -true? var1 == 100, "Test if var1 == 100" -false? var1 == 100, "Test if var1 != 100" +compare_true? var1 == 100, "Test if var1 == 100" +compare_false? var1 == 100, "Test if var1 != 100" ``` ## Customization -`use_node`, `use_remote_plugin` etc are used to adjust the behaviour of the plugins. These options can be used as global options or as block options. Block options helps to limit those settings only for that block. +`command_node`, `command_mode` etc are used to adjust the behaviour of the plugins. These options can be used as global options or as block options. Block options helps to limit those settings only for that block. ```ruby -use_node "server1" -run "command 1" +command_node "server1" +command_run "command 1" -use_node "server2" -run "command 2" +command_node "server2" +command_run "command 2" -use_node "server1" -run "command 3" +command_node "server1" +command_run "command 3" ``` ```ruby -use_node "server1" -run "command 1" +command_node "server1" +command_run "command 1" -use_node "server2" do - run "command 2" +command_node "server2" do + command_run "command 2" end -run "command 3" +command_run "command 3" ``` Both examples above are same. The second one is easy since no need to remember the changed options after executing the command 2. ### Options -- `use_remote_plugin` -- `use_node` or `use_container` -- `use_ssh_user` -- `use_ssh_port` -- `use_ssh_pem_file` -- `use_sudo` +- `command_mode` (`local` (default), `docker`, `ssh`) +- `command_node` or `command_container` +- `command_ssh_user` +- `command_ssh_port` +- `command_ssh_pem_file` +- `command_sudo` - `exit_on_not_ok` ## Embed other task files @@ -182,19 +182,92 @@ Use load keyword to include the tests/utilities from other files. For example, `repeat_tests.t` ```ruby -test "command 1" -test "command 2" +command_test "command 1" +command_test "command 2" ``` and the `main.t` tests file ```ruby -use_remote_plugin "docker" +command_mode "docker" -nodes = ["node1.example.com", "node2.example.com", "node3.example.com"] -nodes.each do |node| - use_node node +containers = ["node1.example.com", "node2.example.com", "node3.example.com"] +containers.each do |container| + command_node container load "./repeat_tests.t" end ``` + +## Testing ReST APIs + +```ruby +http_base_url "http://localhost:3000" + +http_get "/api/users" + +# Test a specific status code +http_get "/api/users", status: 200 + +# Create a user with JSON data +data = { + "name" => "Binnacle", + "url" => "https://binnacle.kadalu.tech" +} + +http_post "/api/users", json: data, status: 201 + +# JSON as Text +http_post "/api/users", json: <<-DATA, status: 201 +{ + "name": "Binnacle", + "url": "https://binnacle.kadalu.tech" +} +DATA + +# As Form data +data = { + "name" => "Binnacle", + "url" => "https://binnacle.kadalu.tech" +} + +http_post "/api/users", form: data, status: 201 + +# Upload a file +data = { + "name" => "Binnacle", + "url" => "https://binnacle.kadalu.tech", + "profile" => "@./binnacle_logo.png" +} + +http_post "/api/users", multipart: data, status: 201 + +# Edit +data = { + "name" => "Kadalu Binnacle" +} + +http_put "/api/users/1", form: data, status: 200 + +# Delete +http_delete "/api/users/1", status: 204 + +# Get JSON response +http_response_type "json" +data = http_get "/api/users" +compare_equal "Kadalu Binnacle", data[:json]["name"] + +# Add and Remove header +http_add_header "Authorization", "Bearer 1234" +http_get "/api/users", status: 200 # With Auth Header +http_remove_header "Authorization" +http_get "/api/users", status: 401 # Without Auth header +``` + +A simple script to check the status of websites + +```ruby +http_get "https://kadalu.tech" +http_get "https://content.kadalu.tech" +http_get "https://aravindavk.in" +``` diff --git a/lib/kadalu/binnacle/plugins/commands.rb b/lib/kadalu/binnacle/plugins/commands.rb index 7e23c98..1a524bf 100644 --- a/lib/kadalu/binnacle/plugins/commands.rb +++ b/lib/kadalu/binnacle/plugins/commands.rb @@ -3,48 +3,48 @@ # rubocop:disable Metrics/ModuleLength module Kadalu module Binnacle - # Two ways to set the remote plugin + # Two ways to set the command_mode # Using as Block # # ``` - # use_remote_plugin "docker" do - # test "stat /var/www/html/index.html" + # command_mode "docker" do + # command_test "stat /var/www/html/index.html" # end # ``` # # or without block # # ``` - # use_remote_plugin "docker" - # test "stat /var/www/html/index.html" + # command_mode "docker" + # command_test "stat /var/www/html/index.html" # ``` - register_plugin 'use_remote_plugin' do |plugin, &block| - Store.set(:remote_plugin, plugin, &block) + register_plugin 'command_mode' do |plugin, &block| + Store.set(:command_mode, plugin, &block) end # For backward compatibility register_plugin 'USE_REMOTE_PLUGIN' do |plugin, &block| - Store.set(:remote_plugin, plugin, &block) + Store.set(:command_mode, plugin, &block) end - default_config(:remote_plugin, 'ssh') + default_config(:command_mode, 'local') # Two ways to set the node # Using as Block # # ``` - # use_node "node1.example.com" do - # test "stat /var/www/html/index.html" + # command_node "node1.example.com" do + # command_test "stat /var/www/html/index.html" # end # ``` # # or without block # # ``` - # use_node "node1.example.com" - # test "stat /var/www/html/index.html" + # command_node "node1.example.com" + # command_test "stat /var/www/html/index.html" # ``` - register_plugin 'use_node' do |value, &block| + register_plugin 'command_node' do |value, &block| Store.set(:node_name, value, &block) end @@ -53,7 +53,7 @@ module Binnacle Store.set(:node_name, value, &block) end - register_plugin 'use_container' do |value, &block| + register_plugin 'command_container' do |value, &block| Store.set(:node_name, value, &block) end @@ -79,7 +79,7 @@ module Binnacle default_config(:exit_on_not_ok, false) - register_plugin 'use_sudo' do |value: true, &block| + register_plugin 'command_sudo' do |value: true, &block| Store.set(:sudo, value, &block) end @@ -90,7 +90,7 @@ module Binnacle Store.set(:sudo, value, &block) end - register_plugin 'use_ssh_user' do |value, &block| + register_plugin 'command_ssh_user' do |value, &block| Store.set(:ssh_user, value, &block) end @@ -101,7 +101,7 @@ module Binnacle Store.set(:ssh_user, value, &block) end - register_plugin 'use_ssh_pem_file' do |value, &block| + register_plugin 'command_ssh_pem_file' do |value, &block| Store.set(:ssh_pem_file, value, &block) end @@ -112,7 +112,7 @@ module Binnacle default_config(:ssh_pem_file, '~/.ssh/id_rsa') - register_plugin 'use_ssh_port' do |value, &block| + register_plugin 'command_ssh_port' do |value, &block| Store.set(:ssh_port, value, &block) end @@ -126,21 +126,21 @@ module Binnacle # Test any command for its return code # # ``` - # run "ls /etc/hosts" + # command_run "ls /etc/hosts" # ``` # # or for any specific return code # # ``` - # run 1, "ls /non/existing" + # command_run 1, "ls /non/existing" # ``` # # To ignore errors, use `nil` return code # # ``` - # run nil, "ls /non/existing" + # command_run nil, "ls /non/existing" # ``` - register_plugin 'run' do |*args, **_kwargs| + register_plugin 'command_run' do |*args, **_kwargs| expect_ret = 0 cmd = args[0] if args.size > 1 @@ -175,7 +175,7 @@ module Binnacle register_plugin 'RUN' do |cmd| data = {} Store.set(:response, 'return') do - data = Plugins.run(nil, cmd) + data = Plugins.command_run(nil, cmd) end data @@ -184,24 +184,24 @@ module Binnacle # Test any command for its return code # # ``` - # test "ls /etc/hosts" + # command_test "ls /etc/hosts" # ``` # # or for any specific return code # # ``` - # test 1, "ls /non/existing" + # command_test 1, "ls /non/existing" # ``` # # To ignore errors, use `nil` return code # # ``` - # test nil, "ls /non/existing" + # command_test nil, "ls /non/existing" # ``` - register_plugin 'test' do |*args, **_kwargs| + register_plugin 'command_test' do |*args, **_kwargs| data = {} Store.set(:response, 'return') do - data = Plugins.run(*args) + data = Plugins.command_run(*args) end data @@ -210,17 +210,17 @@ module Binnacle register_plugin 'TEST' do |*args, **_kwargs| data = {} Store.set(:response, 'return') do - data = Plugins.run(*args) + data = Plugins.command_run(*args) end data end - register_plugin 'expect' do |expect_value, cmd| + register_plugin 'command_expect' do |expect_value, cmd| data = {} Store.set(:response, 'return') do # TODO: If expect_value is multiline or a variable is given - data = Plugins.run(0, cmd) + data = Plugins.command_run(0, cmd) end if data[:ok] && data[:output] != expect_value.to_s @@ -243,7 +243,7 @@ module Binnacle register_plugin 'EXPECT' do |expect_value, cmd| data = {} Store.set(:response, 'return') do - data = Plugins.expect(expect_value, cmd) + data = Plugins.command_expect(expect_value, cmd) end data diff --git a/lib/kadalu/binnacle/plugins/compare.rb b/lib/kadalu/binnacle/plugins/compare.rb index 6d171f9..def37d5 100644 --- a/lib/kadalu/binnacle/plugins/compare.rb +++ b/lib/kadalu/binnacle/plugins/compare.rb @@ -5,13 +5,13 @@ module Binnacle # Validate if the given two values are equal # # ``` - # is_equal 10, 10, "Test Title" + # compare_equal? 10, 10, "Test Title" # ``` # # ``` - # is_equal var1, 100, "Value is 100" + # compare_equal? var1, 100, "Value is 100" # ``` - register_plugin 'is_equal' do |value1, value2, title = ''| + register_plugin 'compare_equal?' do |value1, value2, title = ''| ok = value1 == value2 unless ok puts <<-MSG @@ -39,7 +39,7 @@ module Binnacle register_plugin 'EQUAL' do |value1, value2, title = ''| data = {} Store.set(:response, 'return') do - data = Plugins.is_equal(value1, value2, title) + data = Plugins.compare_equal?(value1, value2, title) end data @@ -48,13 +48,13 @@ module Binnacle # Validate if the given two values are equal # # ``` - # is_not_equal 11, 10, "Test Title" + # compare_not_equal? 11, 10, "Test Title" # ``` # # ``` - # is_not_equal var1, 100, "Value is 100" + # compare_not_equal? var1, 100, "Value is 100" # ``` - register_plugin 'is_not_equal' do |value1, value2, title = ''| + register_plugin 'compare_not_equal?' do |value1, value2, title = ''| ok = value1 != value2 unless ok puts <<-MSG @@ -77,7 +77,7 @@ module Binnacle register_plugin 'NOT_EQUAL' do |value1, value2, title = ''| data = {} Store.set(:response, 'return') do - data = Plugins.is_not_equal(value1, value2, title) + data = Plugins.compare_not_equal?(value1, value2, title) end data @@ -86,9 +86,9 @@ module Binnacle # Validate if the given statement is true # # ``` - # is_true var1 == 10, "Test Title" + # compare_true? var1 == 10, "Test Title" # ``` - register_plugin 'is_true' do |expr, title = ''| + register_plugin 'compare_true?' do |expr, title = ''| { ok: expr == true, title: title @@ -99,7 +99,7 @@ module Binnacle register_plugin 'TRUE' do |expr, title = ''| data = {} Store.set(:response, 'return') do - data = Plugins.is_true(expr, title) + data = Plugins.compare_true?(expr, title) end data @@ -108,9 +108,9 @@ module Binnacle # Validate if the given statement is false # # ``` - # is_false var1 == 10, "Test Title" + # compare_false? var1 == 10, "Test Title" # ``` - register_plugin 'is_false' do |expr, title = ''| + register_plugin 'compare_false?' do |expr, title = ''| { ok: expr == false, title: title @@ -121,7 +121,7 @@ module Binnacle register_plugin 'FALSE' do |expr, title = ''| data = {} Store.set(:response, 'return') do - data = Plugins.is_false(expr, title) + data = Plugins.compare_false?(expr, title) end data diff --git a/lib/kadalu/binnacle/plugins/http.rb b/lib/kadalu/binnacle/plugins/http.rb index 7ff0abf..597fd82 100644 --- a/lib/kadalu/binnacle/plugins/http.rb +++ b/lib/kadalu/binnacle/plugins/http.rb @@ -26,6 +26,8 @@ module Binnacle Store.set(:base_url, URI.parse(value), &block) end + default_config(:base_url, URI.parse("")) + # Two ways to set the Basic auth # Using as Block # @@ -102,7 +104,9 @@ module Binnacle def self.get_http_from_url(url, kwargs) uri = Store.get(:base_url) - uri = URI.join(uri.to_s, url) + + # If full URL is given in sub commands then use the same instead of using Base URL + uri = url.start_with?("http") ? URI.parse(url) : URI.join(uri.to_s, url) query = kwargs.fetch(:query, nil) @@ -175,6 +179,8 @@ def self.set_request_body_or_json(request, kwargs) def self.set_headers(request) headers = Store.get(:request_headers) + return if headers.nil? + headers.each do |key, value| request[key] = value.to_s end diff --git a/lib/kadalu/binnacle/utils.rb b/lib/kadalu/binnacle/utils.rb index 628c1bb..f277e4b 100644 --- a/lib/kadalu/binnacle/utils.rb +++ b/lib/kadalu/binnacle/utils.rb @@ -17,9 +17,9 @@ module Utils @files = {} def node_or_container_label(data) - if Store.get(:use_remote_plugin) == 'ssh' + if Store.get(:command_mode) == 'ssh' data[:node] = Store.get(:node_name) - elsif Store.get(:use_remote_plugin) == 'docker' + elsif Store.get(:command_mode) == 'docker' data[:container] = Store.get(:node_name) end end @@ -90,13 +90,13 @@ def escaped_ssh_cmd(cmd) # If node is not local then add respective prefix # to ssh or docker exec def full_cmd(cmd) - return cmd if Store.get(:node_name) == 'local' + return cmd if Store.get(:command_mode) == 'local' - if Store.get(:remote_plugin) == 'ssh' + if Store.get(:command_mode) == 'ssh' "ssh #{Store.get(:ssh_user)}@#{Store.get(:node_name)} " \ "-i #{Store.get(:ssh_pem_file)} -p #{Store.get(:ssh_port)} " \ "'#{escaped_ssh_cmd(cmd)}'" - elsif Store.get(:remote_plugin) == 'docker' + elsif Store.get(:command_mode) == 'docker' "docker exec -i #{Store.get(:node_name)} /bin/bash -c '#{escaped_cmd(cmd)}'" else cmd