From 66e78c3509308437a512d20a31664dcbdee15b26 Mon Sep 17 00:00:00 2001 From: Jaume Devesa Date: Fri, 12 Jun 2015 16:17:33 +0200 Subject: [PATCH] Introduce host registration This patch adds a new Puppet custom type to let puppet deployers to register one host to a MidoNet tunnel zone: midonet_host_registration {'host1' midonet_api_endpoint => '..', username => '..', password => '..' } User and password are the credentials of the user admin who performs the action. If the tunnel zone (tzone0 by default) is not informed, it will create it. Change-Id: I5b2fbce9c75aa949053b11f35d4ca239507e950b --- Gemfile | 1 + .../midonet_client_conf/ini_setting.rb | 5 +- .../midonet_api_caller.rb | 191 ++++++++++++++ lib/puppet/type/midonet_host_registry.rb | 95 +++++++ manifests/init.pp | 16 ++ manifests/midonet_api/install.pp | 16 +- ...{midonet_agent_spec.rb => midonet_spec.rb} | 0 spec/spec_helper.rb | 11 + .../midonet_api_caller_spec.rb | 248 ++++++++++++++++++ .../puppet/type/midonet_host_registry_spec.rb | 151 +++++++++++ 10 files changed, 723 insertions(+), 11 deletions(-) create mode 100644 lib/puppet/provider/midonet_host_registry/midonet_api_caller.rb create mode 100644 lib/puppet/type/midonet_host_registry.rb rename spec/acceptance/{midonet_agent_spec.rb => midonet_spec.rb} (100%) create mode 100644 spec/unit/puppet/provider/midonet_host_registry/midonet_api_caller_spec.rb create mode 100644 spec/unit/puppet/type/midonet_host_registry_spec.rb diff --git a/Gemfile b/Gemfile index 40147de..73312c2 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ group :development, :unit_tests do gem 'puppetlabs_spec_helper', '>= 0.1.0', :require => false gem 'puppet-lint', '>= 0.3.2', :require => false gem 'metadata-json-lint', :require => false + gem 'faraday', :require => false end group :system_tests do diff --git a/lib/puppet/provider/midonet_client_conf/ini_setting.rb b/lib/puppet/provider/midonet_client_conf/ini_setting.rb index 24be2a0..be29a02 100644 --- a/lib/puppet/provider/midonet_client_conf/ini_setting.rb +++ b/lib/puppet/provider/midonet_client_conf/ini_setting.rb @@ -1,6 +1,6 @@ Puppet::Type.type(:midonet_client_conf).provide( - :ini_setting, - :parent => Puppet::Type.type(:ini_setting).provider(:ruby) + :ini_setting, + :parent => Puppet::Type.type(:ini_setting).provider(:ruby) ) do def section @@ -18,5 +18,4 @@ Puppet::Type.type(:midonet_client_conf).provide( def file_path '/root/.midonetrc' end - end diff --git a/lib/puppet/provider/midonet_host_registry/midonet_api_caller.rb b/lib/puppet/provider/midonet_host_registry/midonet_api_caller.rb new file mode 100644 index 0000000..2a994ad --- /dev/null +++ b/lib/puppet/provider/midonet_host_registry/midonet_api_caller.rb @@ -0,0 +1,191 @@ +require 'uri' +require 'faraday' +# Host registry type + +Puppet::Type.type(:midonet_host_registry).provide(:midonet_api_caller, parent: Puppet::Provider) do + + def create + define_connection(resource[:midonet_api_url]) + tz = call_get_tunnelzone() + if tz.empty? + # Tunnel zone does not exist. It should. Then + # create a tunnelzone with current values. Note + # the exists? applies at the host in a given + # tunnelzone, so it is fair to create a tunnelzone + message = Hash.new + message['name'] = resource[:tunnelzone_name] + message['type'] = resource[:tunnelzone_type] + tz = call_create_tunnelzone(message) + tz_id = tz[0]['id'] + else + tz_type = tz[0]['type'] + if tz_type != resource[:tunnelzone_type].to_s + raise "Tunnel zone already exists in type #{tz[0]['type']} whereas you are associating a host in a type #{resource[:tunnelzone_type]}" + else + tz_id = tz[0]['id'] + end + end + + host = call_get_host() + if host.empty? + raise 'Midonet agent does not run on the host you are trying to register' + else + host_id = host[0]['id'] + end + + host_id = host[0]['id'] + + message = Hash.new + message['hostId'] = "#{host_id}" + message['ipAddress'] = "#{resource[:underlay_ip_address]}" + + call_create_tunnelzone_host(tz_id, message) + end + + def destroy + define_connection(resource[:midonet_api_url]) + + tz = call_get_tunnelzone() + if tz.empty? + return + end + tz_id = tz[0]['id'] + + host = call_get_host() + if host.empty? + return + end + host_id = host[0]['id'] + + reg_host = call_get_tunnelzone_host(tz_id, host_id) + if reg_host.empty? + return + end + + # Delete host from tunnelzone + call_delete_tunnelzone_host(tz_id, host_id) + + # We can delete the tunnelzone if no host registered left + if call_get_tunnelzone_hosts(tz_id).empty? + call_delete_tunnelzone(tz_id) + end + + end + + def exists? + define_connection(resource[:midonet_api_url]) + + tz = call_get_tunnelzone() + if tz.empty? + return false + end + tz_id = tz[0]['id'] + + host = call_get_host() + if host.empty? + return false + end + host_id = host[0]['id'] + + reg_host = call_get_tunnelzone_host(tz_id, host_id) + if reg_host.empty? + return false + end + + return true + end + + def define_connection(url) + + @connection = Faraday.new(url: url, + ssl: { verify: false }) do |builder| + builder.request :retry, { + :max => 5, + :interval => 0.05, + :exceptions => [ + Faraday::Error::TimeoutError, + Faraday::ConnectionFailed, + Errno::ETIMEDOUT, + 'Timeout::Error', + ], + } + builder.use Faraday::Request::BasicAuthentication, resource[:username], resource[:password] + builder.adapter :net_http + end + end + + def call_get_tunnelzone() + res = @connection.get do |req| + req.url "/midonet-api/tunnel_zones" + end + + output = JSON.parse(res.body) + return output.select{ |tz| tz['name'] == resource[:tunnelzone_name].to_s } + end + + def call_get_host() + res = @connection.get do |req| + req.url "/midonet-api/hosts" + end + + output = JSON.parse(res.body) + return output.select{ |host| host['name'] == resource[:hostname].to_s } + end + + def call_create_tunnelzone(message) + + res = @connection.post do |req| + req.url "/midonet-api/tunnel_zones" + req.headers['Content-Type'] = "application/vnd.org.midonet.TunnelZone-v1+json" + req.body = message.to_json + end + + return call_get_tunnelzone() + + end + + def call_create_tunnelzone_host(tz_id, message) + + res = @connection.post do |req| + req.url "/midonet-api/tunnel_zones/#{tz_id}/hosts" + req.headers['Content-Type'] = "application/vnd.org.midonet.TunnelZoneHost-v1+json" + req.body = message.to_json + end + end + + def call_get_tunnelzone_hosts(tz_id) + res = @connection.get do |req| + req.url "/midonet-api/tunnel_zones/#{tz_id}/hosts" + end + + return JSON.parse(res.body) + end + + def call_get_tunnelzone_host(tz_id, host_id) + return call_get_tunnelzone_hosts(tz_id).select{ |host| host['id'] == host_id } + end + + + def call_delete_tunnelzone(tz_id) + res = @connection.delete do |req| + req.url "/midonet-api/tunnel_zones/#{tz_id}" + end + end + + def call_delete_tunnelzone_host(tz_id, host_id) + res = @connection.delete do |req| + req.url "/midonet-api/tunnel_zones/#{tz_id}/hosts/#{host_id}" + end + end + + private :call_create_tunnelzone, + :call_create_tunnelzone_host, + :call_delete_tunnelzone, + :call_delete_tunnelzone_host, + :call_get_host, + :call_get_tunnelzone, + :call_get_tunnelzone_host, + :call_get_tunnelzone_hosts, + :define_connection + +end diff --git a/lib/puppet/type/midonet_host_registry.rb b/lib/puppet/type/midonet_host_registry.rb new file mode 100644 index 0000000..00d6d4d --- /dev/null +++ b/lib/puppet/type/midonet_host_registry.rb @@ -0,0 +1,95 @@ +require 'uri' +require 'facter' + +Puppet::Type.newtype(:midonet_host_registry) do + @doc = %q{Register a Host to a MidoNet tunnel zone + through the MidoNet API + + Example: + + midonet_host_registry {'hostname': + $midonet_api_url => 'http://controller:8080', + $username => 'admin', + $password => 'admin', + $ip_address => '123.23.43.2' + } + } + ensurable + + newparam(:hostname, :namevar => true) do + desc 'Hostname of the host that wants to register in MidoNet cloud' + # Regex obtained from StackOverflow question: + # http://stackoverflow.com/questions/1418423/the-hostname-regex + validate do |value| + unless value =~ /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/ + raise ArgumentError, "'%s' is not a valid hostname" % value + end + end + end + + newparam(:tunnelzone_name) do + desc 'Name of the tunnelzone. If it does not exist, it creates one' + defaultto :'tzone0' + validate do |value| + unless value =~ /\w+/ + raise ArgumentError, "'%s' is not a valid tunnelzone name" % value + end + end + end + + newparam(:tunnelzone_type) do + desc 'Network technology to use when creating the tunnel' + defaultto 'gre' + newvalues('gre', 'vxlan') + end + + newparam(:midonet_api_url) do + desc 'MidoNet API endpoint to connect to' + validate do |value| + unless value =~ /\A#{URI::regexp(['http', 'https'])}\z/ + raise ArgumentError, "'%s' is not a valid URI" % value + end + end + end + + newparam(:username) do + desc 'Username of the admin user in keystone' + validate do |value| + unless value =~ /\w+/ + raise ArgumentError, "'%s' is not a valid username" % value + end + end + end + + newparam(:password) do + desc 'Password of the admin user in keystone' + validate do |value| + unless value =~ /\w+/ + raise ArgumentError, "'%s' is not a valid password" % value + end + end + end + + newparam(:tenant_name) do + desc 'Tenant name of the admin user' + defaultto :'admin' + validate do |value| + unless value =~ /\w+/ + raise ArgumentError, "'%s' is not a tenant name" % value + end + end + end + + newparam(:underlay_ip_address) do + desc "IP address that will be used to as the underlay layer to + create the tunnels. It will take the fact $ipaddress by + default" + defaultto Facter['ipaddress'].value + validate do |value| + unless value =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/ + raise ArgumentError, "'%s' is not a valid IPv4 address" % value + end + end + end + +end diff --git a/manifests/init.pp b/manifests/init.pp index 36d1979..d1a8ea1 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -60,4 +60,20 @@ class midonet { # Add midonet-cli class {'midonet::midonet_cli':} + if ! defined(Package['faraday']) { + package { 'faraday': + ensure => present, + provider => 'gem', + before => Midonet_host_registry[$::hostname] + } + } + + # Register the host + midonet_host_registry { $::hostname: + ensure => present, + midonet_api_url => 'http://127.0.0.1:8080', + username => 'admin', + password => 'admin', + require => Class['midonet::midonet_agent'] + } } diff --git a/manifests/midonet_api/install.pp b/manifests/midonet_api/install.pp index 4db738a..e75459a 100644 --- a/manifests/midonet_api/install.pp +++ b/manifests/midonet_api/install.pp @@ -28,19 +28,19 @@ class midonet::midonet_api::install { require midonet::midonet_api::augeas if ! defined(Class['java']) { - class {'java': - distribution => 'jre', - require => Exec['update-midonet-repos'] - } + class {'java': + distribution => 'jre', + require => Exec['update-midonet-repos'] + } } class {'tomcat': - install_from_source => false, - require => [Class['java'], - Exec['update-midonet-repos']] + install_from_source => false, + require => [Class['java'], + Exec['update-midonet-repos']] } -> package {'midonet-api': - ensure => present, + ensure => present, } } diff --git a/spec/acceptance/midonet_agent_spec.rb b/spec/acceptance/midonet_spec.rb similarity index 100% rename from spec/acceptance/midonet_agent_spec.rb rename to spec/acceptance/midonet_spec.rb diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1b1e893..b74f0a3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -9,4 +9,15 @@ RSpec.configure do |c| c.alias_it_should_behave_like_to :it_raises, 'raises' c.module_path = File.join(fixture_path, 'modules') c.manifest_dir = File.join(fixture_path, 'manifests') + c.mock_with :rspec do |mock_c| + mock_c = :expect + end +end + +def make_site_pp(pp, path = File.join(master['puppetpath'], 'manifests')) + on master, "mkdir -p #{path}" + create_remote_file(master, File.join(path, "site.pp"), pp) + on master, "chown -R #{master['user']}:#{master['group']} #{path}" + on master, "chmod -R 0755 #{path}" + on master, "service #{master['puppetservice']} restart" end diff --git a/spec/unit/puppet/provider/midonet_host_registry/midonet_api_caller_spec.rb b/spec/unit/puppet/provider/midonet_host_registry/midonet_api_caller_spec.rb new file mode 100644 index 0000000..12e7c16 --- /dev/null +++ b/spec/unit/puppet/provider/midonet_host_registry/midonet_api_caller_spec.rb @@ -0,0 +1,248 @@ +require 'spec_helper' + +describe Puppet::Type.type(:midonet_host_registry).provider(:midonet_api_caller) do + + let(:provider) { described_class.new(resource) } + + let(:resource) { Puppet::Type.type(:midonet_host_registry).new( + { + :ensure => :present, + :hostname => 'compute.midonet', + :midonet_api_url => 'http://controller:8080', + :username => 'username', + :password => 'password', + :tunnelzone_name => 'tzone1', + :underlay_ip_address => '172.10.0.10' + } + )} + + + describe 'host registry happy path' do + # - Single tunnelzone zones + # - Host registered + # - Allow to be created, and deleted + # - Tunnel zone should be deleted after the host deletion + + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + + let(:hosts) { + [ + { + "id" => "04f7361c-4cb8-4cda-a50f-1744fd8b7851", + "name" => "compute.midonet" + } + ] + } + + before :each do + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return(hosts) + allow(provider).to receive(:call_create_tunnelzone_host) + allow(provider).to receive(:call_get_tunnelzone_host).and_return(hosts) + allow(provider).to receive(:call_delete_tunnelzone_host) + allow(provider).to receive(:call_get_tunnelzone_hosts).and_return([]) + allow(provider).to receive(:call_delete_tunnelzone) + end + + it 'registers the host successfully' do + # Expectations over 'create' call + expect(provider).to receive(:call_create_tunnelzone_host).with(tzones[0]['id'], {'hostId' => '04f7361c-4cb8-4cda-a50f-1744fd8b7851', 'ipAddress' => '172.10.0.10'}) + expect(provider).to receive(:call_get_tunnelzone) + expect(provider).not_to receive(:call_create_tunnelzone) + expect(provider).to receive(:call_get_host) + provider.create + end + + + it 'unregisters the host successfully' do + # Expectations over the 'destroy' call + expect(provider).to receive(:call_get_tunnelzone) + expect(provider).to receive(:call_get_host) + expect(provider).to receive(:call_get_tunnelzone_hosts).with(tzones[0]['id']) + expect(provider).to receive(:call_delete_tunnelzone) + provider.destroy + end + + end + + describe 'when no tunnelzones' do + let(:hosts) { + [ + { + "id" => "04f7361c-4cb8-4cda-a50f-1744fd8b7851", + "name" => "compute.midonet" + } + ] + } + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + it 'creates the tunnelzone and the host' do + allow(provider).to receive(:call_get_tunnelzone).and_return([]) + allow(provider).to receive(:call_create_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return(hosts) + allow(provider).to receive(:call_create_tunnelzone_host) + + expect(provider).to receive(:call_create_tunnelzone).once + expect(provider.exists?).to eq false + + provider.create + end + end + + describe 'unregister not the last host in tunnelzone' do + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + let(:host_to_unregister) { + [ + { + "id" => "04f7361c-4cb8-4cda-a50f-1744fd8b7851", + "name" => "compute.midonet" + } + ] + } + let(:host_left_in_tunnelzone) { + [ + { + "id" => "04f7361c-4cb8-4cda-a50f-1744fd8b7852", + "name" => "compute2.midonet" + } + ] + } + + it 'should not call the tunnelzone deletion' do + # Preparing the rest responses + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return(host_to_unregister) + allow(provider).to receive(:call_delete_tunnelzone_host) + allow(provider).to receive(:call_get_tunnelzone_host).and_return(host_to_unregister) + allow(provider).to receive(:call_get_tunnelzone_hosts).and_return(host_left_in_tunnelzone) + + # Set the behaviour expectations + expect(provider).to receive(:call_delete_tunnelzone_host).with(tzones[0]['id'], host_to_unregister[0]['id']) + expect(provider).not_to receive(:call_delete_tunnelzone) + + provider.destroy + end + end + + describe 'try to register a host without midonet-agent' do + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + + it 'should raise an exception' do + # Preparing the rest responses + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return([]) + expect { + provider.create + }.to raise_error(RuntimeError) + end + end + + describe 'try to register a host with wrong tunnelzone type' do + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "vxlan" # Resource is 'gre' and current one is 'vxlan' + } + ] + } + it 'should raise an exception' do + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + expect { + provider.create + }.to raise_error(RuntimeError) + end + end + + describe 'try to unregister a host that belongs to a tunnelzone that does not exist' do + it 'should not fail' do + allow(provider).to receive(:call_get_tunnelzone).and_return([]) + expect(provider).not_to receive(:call_delete_tunnelzone_host) + provider.destroy + end + end + + describe 'try to unregister a host that does not exist' do + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + it 'should not fail' do + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return([]) + + expect(provider).not_to receive(:call_delete_tunnelzone_host) + + provider.destroy + end + end + + describe 'try to unregister a host that does not belong to a tunnelzone' do + let(:tzones) { + [ + { + "name" => "tzone1", + "id" => "bd69f96a-005b-4d58-9f6c-b8dd9fbb6339", + "type" => "gre" + } + ] + } + let(:hosts) { + [ + { + "id" => "04f7361c-4cb8-4cda-a50f-1744fd8b7851", + "name" => "compute.midonet" + } + ] + } + it 'should not fail' do + allow(provider).to receive(:call_get_tunnelzone).and_return(tzones) + allow(provider).to receive(:call_get_host).and_return(hosts) + allow(provider).to receive(:call_get_tunnelzone_host).and_return([]) + + expect(provider).to receive(:call_get_tunnelzone).once + expect(provider).to receive(:call_get_host).once + expect(provider).to receive(:call_get_tunnelzone_host).once.with(tzones[0]['id'], hosts[0]['id']) + + provider.destroy + end + end + +end diff --git a/spec/unit/puppet/type/midonet_host_registry_spec.rb b/spec/unit/puppet/type/midonet_host_registry_spec.rb new file mode 100644 index 0000000..7f36425 --- /dev/null +++ b/spec/unit/puppet/type/midonet_host_registry_spec.rb @@ -0,0 +1,151 @@ +require 'spec_helper' +require 'puppet' +require 'puppet/type/midonet_host_registry' +require 'facter' + +describe Puppet::Type::type(:midonet_host_registry) do + + context 'on default values' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin') + end + + it 'assign the default values' do + expect(resource[:tenant_name]).to eq :'admin' + expect(resource[:underlay_ip_address]).to eq Facter['ipaddress'].value + expect(resource[:tunnelzone_name]).to eq :'tzone0' + expect(resource[:tunnelzone_type]).to eq :'gre' + end + end + + context 'on invalid hostname' do + it do + expect { + Puppet::Type.type(:midonet_host_registry).new( + :hostname => '_invalid_hostname.local', + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin') + }.to raise_error(Puppet::ResourceError) + end + end + + context 'on invalid api url' do + it do + expect { + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => '87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin') + }.to raise_error(Puppet::ResourceError) + end + end + + context 'on tenant_name valid value' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :tenant_name => 'midokura') + end + + it 'assign to it' do + expect(resource[:tenant_name]).to eq 'midokura' + end + end + + context 'on tunnelzone valid name' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :tunnelzone_name => 'tzoneee') + end + + it 'assign to it' do + expect(resource[:tunnelzone_name]).to eq 'tzoneee' + end + end + + context 'on tunnelzone valid type gre' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :tunnelzone_type => 'gre') + end + + it 'assign to it' do + expect(resource[:tunnelzone_type]).to eq :'gre' + end + end + + context 'on tunnelzone valid type vxlan' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :tunnelzone_type => 'vxlan') + end + + it 'assign to it' do + expect(resource[:tunnelzone_type]).to eq :'vxlan' + end + end + + context 'on tunnelzone valid type foo' do + it do + expect { + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :tunnelzone_type => 'foo') + }.to raise_error(Puppet::ResourceError) + end + end + + context 'on underlay_ip_address valid IP' do + let(:resource) do + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :underlay_ip_address => '76.3.176.129') + end + + it 'assign it properly' do + expect(resource[:underlay_ip_address]).to eq '76.3.176.129' + end + end + + context 'on underlay_ip_address invalid IP' do + + it do + expect { + Puppet::Type.type(:midonet_host_registry).new( + :hostname => Facter['hostname'].value, + :midonet_api_url => 'http://87.23.43.2:8080/midonet-api', + :username => 'admin', + :password => 'admin', + :underlay_ip_address => '76.3.280.129') + }.to raise_error(Puppet::ResourceError) + end + + end +end