Repository: voxpupuli/puppet-jira
Pull request #434: Fix breaking change regression of PR #429
Author: login: diLLec
Labels: name: bug
description: Something isn't working
name: needs-squash
Created: 2025-02-25T22:37:33Z | Merged: 2025-03-27T12:31:10Z

#### Pull Request (PR) description
Optimization for PR [Add "change database password" parameter - JIRA >10.3](https://github.com/voxpupuli/puppet-jira/pull/429)

#### This Pull Request (PR) fixes the following issues
* make change_dbpassword only be effective after version 10.3.0
* add tests 



Diff:
diff --git a/README.md b/README.md
index 5be5471a..6606a2ca 100644
--- a/README.md
+++ b/README.md
@@ -93,6 +93,7 @@ If you would prefer to use Hiera then see jira.yaml file for an example.
 The module can install a package for you using your OS's package manager.
 Note that there's no smarts here. You need to set javahome correctly.
 
+*Pre JIRA 10*
 ```puppet
   # this example works on RHEL
   class { 'jira':
@@ -101,6 +102,15 @@ Note that there's no smarts here. You need to set javahome correctly.
   }
 ```
 
+*Post JIRA 10*
+```puppet
+  # this example works on RHEL
+  class { 'jira':
+    java_package  => 'java-17-openjdk'
+    javahome      => '/usr/lib/jvm/jre-17-opendjk/',
+  }
+```
+
 #### Upgrades
 
 ##### Upgrades to JIRA
@@ -113,7 +123,7 @@ doing large version upgrades. Always backup your database and your home director
   class { 'jira':
     java_package  => 'java-11-openjdk-headless'
     javahome      => '/usr/lib/jvm/jre-11-opendjk/',
-    version     => '8.16.0',
+    version       => '8.16.0',
   }
 ```
 
@@ -247,6 +257,11 @@ Reverse proxy can be configured as a hash as part of the JIRA resource
    },
 ```
 
+### notes on secret encryption in dbconfig.xml
+The JIRA process will read the dbconfig.xml on startup replace it with the string "{ATL_SECURED}". The password is moved
+into `<shared_homedir>/keys/javax.crypto.spec.SecretKeySpec_<some random number>`. It is important that this directory
+is not located inside of the installation dir as you would lose it in the case of an update.
+
 ## Reference
 
 see [REFERENCE.md](REFERENCE.md)
diff --git a/REFERENCE.md b/REFERENCE.md
index 6b9fe2cf..322f44b6 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -20,6 +20,10 @@
 
 ### Functions
 
+#### Public Functions
+
+* [`jira::is_installed`](#jira--is_installed): Check if JIRA is already installed
+
 #### Private Functions
 
 * `jira::sort_hash`: Sort a hash
@@ -388,7 +392,7 @@ Default value: `'jira'`
 
 Data type: `Boolean`
 
-Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}"
+Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}" (defaults to true in JIRA versions < 10.3.0)
 
 Default value: `false`
 
@@ -1164,6 +1168,26 @@ Deprecated. Has no effect.
 
 Default value: `undef`
 
+## Functions
+
+### <a name="jira--is_installed"></a>`jira::is_installed`
+
+Type: Ruby 4.x API
+
+Check if JIRA is already installed
+
+#### `jira::is_installed(String[1] $homedir)`
+
+The jira::is_installed function.
+
+Returns: `Boolean`
+
+##### `homedir`
+
+Data type: `String[1]`
+
+
+
 ## Data types
 
 ### <a name="Jira--Jvm_types"></a>`Jira::Jvm_types`
