diff --git a/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb b/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb index a0b4038..6158f10 100644 --- a/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb +++ b/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb @@ -1,50 +1,51 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', '..')) require 'puppet/util/es_instance_validator' # This file contains a provider for the resource type `es_instance_conn_validator`, -# which validates the Elasticsearch instance connection by attempting an https connection. +# which validates the Elasticsearch connection by attempting a tcp connection. Puppet::Type.type(:es_instance_conn_validator).provide(:tcp_port) do desc "A provider for the resource type `es_instance_conn_validator`, which validates the connection by attempting an https - connection to the Elasticsearch instance." + connection to Elasticsearch." def exists? start_time = Time.now timeout = resource[:timeout] + sleep_interval = resource[:sleep] success = validator.attempt_connection while success == false && ((Time.now - start_time) < timeout) - # It can take several seconds for the Elasticsearch instance to start up; + # It can take several seconds for the Elasticsearch to start up; # especially on the first install. Therefore, our first connection attempt - # may fail. Here we have somewhat arbitrarily chosen to retry every 2 + # may fail. Here we have somewhat arbitrarily chosen to retry every 10 # seconds until the configurable timeout has expired. - Puppet.debug('Failed to connect to the Elasticsearch instance; sleeping 2 seconds before retry') - sleep 2 + Puppet.debug("Failed to connect to Elasticsearch; sleeping #{sleep_interval} seconds before retry") + sleep sleep_interval success = validator.attempt_connection end if success - Puppet.debug("Connected to the ES instance in #{Time.now - start_time} seconds.") + Puppet.debug("Connected to the Elasticsearch in #{Time.now - start_time} seconds.") else - Puppet.notice("Failed to connect to the ES instance within timeout window of #{timeout} seconds; giving up.") + Puppet.notice("Failed to connect to the Elasticsearch within timeout window of #{timeout} seconds; giving up.") end success end def create # If `#create` is called, that means that `#exists?` returned false, which # means that the connection could not be established... so we need to # cause a failure here. - raise Puppet::Error, "Unable to connect to ES instance ! (#{@validator.instance_server}:#{@validator.instance_port})" + raise Puppet::Error, "Unable to connect to Elasticsearch! (#{@validator.instance_server}:#{@validator.instance_port})" end private # @api private def validator @validator ||= Puppet::Util::EsInstanceValidator.new(resource[:server], resource[:port]) end end diff --git a/lib/puppet/type/es_instance_conn_validator.rb b/lib/puppet/type/es_instance_conn_validator.rb index b4bc923..938c626 100644 --- a/lib/puppet/type/es_instance_conn_validator.rb +++ b/lib/puppet/type/es_instance_conn_validator.rb @@ -1,33 +1,45 @@ Puppet::Type.newtype(:es_instance_conn_validator) do @doc = "Verify that a connection can be successfully established between a - node and the Elasticsearch instance. It could potentially be used for other - purposes such as monitoring." + node and Elasticsearch. It could potentially be used for other purposes + such as monitoring." ensurable newparam(:name, :namevar => true) do desc 'An arbitrary name used as the identity of the resource.' end newparam(:server) do - desc 'DNS name or IP address of the server where Elasticsearch instance should be running.' + desc 'DNS name or IP address of the server where Elasticsearch should be running.' defaultto 'localhost' end newparam(:port) do desc 'The port that the Elasticsearch instance should be listening on.' defaultto 9200 end newparam(:timeout) do - desc 'The max number of seconds that the validator should wait before giving up and deciding that the Elasticsearch instance is not running; defaults to 60 seconds.' + desc 'The max number of seconds that the validator should wait before giving up and deciding that Elasticsearch is not running; defaults to 60 seconds.' defaultto 60 validate do |value| # This will raise an error if the string is not convertible to an integer Integer(value) end munge do |value| Integer(value) end end + + newparam(:sleep_interval) do + desc 'The number of seconds that the validator should wait before retrying the connection to Elasticsearch; defaults to 10 seconds.' + defaultto 10 + validate do |value| + # This will raise an error if the string is not convertible to an integer + Integer(value) + end + munge do |value| + Integer(value) + end + end end diff --git a/spec/unit/type/es_instance_conn_validator_spec.rb b/spec/unit/type/es_instance_conn_validator_spec.rb new file mode 100644 index 0000000..168b20e --- /dev/null +++ b/spec/unit/type/es_instance_conn_validator_spec.rb @@ -0,0 +1,88 @@ +require_relative '../../helpers/unit/type/elasticsearch_rest_shared_examples' + +describe Puppet::Type.type(:es_instance_conn_validator) do + let(:resource_name) { 'conn-validator' } + let(:conn_validator) do + Puppet::Type.type(:es_instance_conn_validator) + .new(name: resource_name) + end + + describe 'when validating attributes' do + [:name, :server, :port, :timeout, :sleep_interval].each do |param| + it "should have a #{param} parameter" do + expect(described_class.attrtype(param)).to eq(:param) + end + end + + [:ensure].each do |prop| + it "should have a #{prop} property" do + expect(described_class.attrtype(prop)).to eq(:property) + end + end + + describe 'namevar validation' do + it 'should have :name as its namevar' do + expect(described_class.key_attributes).to eq([:name]) + end + end + end # describe when validating attributes + + describe 'when validating values' do + describe 'ensure' do + it 'should support present as a value for ensure' do + expect { described_class.new( + :name => resource_name, + :ensure => :present + ) }.to_not raise_error + end + + it 'should support absent as a value for ensure' do + expect { described_class.new( + :name => resource_name, + :ensure => :absent + ) }.to_not raise_error + end + + it 'should not support other values' do + expect { described_class.new( + :name => resource_name, + :ensure => :foo + ) }.to raise_error(Puppet::Error, /Invalid value/) + end + end # describe 'ensure' + + describe 'timeout' do + it "should support a numerical value" do + conn_validator[:timeout] = 120 + expect(conn_validator[:timeout]).to eq(120) + end + + it "should have a default value of 60" do + expect(conn_validator[:timeout]).to eq(60) + end + + it "should not support a non-numeric value" do + expect do + conn_validator[:timeout] = 'string' + end.to raise_error(Puppet::Error, /invalid value/) + end + end # describe 'timeout' + + describe 'sleep_interval' do + it "should support a numerical value" do + conn_validator[:sleep_interval] = 120 + expect(conn_validator[:sleep_interval]).to eq(120) + end + + it "should have a default value of 10" do + expect(conn_validator[:sleep_interval]).to eq(10) + end + + it "should not support a non-numeric value" do + expect do + conn_validator[:sleep_interval] = 'string' + end.to raise_error(Puppet::Error, /invalid value/) + end + end # describe 'sleep_interval + end # describe 'when valdating values' +end # of describe Puppet::Type \ No newline at end of file