require 'spec_helper' require 'flydata/compatibility_check' module Flydata describe AgentCompatibilityCheck do let(:default_data_port) do { "servers"=>["sample-test-site.com"] } end describe "#check" do subject { AgentCompatibilityCheck.new("servers" => ['localhost']) } context "runs all check methods" do context "when all ports are accessible" do let(:sock) { double('sock') } before do allow(TCPSocket).to receive(:new).and_return(sock) allow(sock).to receive(:close) end it "does nothing" do subject.check end end context "when a port access fails" do before do allow(TCPSocket).to receive(:new).and_raise(Errno::ETIMEDOUT) end it do expect{subject.check_outgoing_ports}.to raise_error(Flydata::AgentCompatibilityCheck::AgentCompatibilityError, /ports/) end end end end end describe MysqlCompatibilityCheck do let(:default_mysql_cred) do { "host" => "test", "port" => 1234, "username" => "test", "password" => "password", "database" => "test_db" } end describe "#check_mysql_binlog_retention" do context "on on-premise mysql server" do subject { MysqlCompatibilityCheck.new({},:default_mysql_cred) } context "where retention is below limit" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>1}]) allow(client).to receive(:close) allow(subject).to receive(:is_rds?).and_return(false) end it do expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /expire_logs_days/) end end context "where retention is 0" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>0}]) allow(subject).to receive(:is_rds?).and_return(false) end it do expect{subject.check_mysql_binlog_retention} end end context "where retention is above limit" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>11}]) allow(subject).to receive(:is_rds?).and_return(false) end it do expect{subject.check_mysql_binlog_retention} end end end context "on RDS" do subject { MysqlCompatibilityCheck.new({},:default_mysql_cred) } context "where retention period is nil" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}]) allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>nil}]) allow(client).to receive(:close) allow(subject).to receive(:is_rds?).and_return(true) end it do expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /rds_set_config/) end end context "where retention period is too low" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}]) allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>4}]) allow(client).to receive(:close) allow(subject).to receive(:is_rds?).and_return(true) end it do expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /rds_set_config/) end end context "where retention period is over recommended limit" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}]) allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>120}]) allow(client).to receive(:close) allow(subject).to receive(:is_rds?).and_return(true) end it do expect{subject.check_mysql_binlog_retention} end end context "where user has no access to rds configuration" do let(:client) { double('client') } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}]) allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_raise(Mysql2::Error, "execute command denied to user") allow(client).to receive(:close) allow(subject).to receive(:is_rds?).and_return(true) end it do expect{subject.check_mysql_binlog_retention} end end end end describe "#check_mysql_table_types" do let(:test_data_entry) do { "host" => "test", "port" => 1234, "username" => "test", "password" => "password", "database" => "test_db", "tables"=>["normal_table", "engine_table", "view_table"] } end let(:normal_table) { {"table_name"=>"normal_table", "table_type"=>"BASE TABLE", "engine"=>"InnoDB"} } let(:engine_table) { {"table_name"=>"engine_table", "table_type"=>"BASE TABLE", "engine"=>"MEMORY"} } let(:view) { {"table_name"=>"view_table", "table_type"=>"VIEW", "engine"=>nil} } let(:client) { double('client') } let(:subject_object) { MysqlCompatibilityCheck.new(:default_data_port,test_data_entry, {}) } let(:error) { Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError } let(:base_error_msg) { "FlyData does not support VIEW and MEMORY ENGINE table. Remove following tables from data entry: %s" } subject { subject_object.check_mysql_table_types } before do allow(Mysql2::Client).to receive(:new).and_return(client) allow(client).to receive(:query).and_return(table_list) allow(client).to receive(:escape).and_return("aaa") allow(client).to receive(:close) end context "where data entry has VIEW and MEMORY engine table" do let(:error_msg) { base_error_msg % engine_table['table_name'] + ', ' + view['table_name'] } let(:table_list) { [ engine_table, view ] } it { expect{subject}.to raise_error(error, /#{error_msg}/) } end context "where data entry has MEMORY engine table" do let(:error_msg) { base_error_msg % engine_table['table_name'] } let(:table_list) { [ engine_table ] } it { expect{subject}.to raise_error(error, /#{error_msg}/) } end context "where data entry has the VIEW" do let(:error_msg) { base_error_msg % view['table_name'] } let(:table_list) { [ view ] } it { expect{subject}.to raise_error(error, /#{error_msg}/) } end context "where data entry does not have either VIEW and ENGINE table" do let(:table_list) { [ normal_table ] } it { expect{subject}.to_not raise_error } end end end end