diff --git a/examples/jira_mysql_install.pp b/examples/jira_mysql_install.pp
index d06ec78a..2a8a274f 100644
--- a/examples/jira_mysql_install.pp
+++ b/examples/jira_mysql_install.pp
@@ -1,8 +1,7 @@
 node default {
   class { 'mysql::server':
-    root_password    => 'strongpassword',
+    root_password => 'strongpassword',
   }
-
   -> mysql::db { 'jira':
     user     => 'jiraadm',
     password => 'mypassword',
diff --git a/examples/jira_mysql_nativessl_install.pp b/examples/jira_mysql_nativessl_install.pp
index d6b8943c..772cb5b4 100644
--- a/examples/jira_mysql_nativessl_install.pp
+++ b/examples/jira_mysql_nativessl_install.pp
@@ -3,7 +3,7 @@
   $key = hiera('key')
 
   class { 'mysql::server':
-    root_password    => 'strongpassword',
+    root_password => 'strongpassword',
   }
 
   mysql::db { 'jira':
diff --git a/examples/jira_postgres_install.pp b/examples/jira_postgres_install.pp
index fe011db8..ed3475cf 100644
--- a/examples/jira_postgres_install.pp
+++ b/examples/jira_postgres_install.pp
@@ -12,7 +12,7 @@
   }
 
   -> class { 'jira':
-    javahome    => '/opt/java/latest',
+    javahome => '/opt/java/latest',
   }
 
   include jira::facts
diff --git a/lib/puppet/functions/jira/is_installed.rb b/lib/puppet/functions/jira/is_installed.rb
new file mode 100644
index 00000000..2b40deb2
--- /dev/null
+++ b/lib/puppet/functions/jira/is_installed.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# @summary Check if JIRA is already installed
+Puppet::Functions.create_function(:'jira::is_installed') do
+  dispatch :default_impl do
+    # @param homedir The directory for JIRA's runtime data that persists between versions.
+    # @return [Boolean] install status
+    param 'String[1]', :homedir
+    return_type 'Boolean'
+  end
+
+  def default_impl(homedir)
+    File.exist? format('%s/dbconfig.xml', homedir)
+  rescue StandardError
+    false
+  end
+end
diff --git a/manifests/config.pp b/manifests/config.pp
index 3f73cbca..039a223e 100644
--- a/manifests/config.pp
+++ b/manifests/config.pp
@@ -48,8 +48,6 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
-
   if $jira::dbport {
     $dbport = $jira::dbport
   } else {
@@ -106,6 +104,7 @@
     deprecation('jira::poolsize', 'jira::poolsize is deprecated and simply sets max-pool-size. Please use jira::pool_max_size instead and remove this configuration')
   }
 
+  $change_dbpassword = $jira::change_dbpassword_real
   $pool_min_size = pick($jira::pool_min_size, 20)
   $pool_max_size = pick($jira::pool_max_size, $jira::poolsize, 20)
   $pool_max_wait = pick($jira::pool_max_wait, 30000)
diff --git a/manifests/init.pp b/manifests/init.pp
index 523b4c16..4fc25bb6 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -69,7 +69,7 @@
 # @param dbname
 #   The database name to connect to
 # @param change_dbpassword
-#   Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}"
+#   Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}" (defaults to true in JIRA versions < 10.3.0)
 # @param dbuser
 #   Database username
 # @param dbpassword
@@ -484,6 +484,23 @@
     fail('You need to specify a value for javahome')
   }
 
+  $is_insalled_deferred = Deferred('jira::is_installed', [$jira::homedir])
+  $is_installed = $is_insalled_deferred =~ Deferred ? {
+    true  => jira::is_installed($jira::homedir),
+    false => $is_insalled_deferred
+  }
+  if $is_installed {
+    # use the parameter if the fact did not run (confine), or the fact shows that there is a dbconfig.xml in place
+    $change_dbpassword_real = versioncmp($version, '10.3.0') ? {
+      -1      => true,
+      default => $change_dbpassword,
+    }
+  }
+  else {
+    # jira probably not installed
+    $change_dbpassword_real = true
+  }
+
   contain jira::install
   contain jira::config
   contain jira::service
@@ -502,7 +519,7 @@
     if  $plugin_data['ensure'] == 'absent' {
       archive {
         $target:
-          ensure        => 'absent',
+          ensure => 'absent',
       }
     } else {
       $_target_defaults = {
diff --git a/spec/acceptance/default_parameters_jira_10_spec.rb b/spec/acceptance/default_parameters_jira_10_spec.rb
new file mode 100644
index 00000000..bc8b9414
--- /dev/null
+++ b/spec/acceptance/default_parameters_jira_10_spec.rb
@@ -0,0 +1,187 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  family = fact('os.family')
+  major = fact('os.release.major')
+  (family == 'Debian' and (major >= '22.04' or (major >= '11' and major <= '20'))) or (family == 'RedHat' and major >= '8')
+end
+
+prepare = <<-EOS
+  # package {'diffutils':
+  #   ensure  => installed
+  # }
+  # file_line{'enable show_diff':
+  #   path => '/etc/puppetlabs/puppet/puppet.conf',
+  #   line => 'show_diff = true'
+  # }
+EOS
+
+pre = <<-EOS
+  if $facts['os']['family']  == 'RedHat' {
+    $java_package = 'java-17-openjdk'
+    $java_home = '/usr/lib/jvm/jre-17-openjdk'
+    $postgresql_version = '13'
+    $pgsql_package_name = 'postgresql-server'
+    $pgsql_data_dir = '/var/lib/pgsql'
+    $manage_dnf_module = $facts['os']['release']['major'] ? {
+      '8'       => true,
+      default   => false # RHEL-9 has pgsql 13 as a default
+    }
+    $autoremove_command = 'dnf --exclude="systemd*" autoremove -y'
+  }
+  elsif $facts['os']['family']  == 'Debian' {
+    $postgresql_version = $facts['os']['release']['major'] ? {
+      '11'    => '13',
+      default => '14'
+    }
+    $java_package = 'openjdk-17-jre'
+    $java_home = '/usr/lib/jvm/java-17-openjdk-amd64'
+    $pgsql_package_name = "postgresql-${postgresql_version}"
+    $pgsql_data_dir = "/var/lib/postgresql/${postgresql_version}/main/"
+    $manage_dnf_module = false
+    $autoremove_command = 'apt autoremove -y'
+  }
+  $jira_install_dir = '/opt/jira/'
+  $postgres_service = 'postgresql'
+  $jira_service = 'jira'
+EOS
+
+pp = <<-EOS
+  # The output of `systemctl status postgresql` is non ascii which
+  # breaks the Exec in Postgresql::Server::Instance::Reload
+  # on rhel based docker containers
+  # We don't need the output.
+  class { 'postgresql::globals':
+    manage_dnf_module => $manage_dnf_module,
+    version           => $postgresql_version,
+  }
+  class { 'postgresql::server':
+    service_status => 'systemctl status postgresql > /dev/null',
+    needs_initdb   => true
+  }
+
+  postgresql::server::db { 'jira':
+    user     => 'jiraadm',
+    password => postgresql::postgresql_password('jiraadm', 'mypassword'),
+  }
+
+  # There is a bug in the check-java.sh that prevents jira from starting on Centos Stream 8
+  # https://jira.atlassian.com/browse/JRASERVER-77097
+  # Running with script_check_java_manage => true to solve this
+  class { 'jira':
+    version                  => '10.3.2',
+    java_package             => $java_package,
+    javahome                 => $java_home,
+    script_check_java_manage => false,
+    connection_settings      => 'tcpKeepAlive=true',
+    require                  => Postgresql::Server::Db['jira']
+  }
+EOS
+pp = pre + pp
+
+pp_upgrade = <<-EOS
+  class { 'jira':
+    version                  => '10.3.3',
+    java_package             => $java_package,
+    javahome                 => $java_home,
+    connection_settings      => 'tcpKeepAlive=true',
+    script_check_java_manage => false
+  }
+EOS
+pp_upgrade = pre + pp_upgrade
+
+pp_remove = <<-EOS
+  package {$java_package:
+    ensure => purged
+  }
+  exec {'clear JIRA home':
+    command => 'rm -Rf ~jira/*',
+    provider => shell,
+  }
+  package {$pgsql_package_name:
+     ensure => purged
+  }
+  if $manage_dnf_module {
+    exec {"dnf module reset postgresql":
+      command => 'dnf module reset -y postgresql',
+      provider => shell,
+    }
+  }
+  exec {"autoremove cleanup":
+    command => $autoremove_command,
+    provider => shell,
+  }
+  exec {'cleanup pgsql and JIRA install dir':
+    command => "rm -Rf ${pgsql_data_dir}/* ${$jira_install_dir}/atlassian-jira-software*",
+    provider => shell,
+    require => Exec['autoremove cleanup'],
+  }
+  service{$postgres_service:
+    ensure => stopped
+  }
+  service{$jira_service:
+    ensure => stopped
+  }
+EOS
+pp_remove = pre + pp_remove
+
+context 'jira 10 only on RedHat >=8 and Debian-11', if: on_supported_os do
+  describe 'jira 10 postgresql' do
+    it 'installs jira 10 with defaults' do
+      apply_manifest(prepare, catch_failures: true)
+      # jira just takes *ages* to start up :-(
+      wget_cmd = 'wget -q --tries=24 --retry-connrefused --read-timeout=10 localhost:8080'
+      apply_manifest(pp, catch_failures: true)
+      sleep SLEEP_SECONDS
+      shell wget_cmd, acceptable_exit_codes: [0, 8]
+      sleep SLEEP_SECONDS
+      shell wget_cmd, acceptable_exit_codes: [0, 8]
+      apply_manifest(pp, catch_changes: true)
+
+      apply_manifest(pp_upgrade, catch_failures: true)
+      sleep SLEEP_SECONDS
+      shell wget_cmd, acceptable_exit_codes: [0, 8]
+      sleep SLEEP_SECONDS
+      shell wget_cmd, acceptable_exit_codes: [0, 8]
+
+      apply_manifest(pp_upgrade, catch_changes: true)
+    end
+
+    describe process('java') do
+      it { is_expected.to be_running }
+    end
+
+    describe port(8080) do
+      it { is_expected.to be_listening }
+    end
+
+    describe service('jira') do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe user('jira') do
+      it { is_expected.to belong_to_group 'jira' }
+      it { is_expected.to have_login_shell '/bin/true' }
+    end
+
+    expected_version = '10.3.3'
+    describe command("wget -q --tries=54 --retry-connrefused --read-timeout=10 -O- localhost:8080 | grep '#{expected_version}'") do
+      its(:stdout) { is_expected.to include(expected_version) }
+    end
+
+    # cleanup after this spec to ensure that following tests start without any unmanaged
+    # packages and data
+    describe 'shutdown' do
+      it 'cleans up nicely' do
+        apply_manifest(pp_remove, catch_failures: true)
+      end
+
+      it { shell('service jira stop', acceptable_exit_codes: [0, 1]) }
+      it { shell('pkill -9 -f postgres', acceptable_exit_codes: [0, 1]) }
+      it { shell('pkill -9 -f jira', acceptable_exit_codes: [0, 1]) }
+    end
+  end
+end
diff --git a/spec/acceptance/default_parameters_spec.rb b/spec/acceptance/default_parameters_spec.rb
index 05ecc9ba..f72d7f34 100644
--- a/spec/acceptance/default_parameters_spec.rb
+++ b/spec/acceptance/default_parameters_spec.rb
@@ -20,7 +20,8 @@
       # on rhel based docker containers
       # We don't need the output.
       class { 'postgresql::server':
-        service_status => 'systemctl status postgresql > /dev/null'
+        service_status => 'systemctl status postgresql > /dev/null',
+        needs_initdb   => true
       }
 
       postgresql::server::db { 'jira':
@@ -53,8 +54,7 @@ class { 'jira':
         version                  => '8.16.0',
         java_package             => $java_package,
         javahome                 => $java_home,
-        script_check_java_manage => true,
-        change_dbpassword        => true,
+        script_check_java_manage => true
       }
     EOS
 
diff --git a/spec/acceptance/mysql_spec.rb b/spec/acceptance/mysql_spec.rb
index 1f821988..9c18e857 100644
--- a/spec/acceptance/mysql_spec.rb
+++ b/spec/acceptance/mysql_spec.rb
@@ -77,7 +77,6 @@ class { 'jira':
         dbport                   => 3306,
         dbdriver                 => 'com.mysql.jdbc.Driver',
         dbtype                   => 'mysql',
-        change_dbpassword        => true,
         tomcat_port              => 8081,
         tomcat_native_ssl        => true,
         tomcat_keystore_file     => '/tmp/jira.ks',
diff --git a/spec/classes/jira_config_spec.rb b/spec/classes/jira_config_spec.rb
index 76428c4a..9e381b2c 100644
--- a/spec/classes/jira_config_spec.rb
+++ b/spec/classes/jira_config_spec.rb
@@ -91,6 +91,42 @@
             end
           end
 
+          context 'default params with java install, mysql, and jira > 10.3.0 and change_dbpassword=true' do
+            let(:params) do
+              {
+                version: '10.3.3',
+                db: 'mysql',
+                dbpassword: 'test',
+                change_dbpassword: true,
+                javahome: '/usr/lib/jvm/jre-11-openjdk',
+                java_package: 'java-11-openjdk-headless',
+              }
+            end
+
+            it do
+              is_expected.to contain_file(FILENAME_DBCONFIG_XML).
+                with_content(%r{<password>test</password>})
+            end
+          end
+
+          context 'default params with java install, mysql, and jira > 10.3.0 and change_dbpassword=false (default) and facts that indicate a fresh install' do
+            let(:params) do
+              {
+                version: '10.3.3',
+                db: 'mysql',
+                dbpassword: 'test',
+                change_dbpassword: false,
+                javahome: '/usr/lib/jvm/jre-11-openjdk',
+                java_package: 'java-11-openjdk-headless',
+              }
+            end
+
+            it do
+              is_expected.to contain_file(FILENAME_DBCONFIG_XML).
+                with_content(%r{<password>test</password>})
+            end
+          end
+
           context 'database settings' do
             let(:params) do
               super().merge(
@@ -172,8 +208,7 @@
                 dbserver: 'TheSQLServer',
                 dbname: 'TheJiraDB',
                 dbuser: 'TheDBUser',
-                dbpassword: 'TheDBPassword',
-                change_dbpassword: true
+                dbpassword: 'TheDBPassword'
               )
             end
 
@@ -196,8 +231,7 @@
                 dbserver: 'TheSQLServer',
                 dbname: 'TheJiraDB',
                 dbuser: 'TheDBUser',
-                dbpassword: 'TheDBPassword',
-                change_dbpassword: true
+                dbpassword: 'TheDBPassword'
               )
             end
 
@@ -239,8 +273,7 @@
                 dbserver: 'TheSQLServer',
                 dbname: 'TheJiraDB',
                 dbuser: 'TheDBUser',
-                dbpassword: 'TheDBPassword',
-                change_dbpassword: true
+                dbpassword: 'TheDBPassword'
               )
             end
 


Reviews:
user: login: SimonHoenscheid
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-02-26T12:50:13Z
user: login: SimonHoenscheid
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-26T12:52:00Z
user: login: SimonHoenscheid
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-02-26T15:43:36Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-26T22:17:30Z
user: login: SimonHoenscheid
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T06:50:14Z
user: login: SimonHoenscheid
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T07:41:03Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T07:42:25Z
user: login: SimonHoenscheid
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T08:03:25Z
user: login: SimonHoenscheid
state: APPROVED
author_association: MEMBER
submitted_at: 2025-02-27T08:22:31Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T16:38:18Z
user: login: SimonHoenscheid
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T16:43:02Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-27T16:46:27Z
user: login: kenyon
body: We can squash commits on merge.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-28T00:04:17Z
user: login: vchepkov
body: All facts need to be confined, so they won't be failing on Windows, for example.
Also, do you need most of the facts? Normally module itself sets the desired state, here it feels like results are unpredictable?
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-03-06T00:03:39Z
user: login: vchepkov
body: I would pass a path to the config file instead of relying on user's home. 
manifest uses jira::homedir, imho, that should be used
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-21T13:36:03Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:46:34Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:46:54Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:48:41Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:49:08Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:51:07Z
user: login: bastelfreak
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T13:52:03Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T17:55:59Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:01:46Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:02:14Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:02:24Z
user: login: diLLec
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T21:43:49Z
user: login: rwaffen
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-27T12:25:03Z

Review comments:
diff_hunk: @@ -69,7 +69,7 @@
 # @param dbname
 #   The database name to connect to
 # @param change_dbpassword
-#   Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}"
+#   Set to true to actually generate a dbconfig.xml with the password - otherwise write "{ATL_SECURED}" (for JIRA versions > 10.3.0)
path: manifests/init.pp
user: login: SimonHoenscheid
body: Defaults to true unless jira_version >= 10.3.0
created_at: 2025-02-26T12:37:09Z
author_association: MEMBER
diff_hunk: @@ -12,7 +12,7 @@
     <url><%= $jira::config::dburl %></url>
     <driver-class><%= $jira::config::dbdriver %></driver-class>
     <username><%= $jira::dbuser %></username>
-    <%- if $jira::config::change_dbpassword { -%>
+    <%- if versioncmp($jira::version, '10.3.0') < 0 or $jira::config::change_dbpassword { -%>
path: templates/dbconfig.xml.epp
user: login: SimonHoenscheid
body: I would move this to the parameter in init.pp with something like this and just use the parameter here. That ensures the module behaves the same for old versions (which is not the case right now, I did not see this while reviewing the last PR):

  $Boolean $change_dbpassword  = versioncmp($jira::version, '10.3.0') ? {
    >= 0    => false,
    default => true,
    },
created_at: 2025-02-26T12:50:03Z
author_association: MEMBER
diff_hunk: @@ -12,7 +12,7 @@
     <url><%= $jira::config::dburl %></url>
     <driver-class><%= $jira::config::dbdriver %></driver-class>
     <username><%= $jira::dbuser %></username>
-    <%- if $jira::config::change_dbpassword { -%>
+    <%- if versioncmp($jira::version, '10.3.0') < 0 or $jira::config::change_dbpassword { -%>
path: templates/dbconfig.xml.epp
user: login: SimonHoenscheid
body: Mind the parameter order here, jira::version needs to be declared first
created_at: 2025-02-26T12:52:00Z
author_association: MEMBER
diff_hunk: @@ -48,7 +48,10 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
+  $change_dbpassword = versioncmp($jira::version, '10.3.0') ? {
+    /[0-1]/  => $change_dbpassword,
path: manifests/config.pp
user: login: SimonHoenscheid
body: why not using this in init.pp and set this to false? Would prevent old setups from breaking and make the logic clear without the need for users to dig in other classes than init.pp

You are assigning a parameter to itself. This would only work if set to $jira:: change_dbpassword, so you load the default from init.pp.

created_at: 2025-02-26T15:38:07Z
author_association: MEMBER
diff_hunk: @@ -48,7 +48,10 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
+  $change_dbpassword = versioncmp($jira::version, '10.3.0') ? {
+    /[0-1]/  => $change_dbpassword,
path: manifests/config.pp
user: login: diLLec
body: All the parameters in the template templates/dbconfig.xml.epp are from jira::config. That's the reason I've done it that way. The tests are clean now. Please check
created_at: 2025-02-26T22:17:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,7 +48,10 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
+  $change_dbpassword = versioncmp($jira::version, '10.3.0') ? {
+    /[0-1]/  => $change_dbpassword,
path: manifests/config.pp
user: login: SimonHoenscheid
body: I don't see a reason to change the variable in the template. That is fine. 

But I would prefer it from a technical standpoint if the condition would move to init.pp and the parameter in config.pp would just inherit the value. For somebody looking at the init.pp it is not clear right now that a condition in config.pp might change the value. 

The rest of the PR looks good to me. 
created_at: 2025-02-27T06:50:14Z
author_association: MEMBER
diff_hunk: @@ -484,6 +484,11 @@
     fail('You need to specify a value for javahome')
   }
 
+  $change_dbpassword = versioncmp($version, '10.3.0') ? {
path: manifests/init.pp
user: login: SimonHoenscheid
body: Puppet does not allow reassignments.

There are two possible solutions:

1: do this in the parameter list, default to false.
2: use a variable like $real_change_dbpassword, to assign this to and use this one afterwards
created_at: 2025-02-27T07:40:42Z
author_association: MEMBER
diff_hunk: @@ -48,7 +48,10 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
+  $change_dbpassword = versioncmp($jira::version, '10.3.0') ? {
+    /[0-1]/  => $change_dbpassword,
path: manifests/config.pp
user: login: diLLec
body: I've added the code to init.pp but the puppet idiom of reassigned variables is not allowed makes it hard here. There are two options here: 

1. use another variable name like change_dbpassword_real  in init.pp and assign that in config.pp
```
  $change_dbpassword_real = versioncmp($version, '10.3.0') ? {
    -1      => true,
    default => $change_dbpassword,
  }
```
2. assign the variable to `jira::config` out of `init.pp`  like this
```
  $jira::config::change_dbpassword = versioncmp($version, '10.3.0') ? {
    -1      => true,
    default => $change_dbpassword,
  }
```

Do you see another option here? I've added a commit for version 2 but it did not work like that:
`Illegal attempt to assign to 'jira::config::change_dbpassword'. Cannot assign to variables in other namespace`

So the last commit implements option 1 

created_at: 2025-02-27T07:42:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -48,7 +48,10 @@
     }
   }
 
-  $change_dbpassword = $jira::change_dbpassword
+  $change_dbpassword = versioncmp($jira::version, '10.3.0') ? {
+    /[0-1]/  => $change_dbpassword,
path: manifests/config.pp
user: login: SimonHoenscheid
body: ```
  Boolean $change_dbpassword = versioncmp($version, '10.3.0') ? {
    -1      => true,
    default => false,
},
```

would work, version needs to be declared first.
created_at: 2025-02-27T08:03:24Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,5 @@
+{
path: .vscode/settings.json
user: login: bastelfreak
body: please don't commit your editor config
created_at: 2025-02-27T16:38:18Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,5 @@
+{
path: .vscode/settings.json
user: login: SimonHoenscheid
body: should we add this to .gitigniore?
created_at: 2025-02-27T16:43:02Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,5 @@
+{
path: .vscode/settings.json
user: login: bastelfreak
body: I considered it. But our modulesync_config already purges it: https://github.com/voxpupuli/modulesync_config/blob/master/config_defaults.yml#L165-L166. So you could add it to the .gitignore, but it will be deleted when you run msync, and I think that would cause more confusion.
created_at: 2025-02-27T16:46:27Z
author_association: MEMBER
diff_hunk: @@ -91,6 +91,42 @@
             end
           end
 
+          context 'default params with java install and mysql > 10.3.0 and change_dbpassword=true' do
path: spec/classes/jira_config_spec.rb
user: login: kenyon
body: ```suggestion
          context 'default params with java install, mysql, and jira > 10.3.0 and change_dbpassword=true' do
```
created_at: 2025-02-28T00:03:39Z
author_association: MEMBER
diff_hunk: @@ -91,6 +91,42 @@
             end
           end
 
+          context 'default params with java install and mysql > 10.3.0 and change_dbpassword=true' do
+            let(:params) do
+              {
+                version: '10.3.3',
+                db: 'mysql',
+                dbpassword: 'test',
+                change_dbpassword: true,
+                javahome: '/usr/lib/jvm/jre-11-openjdk',
+                java_package: 'java-11-openjdk-headless',
+              }
+            end
+
+            it do
+              is_expected.to contain_file(FILENAME_DBCONFIG_XML).
+                with_content(%r{<password>test</password>})
+            end
+          end
+
+          context 'default params with java install and mysql > 10.3.0 and change_dbpassword=false' do
path: spec/classes/jira_config_spec.rb
user: login: kenyon
body: ```suggestion
          context 'default params with java install, mysql, and jira > 10.3.0 and change_dbpassword=false' do
```
created_at: 2025-02-28T00:03:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# @summary Check if JIRA is already installed
+Puppet::Functions.create_function(:'jira::is_installed') do
path: lib/puppet/functions/jira/is_installed.rb
user: login: bastelfreak
body: is there a reason why you used a function here that you defer? Usually such agent-side checks are done by a fact.
created_at: 2025-03-21T13:46:34Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# @summary Check if JIRA is already installed
+Puppet::Functions.create_function(:'jira::is_installed') do
path: lib/puppet/functions/jira/is_installed.rb
user: login: bastelfreak
body: Edit: Ah because you need to pass a user?
created_at: 2025-03-21T13:46:54Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: bastelfreak
body: This excludes debian and future ubuntu versions. is that on purpose? And below you mentioned debian-11, but the test isn't running on that platform.
created_at: 2025-03-21T13:48:41Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: bastelfreak
body: was that actually required? I thought beaker uses that by default
created_at: 2025-03-21T13:49:08Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
+    path => '/etc/puppetlabs/puppet/puppet.conf',
+    line => 'show_diff = true'
+  }
+EOS
+
+pre = <<-EOS
+  if $facts['os']['family']  == 'RedHat' {
+    $java_package = 'java-17-openjdk'
+    $java_home = '/usr/lib/jvm/jre-17-openjdk'
+    $postgresql_version = '13'
+    $pgsql_package_name = 'postgresql-server'
+    $pgsql_data_dir = '/var/lib/pgsql'
+    $manage_dnf_module = $facts['os']['release']['major'] ? {
+      '8'       => true,
+      default => false # RHEL-9 has pgsql 13 as a default
+    }
+    $autoremove_command = 'dnf --exclude="systemd*" autoremove -y'
+  }
+  elsif $facts['os']['family']  == 'Debian' {
+    $java_package = 'openjdk-17-jre'
+    $java_home = '/usr/lib/jvm/java-17-openjdk-amd64'
+    $postgresql_version = '14'
+    $pgsql_package_name = "postgresql-${postgresql_version}"
+    $pgsql_data_dir = "/var/lib/postgresql/${postgresql_version}/main/"
+    $manage_dnf_module = false
+    $autoremove_command = 'apt autoremove -y'
+  }
+  $jira_install_dir = '/opt/jira/'
+  $postgres_service = 'postgresql'
+  $jira_service = 'jira'
+EOS
+
+pp = <<-EOS
+  # The output of `systemctl status postgresql` is non ascii which
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: bastelfreak
body: I have some questions here. Why does that even break the exec resource? And is that a patch that should be added to the postgresql module instead?
created_at: 2025-03-21T13:51:06Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
+    path => '/etc/puppetlabs/puppet/puppet.conf',
+    line => 'show_diff = true'
+  }
+EOS
+
+pre = <<-EOS
+  if $facts['os']['family']  == 'RedHat' {
+    $java_package = 'java-17-openjdk'
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: bastelfreak
body: should those defaults be added to the actual puppet classes? Or at least be documented in the README.md?
created_at: 2025-03-21T13:52:03Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# @summary Check if JIRA is already installed
+Puppet::Functions.create_function(:'jira::is_installed') do
path: lib/puppet/functions/jira/is_installed.rb
user: login: diLLec
body: yes - thats right. First I have proposed a solution with facts but it was declined by @vchepkov. The deferred version works and has the advantage that the homedir can be passed and does not need to be deducted.
created_at: 2025-03-26T17:55:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: diLLec
body: Yes - it is for testing purposes and to see more details. I've commented it out. 
created_at: 2025-03-26T18:01:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
+    path => '/etc/puppetlabs/puppet/puppet.conf',
+    line => 'show_diff = true'
+  }
+EOS
+
+pre = <<-EOS
+  if $facts['os']['family']  == 'RedHat' {
+    $java_package = 'java-17-openjdk'
+    $java_home = '/usr/lib/jvm/jre-17-openjdk'
+    $postgresql_version = '13'
+    $pgsql_package_name = 'postgresql-server'
+    $pgsql_data_dir = '/var/lib/pgsql'
+    $manage_dnf_module = $facts['os']['release']['major'] ? {
+      '8'       => true,
+      default => false # RHEL-9 has pgsql 13 as a default
+    }
+    $autoremove_command = 'dnf --exclude="systemd*" autoremove -y'
+  }
+  elsif $facts['os']['family']  == 'Debian' {
+    $java_package = 'openjdk-17-jre'
+    $java_home = '/usr/lib/jvm/java-17-openjdk-amd64'
+    $postgresql_version = '14'
+    $pgsql_package_name = "postgresql-${postgresql_version}"
+    $pgsql_data_dir = "/var/lib/postgresql/${postgresql_version}/main/"
+    $manage_dnf_module = false
+    $autoremove_command = 'apt autoremove -y'
+  }
+  $jira_install_dir = '/opt/jira/'
+  $postgres_service = 'postgresql'
+  $jira_service = 'jira'
+EOS
+
+pp = <<-EOS
+  # The output of `systemctl status postgresql` is non ascii which
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: diLLec
body: This I've copied from the existing default_parameters_spec.rb. I don't know if it is still needed.
created_at: 2025-03-26T18:02:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
+end
+
+prepare = <<-EOS
+  package {'diffutils':
+    ensure  => installed
+  }
+  file_line{'enable show_diff':
+    path => '/etc/puppetlabs/puppet/puppet.conf',
+    line => 'show_diff = true'
+  }
+EOS
+
+pre = <<-EOS
+  if $facts['os']['family']  == 'RedHat' {
+    $java_package = 'java-17-openjdk'
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: diLLec
body: Addred a comment on that in the readme.MD
created_at: 2025-03-26T18:02:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,182 @@
+# frozen_string_literal: true
+
+require 'spec_helper_acceptance'
+
+def on_supported_os
+  (fact('os.family') == 'Debian' and fact('os.release.major') == '22.04') or (fact('os.family') == 'RedHat' and fact('os.release.major') >= '8')
path: spec/acceptance/default_parameters_jira_10_spec.rb
user: login: diLLec
body: debian11 and ubuntu2204 and RH8/9 are included now. Ubuntu 2004 only has postgresql 12 and therefore is not compatible with JIRA >10
created_at: 2025-03-26T21:43:48Z
author_association: CONTRIBUTOR

PR comments:
user: login: diLLec
created_at: 2025-02-25T22:41:23Z
body: I really tried to add an acceptance test for JIRA 10.3.3 but I think we would need to limit those to certain modern OS versions like CentOS 9. Otherwise the prerequisites on MySQL and JAVA Version would not be able to be met. Unfortunately, I don't know how to limit the acceptance tests to a certain OS. If someone knows, please contact me.
author_association: CONTRIBUTOR
user: login: SimonHoenscheid
created_at: 2025-02-27T08:21:23Z
body: @diLLec looks good to me. I asked for two other reviewers
author_association: MEMBER
user: login: SimonHoenscheid
created_at: 2025-02-27T08:38:00Z
body: @diLLec can you sqash your commits so there is just one? I think most commits can be fixups.

`git rebase -i HEAD~13` should initiate the rebase


author_association: MEMBER
user: login: bastelfreak
created_at: 2025-02-27T16:42:36Z
body: @diLLec thanks for the PR. As you mentioned, I think an acceptance test makes sense. https://github.com/voxpupuli/puppet-nodejs/blob/master/spec/acceptance/class_spec.rb#L38 has an example of limiting a test to specific operating systems. Does that help you?
author_association: MEMBER
user: login: h-haaks
created_at: 2025-02-28T00:14:09Z
body: The title of this pull request ends up in the change log.
Could you change the title to better address the fact that this fixes a regression introduced in https://github.com/voxpupuli/puppet-jira/pull/429 ?
author_association: CONTRIBUTOR
user: login: h-haaks
created_at: 2025-02-28T00:33:02Z
body: There is another regression as well.

when provisioning jira 10.3.x on a fresh server without specifying change_dbpassword = true, the password ends up being set to `{ATL_SECURED}` before the first server startup.

Solving this regression requires implementing some facts to figure out if jira is already installed or not.
It's probably best to address this in another issue/pull request.
author_association: CONTRIBUTOR
user: login: diLLec
created_at: 2025-02-28T14:40:19Z
body: After a day of testing and learning I finally managed to bring the acceptance test and the facts to work. Please review again. Locally the acceptance tests are building fine with `debian11-64` and `almalinux8-64` and `almalinux9-64`
author_association: CONTRIBUTOR
user: login: diLLec
created_at: 2025-03-05T21:45:45Z
body: Tests are fine now and commits are squashed. Please review and/or merge
author_association: CONTRIBUTOR
user: login: diLLec
created_at: 2025-03-06T07:47:19Z
body: > All facts need to be confined, so they won't be failing on Windows, for example. Also, do you need most of the facts? Normally module itself sets the desired state, here it feels like results are unpredictable?

Allright, I've confined the facts and made sure that the code that uses the fact can run without it beeing there. Most of the facts rely on each other. Sure, one can put that all in one fact but I found it more useful to single them out. 

The last sentence makes no sense to me. Could you elaborate more on what you mean?
author_association: CONTRIBUTOR
user: login: vchepkov
created_at: 2025-03-06T12:01:37Z
body: Happy to clarify! Besides the added database overhead of storing five values per node, these aren't truly 'facts' in the traditional sense. For example, if the desired status for the Jira service is 'active,' the 'jira_service_status' fact may become inaccurate after Puppet's execution if it wasn’t correct before. The same applies to the others, making these values unreliable as facts and unnecessarily increasing database utilization. A Deferred function might be a more efficient approach.
author_association: NONE
user: login: diLLec
created_at: 2025-03-06T19:26:19Z
body: Thanks for pointing out your thoughts on this, but I think that sounds a bit acadamic. There are lots of facts that change while puppet runs - think of ethernet interfaces that are provisioned, or LVM volumes, or even the os.major which could change because of puppet changes. The Deferred function seams to be a way to get to the same result in a much more complex way than the current implementation. 
author_association: CONTRIBUTOR
user: login: kenyon
created_at: 2025-03-07T06:07:46Z
body: @vchepkov is right, none of those facts should exist, IMHO. They are all states of the system that you should be enforcing if you care about them, except for `jira_running_pid`. I'm not sure what the purpose of a process ID fact is, I have never needed a PID fact.
author_association: MEMBER
user: login: diLLec
created_at: 2025-03-07T07:41:29Z
body: OK, I've played a little with the deferred function and wonder how to test them inside of a acceptence test that uses no agent but puppet apply. 

If I puppet apply to following code, the result is as follows
```
$is_installed = Deferred('jira::is_installed', ['jira'])
notice($is_installed)
---
Notice: Scope(Class[main]): Deferred({'name' => 'jira::is_installed', 'arguments' => ['jira']})
```

If the function is used without Deferred, the result (as expected) is a correct Boolean:
```
$is_installed = jira::is_installed('jira')
notice($is_installed)
---
Notice: Scope(Class[main]): false
```

I would use the Deferred function like this in the init.pp

```
$is_installed = Deferred('jira::is_installed', [$jira::user])
```

Is something like this needed to make the acceptence tests run as expected?
```
  $is_insalled_deferred = Deferred('jira::is_installed', [$jira::user])
  $is_installed = $is_insalled_deferred =~ Deferred ? {
    true  => jira::is_installed($jira::user),
    false => $is_insalled_deferred
  }
```
author_association: CONTRIBUTOR
user: login: SimonHoenscheid
created_at: 2025-03-21T12:55:51Z
body: Can we merge this Change?
author_association: MEMBER
user: login: diLLec
created_at: 2025-03-26T17:54:50Z
body: > I would pass a path to the config file instead of relying on user's home. manifest uses jira::homedir, imho, that should be used

OK - added that
author_association: CONTRIBUTOR
user: login: diLLec
created_at: 2025-03-26T21:44:31Z
body: From my point of view, this MR can be merged: all tests are OK and all the requested changes are included.
author_association: CONTRIBUTOR
user: login: rwaffen
created_at: 2025-03-27T12:20:39Z
body: okay, nice, just was looking for this change 😃 will merge and release
author_association: MEMBER