diff --git a/README.markdown b/README.markdown index 9facbb5..1b07d6a 100644 --- a/README.markdown +++ b/README.markdown @@ -346,6 +346,22 @@ Default: `'-Djava.net.preferIPv4Stack=true'` Valid options: A string of valid Java options. +##### `username` + +Specifies the username to set for admin role in ODL. + +Default: `'admin'` + +Valid options: A username string. + +##### `password` + +Specifies the password to set for admin role in ODL. + +Default: `'admin'` + +Valid options: A password string. + ## Limitations - Tested on CentOS 7 and Ubuntu 16.04. diff --git a/lib/puppet/provider/odl_user/idm.rb b/lib/puppet/provider/odl_user/idm.rb new file mode 100644 index 0000000..da48aa5 --- /dev/null +++ b/lib/puppet/provider/odl_user/idm.rb @@ -0,0 +1,40 @@ +Puppet::Type.type(:odl_user).provide(:idm) do + + commands :java => 'java' + + def odl_path + '/opt/opendaylight' + end + + def idm_cmd(*args) + java('-jar', "#{odl_path}/bin/aaa-cli-jar.jar", '--dbd', odl_path, *args) + end + + def create + idm_cmd('--newUser', @resource[:username], '-p', @resource[:password]) + end + + def destroy + idm_cmd('--deleteUser', @resource[:username]) + end + + def exists? + output = idm_cmd('-l').split("\n") + output.each do |line| + if line.eql? @resource[:username] + return true + end + end + return false + end + + def password + return false + end + + def password=(password) + destroy + idm_cmd('--newUser', @resource[:username], '-p', password) + end + +end diff --git a/lib/puppet/type/odl_user.rb b/lib/puppet/type/odl_user.rb new file mode 100644 index 0000000..21904a2 --- /dev/null +++ b/lib/puppet/type/odl_user.rb @@ -0,0 +1,23 @@ +Puppet::Type.newtype(:odl_user) do + + ensurable + + newparam(:username, :namevar => true) do + desc "Username to configure in ODL IDM with admin role" + newvalues(/^\w+$/) + end + + newproperty(:password) do + desc "Password for this user" + validate do |value| + if !value.is_a?(String) + raise ArgumentError, "Passwords must be a string" + end + end + + def change_to_s(current, desire) + "Password changed" + end + end + +end diff --git a/manifests/config.pp b/manifests/config.pp index 921965d..93398de 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -107,4 +107,10 @@ match => '^routing-node=.*$', } } + + # Configure username/password + odl_user { $::opendaylight::username: + password => $::opendaylight::password, + before => Service['opendaylight'], + } } diff --git a/manifests/init.pp b/manifests/init.pp index ae7b4f9..34d42bd 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -53,6 +53,8 @@ $vpp_routing_node = $::opendaylight::params::vpp_routing_node, $java_opts = $::opendaylight::params::java_opts, $manage_repositories = $::opendaylight::params::manage_repositories, + $username = $::opendaylight::params::username, + $password = $::opendaylight::params::password, ) inherits ::opendaylight::params { # Validate OS family diff --git a/manifests/params.pp b/manifests/params.pp index 6ea1311..0f50662 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -22,4 +22,6 @@ $vpp_routing_node = '' $java_opts = '-Djava.net.preferIPv4Stack=true' $manage_repositories = true + $username = 'admin' + $password = 'admin' } diff --git a/spec/acceptance/class_spec.rb b/spec/acceptance/class_spec.rb index 9e21390..341bf2c 100644 --- a/spec/acceptance/class_spec.rb +++ b/spec/acceptance/class_spec.rb @@ -122,4 +122,16 @@ log_level_validations(log_levels: custom_log_levels) end end + + describe 'testing odl username/password' do + context 'using default username/password' do + context 'using default log levels' do + # Call specialized helper fn to install OpenDaylight + install_odl({:extra_features => ['odl-restconf']}) + + # Call specialized helper fn for username/password validations + username_password_validations + end + end + end end diff --git a/spec/classes/opendaylight_spec.rb b/spec/classes/opendaylight_spec.rb index deddde8..2d3d6eb 100644 --- a/spec/classes/opendaylight_spec.rb +++ b/spec/classes/opendaylight_spec.rb @@ -733,4 +733,52 @@ end end + # ODL username/password tests + describe 'ODL username/password tests' do + # Non-OS-type tests assume CentOS 7 + # See issue #43 for reasoning: + # https://github.com/dfarrell07/puppet-opendaylight/issues/43#issue-57343159 + osfamily = 'RedHat' + operatingsystem = 'CentOS' + operatingsystemmajrelease = '7' + context 'using default username/password' do + let(:facts) {{ + :osfamily => osfamily, + :operatingsystem => operatingsystem, + :operatingsystemmajrelease => operatingsystemmajrelease, + }} + + let(:params) {{ }} + + # Run shared tests applicable to all supported OSs + # Note that this function is defined in spec_helper + generic_tests + + # Run test that specialize in checking username/password config + # Note that this function is defined in spec_helper + username_password_tests('admin','admin') + end + + context 'specifying non-default username/password' do + let(:facts) {{ + :osfamily => osfamily, + :operatingsystem => operatingsystem, + :operatingsystemmajrelease => operatingsystemmajrelease, + }} + + let(:params) {{ + :username => 'test', + :password => 'test' + }} + + # Run shared tests applicable to all supported OSs + # Note that this function is defined in spec_helper + generic_tests + + # Run test that specialize in checking routing-node config + # Note that this function is defined in spec_helper + username_password_tests('test', 'test') + end + end + end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cd3b618..a26d1e8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -361,3 +361,13 @@ def vpp_routing_node_tests(options = {}) } end end + +# ODL username/password tests +def username_password_tests(username, password) + + it { + should contain_odl_user(username).with( + :password => password + ) + } +end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index f911b3d..712004d 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -71,6 +71,8 @@ def install_odl(options = {}) enable_ha = options.fetch(:enable_ha, false) ha_node_ips = options.fetch(:ha_node_ips, []) ha_node_index = options.fetch(:ha_node_index, 0) + username = options.fetch(:username, 'admin') + password = options.fetch(:password, 'admin') # Build script for consumption by Puppet apply it 'should work idempotently with no errors' do @@ -85,6 +87,8 @@ class { 'opendaylight': ha_node_ips=> #{ha_node_ips}, ha_node_index=> #{ha_node_index}, log_levels=> #{log_levels}, + username=> #{username}, + password=> #{password}, } EOS @@ -330,3 +334,21 @@ def deb_validations() it { should be_installed } end end + +# Shared function for validations related to username/password +def username_password_validations(options = {}) + # NB: This param default should match the one used by the opendaylight + # class, which is defined in opendaylight::params + # TODO: Remove this possible source of bugs^^ + odl_username = options.fetch(:username, 'admin') + odl_password = options.fetch(:password, 'admin') + odl_check_url = 'http://127.0.0.1:8080/restconf' + + describe file('/opt/opendaylight/idmlight.db.mv.db') do + it { should be_file } + end + + describe command("sleep 60 && curl -o /dev/null --fail --silent --head -u #{odl_username}:#{odl_password} #{odl_check_url}") do + its(:exit_status) { should eq 0 } + end +end diff --git a/spec/unit/provider/idm_spec.rb b/spec/unit/provider/idm_spec.rb new file mode 100644 index 0000000..a8e3cf2 --- /dev/null +++ b/spec/unit/provider/idm_spec.rb @@ -0,0 +1,38 @@ +require 'puppet' +require 'puppet/provider/odl_user/idm' +require 'spec_helper' + +provider_class = Puppet::Type.type(:odl_user).provider(:idm) + +describe 'Puppet::Type.type(:odl_user).provider(:idm)' do + + let :odl_attrs do + { + :username => 'admin', + :ensure => 'present', + } + end + + let :resource do + Puppet::Type::Odl_user.new(odl_attrs) + end + + let :provider do + provider_class.new(resource) + end + + describe 'on create' do + it 'should call idm to create user' do + provider.expects(:idm_cmd) + provider.create + end + end + + describe "when changing password" do + it 'should change password' do + provider.expects(:destroy) + provider.expects(:idm_cmd) + provider.password = 'admin' + end + end +end diff --git a/spec/unit/type/odl_user_spec.rb b/spec/unit/type/odl_user_spec.rb new file mode 100644 index 0000000..e9b0942 --- /dev/null +++ b/spec/unit/type/odl_user_spec.rb @@ -0,0 +1,11 @@ +require 'puppet' +require 'puppet/type/odl_user' +require 'spec_helper' + +describe 'Puppet::Type.type(:odl_user)' do + + it 'should accept username/password' do + Puppet::Type.type(:odl_user).new(:username => 'admin', :password => 'admin') + end + +end