diff options
554 files changed, 16803 insertions, 6248 deletions
@@ -2,7 +2,7 @@ The content of this repository is licensed under a standard BSD license, unless noted otherwise ( ie, the external directory ) ---------------------------------------------------------------- -Copyright (c) 2010 Mageia.Org +Copyright (c) 2010-2017 Mageia.Org All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README b/README deleted file mode 100644 index d1d83446..00000000 --- a/README +++ /dev/null @@ -1,30 +0,0 @@ -Puppet layout -============= - -deployment ----------- - -Contains code specific to our deployment ( static website, mailling list -definition ), most of it should not be reusable - -external --------- - -Modules that were not written by us, and should be synced ( either by hand, -or with svn:externals, or something appropriate ). We should make sure that -proper credit is given, as well as proper location - -modules -------- - -Our own modules - -manifests ---------- - -Main puppet manifests - -extdata -------- - -Puppet extlookup datafie, should not be in svn ( mainly used for password ) diff --git a/README.md b/README.md new file mode 100644 index 00000000..78279f7f --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +Puppet layout +============= + +deployment +---------- + +Contains code specific to our deployment (static website, mailling list +definition), most of it should not be reusable + +external +-------- + +Modules that were not written by us, and should be synced (either by hand, +git submodules or something else appropriate). We should make sure that +proper credit is given, as well as proper location + +modules +------- + +Our own modules + +manifests +--------- + +Main puppet manifests + +extdata +------- + +Puppet extlookup datafie, should not be in git (mainly used for password) + + diff --git a/deployment/access_classes/manifests/admin.pp b/deployment/access_classes/manifests/admin.pp index 4b9c8f87..186c9c87 100644 --- a/deployment/access_classes/manifests/admin.pp +++ b/deployment/access_classes/manifests/admin.pp @@ -1,7 +1,7 @@ -# for server where only admins can connect +# for server where only admins can connect (allowed by default) class access_classes::admin { - pam::multiple_ldap_access { 'admin': - access_classes => ['mga-sysadmin'] + class { 'pam::multiple_ldap_access': + access_classes => [] } } diff --git a/deployment/access_classes/manifests/committers.pp b/deployment/access_classes/manifests/committers.pp index 81dbdb13..37c0e266 100644 --- a/deployment/access_classes/manifests/committers.pp +++ b/deployment/access_classes/manifests/committers.pp @@ -5,9 +5,9 @@ class access_classes::committers { # user, and erase the password ( see pam_auth.c in openssh code, # seek badpw ) # so the file must exist - # permission to use svn, git, etc must be added separatly + # permission to use svn, git, etc must be added separately - pam::multiple_ldap_access { 'committers': + class { 'pam::multiple_ldap_access': access_classes => ['mga-shell_access'], restricted_shell => true, } diff --git a/deployment/access_classes/manifests/iso_makers.pp b/deployment/access_classes/manifests/iso_makers.pp index 21201587..c645205e 100644 --- a/deployment/access_classes/manifests/iso_makers.pp +++ b/deployment/access_classes/manifests/iso_makers.pp @@ -1,5 +1,5 @@ class access_classes::iso_makers { - pam::multiple_ldap_access { 'iso_makers': - access_classes => ['mga-iso_makers','mga-sysadmin'] + class { 'pam::multiple_ldap_access': + access_classes => ['mga-iso_makers'] } } diff --git a/deployment/access_classes/manifests/web.pp b/deployment/access_classes/manifests/web.pp index 45a9992e..fa2c7df5 100644 --- a/deployment/access_classes/manifests/web.pp +++ b/deployment/access_classes/manifests/web.pp @@ -1,5 +1,5 @@ class access_classes::web { - pam::multiple_ldap_access { 'web': - access_classes => ['mga-web','mga-sysadmin'] + class { 'pam::multiple_ldap_access': + access_classes => ['mga-web'] } } diff --git a/deployment/access_classes/manifests/web_and_artwork.pp b/deployment/access_classes/manifests/web_and_artwork.pp deleted file mode 100644 index 9a85bd3d..00000000 --- a/deployment/access_classes/manifests/web_and_artwork.pp +++ /dev/null @@ -1,5 +0,0 @@ -class access_classes::web_and_artwork { - pam::multiple_ldap_access { 'web_artwork': - access_classes => ['mga-web','mga-sysadmin','mga-artwork'] - } -} diff --git a/deployment/backups/manifests/init.pp b/deployment/backups/manifests/init.pp index 1638286d..ba2d16d5 100644 --- a/deployment/backups/manifests/init.pp +++ b/deployment/backups/manifests/init.pp @@ -1,28 +1,23 @@ class backups { class server { - $backups_dir = '/backups' - $confdir = "${backups_dir}/conf" + $backups_dir = '/data/backups' + $confdir = "${backups_dir}/conf" - class { 'rsnapshot::base': - confdir => $confdir, - } + class { 'rsnapshot::base': + confdir => $confdir, + } - file { $backups_dir: - ensure => directory, - owner => root, - group => root, - mode => 700, - } + file { $backups_dir: + ensure => directory, + owner => root, + group => root, + mode => '0700', + } - rsnapshot::backup{ 'alamut': - snapshot_root => "${backups_dir}/alamut", - backup => [ 'root@alamut.mageia.org:/srv/wiki wiki' ], - } - - rsnapshot::backup{ 'krampouezh': - snapshot_root => "${backups_dir}/krampouezh", - backup => [ 'root@krampouezh.mageia.org:/home/irc_bots/meetings meetbot' ], - } + rsnapshot::backup{ 'neru': + snapshot_root => "${backups_dir}/neru", + backup => [ "root@neru.${::domain}:/home/irc_bots/meetings meetbot" ], + } } } diff --git a/deployment/common/manifests/base_packages.pp b/deployment/common/manifests/base_packages.pp index d1509ebd..091e7c3e 100644 --- a/deployment/common/manifests/base_packages.pp +++ b/deployment/common/manifests/base_packages.pp @@ -14,10 +14,10 @@ class common::base_packages { 'lshw', 'lvm2', 'iotop', - 'wget'] + 'wget'] - if $::arch == 'x86_64' { - $package_list += ['mcelog'] + if $::architecture == 'x86_64' { + package { ['mcelog']: } } package { $package_list: } diff --git a/deployment/common/manifests/default_ssh_root_key.pp b/deployment/common/manifests/default_ssh_root_key.pp index 4d4ee524..ab17466d 100644 --- a/deployment/common/manifests/default_ssh_root_key.pp +++ b/deployment/common/manifests/default_ssh_root_key.pp @@ -3,24 +3,34 @@ class common::default_ssh_root_key { user => 'root' } + ssh_authorized_key { 'ssh_key_misc': + # initially removed on 2012-10-17 + ensure => 'absent', + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAABIwAAAgEA4fpjTvcL09Yzv7iV40TPjiXGHOOS5MldSh5ezSk7AMLVjAAloiidl8O3xwlxwUnjUx5zv1+RlbV76sdiSD32lBht72OZPg0UqQIB8nHeVJBdJ8YpnQ3LynNPPYJ65dvdr0uE2KRlN/1emi2N+O+f2apwc1YiL8nySEK/zLvCKO5xj16bIVuGFilDdp75X/t3C/PDsZU+CUyWL5Ly3T2+ljGc+nEAK9P0PNnvl9bRK9dqu457xjca8nXwWVI1fd6Jnt1jISFdQXy6/+9326Z6aAxvWKCrCvmdg+tAUN3fEj0WXZEPZQ1Ot0tBxKYl+xhV1Jv/ILLbInT0JZkSEKNBnJn4G7O4v+syoMqA7myHre73oGn/ocRWGJskIM33aXrJkZkJ4LkF1GLJPFI4y7bzj024sPAVvBwDrV7inwsOy0DSQ5tCbfX25TTXbK+WMXzz0pBbSi6mPgjtzlSYsLZrTa7ARYhggDG2miuOAFrup8vP7/aH2yZ+hZuF70FsMh4lf/eXDGwfypyfYrjfVSkFfY0ZU294ouTBn3HtHmgFu82vOMvLNtI9UyERluCBpLBXOT8xgM97aWFeUJEKrVxkGIiNwVNylMEYp8r16njv810NdTLA3jZu9CLueVvME6GLsGve5idtGmaYuGYNRnSRx3PQuJZl1Nj7uQHsgAaWdiM=', + } + ssh_authorized_key { 'ssh_key_dams': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAACBAP7Dz4U90iWjb8SXVpMsC/snU0Albjsi5rSVFdK5IqG0jcQ3K5F/X8ufUN+yOHxpUKeE6FAPlvDxIQD8hHv53yAoObM4J4h2SVd7xXpIDTXhdQ9kMYbgIQzyI/2jptF77dxlwiH9TirmmpUSb680z55IkVutwSVJUOZCOWFXfa35AAAAFQDqYF7tWvnzM/zeSFsFZ9hqKCj47QAAAIBdmaPCyf4iU9xGUSWi1p7Y6OlUcfu2KgpETy8WdOmZ4lB3MXdGIoK5/LLeLeeGomAVwJMw3twOOzj4e1Hz16WM+fWsMVFnZftLFo9L2LvSQElIEznjIxqfmIsc2Id2c0gI+kEnigOWbBJ7h0O09uT7/eNBysqgseCMErzedy5ZnAAAAIAGrjfWjVtJQa888Sl8KjKM9MXXvgnyCDCBP9i4pncsFOWEWGMWPY0Z9CD0OZYDdvWLnFkrnoMaIvWQU7pb4/u/Tz9Dsm65eQzUaLSGFzROAX6OB47L7spMS4xd6SF+ASawy/aYiHf241zumJLvPkUpXceBv2s7QOp2g6S6qCtypA==', + ensure => 'absent', + type => 'ssh-dss', + key => 'AAAAB3NzaC1kc3MAAACBAP7Dz4U90iWjb8SXVpMsC/snU0Albjsi5rSVFdK5IqG0jcQ3K5F/X8ufUN+yOHxpUKeE6FAPlvDxIQD8hHv53yAoObM4J4h2SVd7xXpIDTXhdQ9kMYbgIQzyI/2jptF77dxlwiH9TirmmpUSb680z55IkVutwSVJUOZCOWFXfa35AAAAFQDqYF7tWvnzM/zeSFsFZ9hqKCj47QAAAIBdmaPCyf4iU9xGUSWi1p7Y6OlUcfu2KgpETy8WdOmZ4lB3MXdGIoK5/LLeLeeGomAVwJMw3twOOzj4e1Hz16WM+fWsMVFnZftLFo9L2LvSQElIEznjIxqfmIsc2Id2c0gI+kEnigOWbBJ7h0O09uT7/eNBysqgseCMErzedy5ZnAAAAIAGrjfWjVtJQa888Sl8KjKM9MXXvgnyCDCBP9i4pncsFOWEWGMWPY0Z9CD0OZYDdvWLnFkrnoMaIvWQU7pb4/u/Tz9Dsm65eQzUaLSGFzROAX6OB47L7spMS4xd6SF+ASawy/aYiHf241zumJLvPkUpXceBv2s7QOp2g6S6qCtypA==', } ssh_authorized_key { 'ssh_key_blino': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAAEBAIuMeFTbzLwcxlKfqSUDmrh2lFVOZyjotQsUm4EGZIh8killmHCBmB8uYvh3ncwvcC8ZwfRU9O8jX6asKJckFIZ37cdHaTQR7fh5ozG4ab652dPND2yKCg1LCwf2x0/Ef1VtyF7jpTG/L9ZaGpeXQ8rykoH4rRnfSdYF0xT7ua9F/J/9ss5FtzQYbQLFMzV3SlXRWp5lzbF4lCyoTyijc8cDrTKeDTu/D5cTpqYxfKUQguGGx0hqUjE3br8r4MPOECqpxAk3gkDr+9mIGftKz07T9aMnHVNNI+hDnjACbbZcG4hZnP99wKmWQ4Pqq7Bten6Z/Hi10E5RiYFyIK8hrR0AAAAVALwhZE/KgdoAM7OV5zxOfOvKrLwJAAABADRU1t5V2XhG07IKgu4PGp9Zgu3v9UkqqPU7F+C8mp2wUw7yTgKaIety8ijShv0qQkF+3YNGj9UnNYeSDWJ62mhMfP6QNQd3RAcbEggPYDjIexoLus44fPGOHtyzvwgSHAGkhBAG9U6GrxTOCUE4ZcZ82r2AdXGzngqnxgvihs9X/thTZu6MuPATueTL6yKShPsFRamgkWmqjJTKP4ggCPHK3FqCiLkrMNbwZ7WECEuodBGou6yCTTGkUXIxGv3/FU96u9FMhqtswClZEElxu+Gajw8gNF8kLnGUSlbubHocfhIAraxfc6s31T+b3Kq6a2JeLhODdgERFM2z/yMbsMMAAAEACqUvqpak3+am+Xz1KOOgTnprpjs8y9cbBU+BzkyhISGNINVSv9fEVEuOIwxW8EZ1gHLORYwAx9onk3WXUKX48DHlMHLwgpahQJnMsuUsJn2QknTiGuML+9MzNrE4ZEoipTEL11UayVcCFYGEB1X0IghX+XmLTGhji6DUBUmepzWN3FXvYMJH50sFLjCok9JszJCgzh8jILp37n8HXgG/FPG5soGG095lHand41s9qdeq4pGchKGDOEia9KAPL6Px5o48dQxxJkMoI8gljFcwVphc0QMmQSqN1paZgnzzwkGp4smuWNxZ+kWdJOceyrlULOsgi9LEkItHZyZtDzufmg==', + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDOyX/M3w0UdN5xwDLpTKj2e7pgXNZIPvWicNkp8BKqEu/ZALJ17QFZro1qrg/fLTsfs15YRMuwQH7MJ9uQsAqyE/aCYt18E/MLdtJSniqdQczSjjCTtB7+KtMh8pXFE5m9KEt0vhutdoB+VoGfbhVaBmjjnDPheM5Qive62askFT0pGlyMdY4PP9q8u10Tiqbb6w0yD7sbtF9GN1HpZBb97YaYyOGu9RpkA+Hb+Ma/faWkbOoP8OIJrGUjhVbSglzKBsEIo/i7+uQ86eMWJHB/o4tN7bU/6QQiGF4pN4E5jKPQHUZsQWI5SAKfkgOEGppYxiMF6pmCdI4Lx9VhttXN', } ssh_authorized_key { 'ssh_key_nanar': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAACBAMLWdzwlo5b9yr1IR5XbbYpESJQpTiZH4gTzVaUIdtbU6S2R41Enn/xZSLgbWcCX79WEcQlfKDS3BcrjWybpwCQD+i1yIA4wmYaQ3KwYBaIsTe5UtPF41hs8Jb8MhTPe9z9hNi5E1R6QQ2wPu3vDAi4zTZ4415ctr6xtW+IDYNOLAAAAFQC9ku78wdBEZKurZj5hJmhU0GSOjwAAAIAeGorkIHQ0Q8iAzKmFQA5PcuuD6X7vaflerTM3srnJOdfMa/Ac7oLV+n5oWj0BhuV09w8dB678rRxl/yVLOgHR9absSicKDkYMZlLU7K1oNFwM4taCdZZ1iyEpJVzzUOVCo8LqK6OZJhbFI0zbarq4YM/1Sr+MIiGv5FK7SCpheAAAAIEAwP95amGY7BgPzyDDFeOkeBPJQA/l7w0dEfG8A+2xui679mGJibhlXiUWqE0NqeDkD17Oc+eOV/ou5DA62tMDSus119JjqYhDEOs0l5dvA6aTzObZDhiUDQbNoS9AIPxgsqdc2vBRxonHUm/7maV8jvWVSy1429CNhnyWKuTe2qU=', + ensure => 'absent', + type => 'ssh-dss', + key => 'AAAAB3NzaC1kc3MAAACBAMLWdzwlo5b9yr1IR5XbbYpESJQpTiZH4gTzVaUIdtbU6S2R41Enn/xZSLgbWcCX79WEcQlfKDS3BcrjWybpwCQD+i1yIA4wmYaQ3KwYBaIsTe5UtPF41hs8Jb8MhTPe9z9hNi5E1R6QQ2wPu3vDAi4zTZ4415ctr6xtW+IDYNOLAAAAFQC9ku78wdBEZKurZj5hJmhU0GSOjwAAAIAeGorkIHQ0Q8iAzKmFQA5PcuuD6X7vaflerTM3srnJOdfMa/Ac7oLV+n5oWj0BhuV09w8dB678rRxl/yVLOgHR9absSicKDkYMZlLU7K1oNFwM4taCdZZ1iyEpJVzzUOVCo8LqK6OZJhbFI0zbarq4YM/1Sr+MIiGv5FK7SCpheAAAAIEAwP95amGY7BgPzyDDFeOkeBPJQA/l7w0dEfG8A+2xui679mGJibhlXiUWqE0NqeDkD17Oc+eOV/ou5DA62tMDSus119JjqYhDEOs0l5dvA6aTzObZDhiUDQbNoS9AIPxgsqdc2vBRxonHUm/7maV8jvWVSy1429CNhnyWKuTe2qU=', } ssh_authorized_key { 'ssh_key_dmorgan': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAACBAOsCjs1EionxMBkyCOXqhDlGUvT/ZORSjqrEhZrro2oPdnMvj3A7IHf1R8+CVVrJlnOHFEwfdC3SB5LYhmUi/XaBq1eqUiVFQLFURrYlrWFh1xSqGUFvvUfMFXOZCn4f9eJYDVaRtWBL7IZCijwZS6bbE0FLW0f6pPzhHtMkSRW/AAAAFQCyg7km5gCZ6W4iRKqr87Wy+LajMwAAAIBZ3+oM/hQ9MS2QkMa8wZk9taEO9PJQHXO3IHyo3wMUj7DYnwgyHQIIeTgPwrE+z0TkM3K3pQlf8xQmsQo7T2kQHCLFZnueEoNB+y+LySLtLDoptYlkqJ9Db0kJti+W8EFc8I+s87HuVdkXpqid222zmRfzYufjbosb8abtGUODXAAAAIBWlhkUEZsbQXkimAnfelHb7EYFnwUgHPSzrzB4xhybma9ofOfM3alZubx9acv94OrAnlvSTfgETKyT0Q+JYvtxZr9srcueSogFq8D8tQoCFJIqpEvjTxjSlg1Fws0zHBH7uO7Kp8zhnuTalhQC1XorFPJD3z40fe62fO6a02EUCQ==', + ensure => 'absent', + type => 'ssh-dss', + key => 'AAAAB3NzaC1kc3MAAACBAOsCjs1EionxMBkyCOXqhDlGUvT/ZORSjqrEhZrro2oPdnMvj3A7IHf1R8+CVVrJlnOHFEwfdC3SB5LYhmUi/XaBq1eqUiVFQLFURrYlrWFh1xSqGUFvvUfMFXOZCn4f9eJYDVaRtWBL7IZCijwZS6bbE0FLW0f6pPzhHtMkSRW/AAAAFQCyg7km5gCZ6W4iRKqr87Wy+LajMwAAAIBZ3+oM/hQ9MS2QkMa8wZk9taEO9PJQHXO3IHyo3wMUj7DYnwgyHQIIeTgPwrE+z0TkM3K3pQlf8xQmsQo7T2kQHCLFZnueEoNB+y+LySLtLDoptYlkqJ9Db0kJti+W8EFc8I+s87HuVdkXpqid222zmRfzYufjbosb8abtGUODXAAAAIBWlhkUEZsbQXkimAnfelHb7EYFnwUgHPSzrzB4xhybma9ofOfM3alZubx9acv94OrAnlvSTfgETKyT0Q+JYvtxZr9srcueSogFq8D8tQoCFJIqpEvjTxjSlg1Fws0zHBH7uO7Kp8zhnuTalhQC1XorFPJD3z40fe62fO6a02EUCQ==', } ssh_authorized_key { 'ssh_key_coling': @@ -29,22 +39,53 @@ class common::default_ssh_root_key { } ssh_authorized_key { 'ssh_key_boklm': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAACBAIGfoferrHXi7m8Hw3wY3HzIvWzlBKRu4aUpOjFgFTw+aPiS842F8B2bqjzUyLVAv13zHB5QjVeAB0YQ1TvMQbew+7CRAgAVWrY/ckMJxSdNk6eKnxlnLA295xBnyc+jdMhdTKisywtlkLP6Au+2eA/sDKELO8tiIQzSUithppU/AAAAFQCP/IlvpJjhxQwgA4UW1Mg7W3MPVwAAAIAc8BA7W9qDaA8/sQiOu6sSueEVnf7QmJzTJuT0ZJ9HDSB39+fQrwjPZqxiTpAfSboBTC0KiuG9ncCZyh6fAmn2i9WSZ6HYkoLBjHU3nu3u18qlT8LqwajUjgp15jgUKWB8OxvO1dPNaLEsvP1BKPTfDoPNPeUeQmb3WaX9S+pVGwAAAIA63gRktdobLeeuRFAfPdQQ7Imi1GwrfKa2QUgowksDxwgBBo796HN41+yF0W2AOZ2lx25KQRF0Wgc5Abm/TV8u3WbzosYbZgUBiGDqyVhIPU/xF+yPEHPYx3G3nwjEZAaxxf+LaeZkY1Yp15O6NAZAzdyV00iG/tO/ciWBPCMeJA==', + # requested by boklm on 2014-03-23 + ensure => 'absent', + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAACAQD4dKlLuPipueSWeX70QbrQ88tSVcfW4efoHS2vYmqbe5VE73yOCLFemDb3yk8PNxsCV5KIIesdKq6uRYiUKfCKJsF+UnFRdTniETsI3gmr895mvJMgdxuYCCRqdhjyKfWSds11cptBJpw2eXpsY6O5GPqVYG23/DWH4sNCFMawek9dWZy21qcGSjyXayek0nqXBLRv1SVNdipMeLVa99haOHViIV+gmqe3FKqT1UsNBSUQ9BdwtN9rvM2Qo1WYgptFffWRmYicSSbJSf8ru0sRcsD2hknlA0Eu5CO7dKD0Nc2cXsuwkiQXW+QKMduB5SGznyRpRBMIPKr1mnwLKEWXlMppgfzoI06xfqmasJZfvtR/dNQ5ugl+8J+AlPo/tegNNrHzzmplx7118kMgqBnYg9zjkju1iv9RblAcWitKjEN+zL795nmkbIPD+bo1Ql/YkMe9bGTHB3isHAAtzvjWHatyKzyq3D/k8+tJxSy91a9JIX5sHvnBev4VrzV+JE7QAT//9ELaG93bIljn8pDKKxjiNexjwiKpDRSB2AAWAMf7Qm3FBXrwfoIsREfGrPAjKsU1YUKC27xBDKSLE2ThqhkSYRKeNoECB5Ab7MhbNx8/sXI/y6YboDnFlFkXSht9WklCiGXpf36F0ei0oiA5O+v4TU6ix/WWrpnTazicKw==', } ssh_authorized_key { 'ssh_key_buchan': - type => 'ssh-dss', - key => 'AAAAB3NzaC1kc3MAAACBALpYDQtkZcfXdOILynCGa7IAbW4+etmzpIMjw6BfvZOfLT6UPfDwajhDBMBNSbgigxkxxEdsa0/UMIE3Yrpr8YivhbL79sFw2N/FeWCs3Vk8JXNjBGA6itAIz9nwfh6qCDUj2t8LTdOQdYrSFOO7x2dFgeCwi21V27Ga2vqsvkUnAAAAFQD708pfON6Itq/5S+4kkNdNNDKWCwAAAIEAkRQeugul6KmOC0C2EmgVJvKK1qImlwHir08W1LTESnujmRIWLRst8sDoKjJpNevFuHGybPQ3palvM9qTQ84k3NMsJYJZSjSexsKydHJbD4ErKk8W6k+Xo7GAtH4nUcNskbnLHUpfvzm0jWs2yeHS0TCrljuTQwX1UsvGKJanzEoAAACBAIurf3TAfN2FKKIpKt5vyNv2ENBVcxAHN36VH8JP4uDUERg/T0OyLrIxW8px9naI6AQ1o+fPLquJ3Byn9A1RZsvWAQJI/J0oUit1KQM5FKBtXNBuFhIMSLPwbtp5pZ+m0DAFo6IcY1pl1TimGa20ajrToUhDh1NpE2ZK//8fw2i7', + ensure => 'absent', + type => 'ssh-dss', + key => 'AAAAB3NzaC1kc3MAAACBALpYDQtkZcfXdOILynCGa7IAbW4+etmzpIMjw6BfvZOfLT6UPfDwajhDBMBNSbgigxkxxEdsa0/UMIE3Yrpr8YivhbL79sFw2N/FeWCs3Vk8JXNjBGA6itAIz9nwfh6qCDUj2t8LTdOQdYrSFOO7x2dFgeCwi21V27Ga2vqsvkUnAAAAFQD708pfON6Itq/5S+4kkNdNNDKWCwAAAIEAkRQeugul6KmOC0C2EmgVJvKK1qImlwHir08W1LTESnujmRIWLRst8sDoKjJpNevFuHGybPQ3palvM9qTQ84k3NMsJYJZSjSexsKydHJbD4ErKk8W6k+Xo7GAtH4nUcNskbnLHUpfvzm0jWs2yeHS0TCrljuTQwX1UsvGKJanzEoAAACBAIurf3TAfN2FKKIpKt5vyNv2ENBVcxAHN36VH8JP4uDUERg/T0OyLrIxW8px9naI6AQ1o+fPLquJ3Byn9A1RZsvWAQJI/J0oUit1KQM5FKBtXNBuFhIMSLPwbtp5pZ+m0DAFo6IcY1pl1TimGa20ajrToUhDh1NpE2ZK//8fw2i7', } ssh_authorized_key { 'ssh_key_tmb': + ensure => 'absent', type => 'ssh-dss', key => 'AAAAB3NzaC1kc3MAAACBAMFaCUsen6ZYH8hsjGK0tlaguduw4YT2KD3TaDEK24ltKzvQ+NDiPRms1zPhTpRL0p0U5QVdIMxm/asAtuiMLMxdmU+Crry6s110mKKY2930ZEk6N4YJ4DbqSiYe2JBmpJVIEJ6Betgn7yZRR2mRM7j134PddAl8BGG+RUvzib7JAAAAFQDzu/G2R+6oe3vjIbbFpOTyR3PAbwAAAIEAmqXAGybY9CVgGChSztPEdvaZ1xOVGJtmxmlWvitWGpu8m5JBf57VhzdpT4Fsf4fiVZ7NWiwPm1DzqNX7xCH7IPLPK0jQSd937xG9Un584CguNB76aEQXv0Yl5VjOrC3DggIEfZ1KLV7GcpOukw0RerxKz99rYAThp6+qzBIrv38AAACBAKhXi7uNlajescWFjiCZ3fpnxdyGAgtKzvlz60mGKwwNyaQCVmPSmYeBI2tg1qk+0I5K6LZUxWkdhuE1UfvAbIrEdwyD8p53dPg1J9DpdQ1KqApeKqLxO02KJtfomuy3cRQXmdfOTovYN7zAu1NCp51uUNTzhIpDHx0MZ6bsWSFv', } + ssh_authorized_key { 'ssh_key_tmb_rsa': + ensure => 'absent', + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAACAQC+PaVLUaIvBg/lDK0esX2xvVe9IspiXq2ES4Ti/KvmTqbsAhgUuW+IR4fxY2vffCdbTo2B247bEh4kTB8P+ZKmrJPv/c18CtidJHKXpV4EwEAD3abeKKYcUlDXyX0zTER64d86yT0PN2eA9BJNfpZeVCMpn32C7tYBzQztp1FVJB+i2oslayKE4Q9FRxpJFzhvepOsUC4ZnePSz7ymeg4Y6vgWjoH9Eo33FSJ0fEm8+/bk8kir9X1wu+BbfQodnkS6wTehXqb0hj1uNIkngy+nA+T+ckhhddlRELKYt44VMp/X8wtCE7Y8nLOi15sQiSIgtrXDIdwoIzfyLKZM1/fH/pYAKL/tjhomHgzSWeyHNA+gFT6B868tnBkSaBMfdAJmNu7RfAobFWmTHp2dF2Q5AsbzqFBWcofO3qvrP1xvz5Ckp+GzmflXdqg2M7XXNP5G1NAAq5dsMGRUBN99xYF25EpmDjbPaSXUDbvtzGY4B2Doc3OhR6Ask4undDvj+oOJw4Ldi9q4xexl1L9P0DbbfGhl/d/0T5snnagIAgXOZvG8Nwywzhv4oIoM2o6C1HNiUea3ODHMMl8f7w0ofDoX7JH4gQvRxgPRniZgBKSTDl7fD0Fh5FAZ6KbcZ2VCit8pLZN0OVHOr7kNBvsRClLe8O8R4S0wACe44U2Jq2U+6Q==', + } + ssh_authorized_key { 'ssh_key_pterjan': type => 'ssh-rsa', key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEAspyZMl5zAkk5SL45zFvtJF7UhXTRb0bEaZ3nuCC1Ql5wM3GWuftqd5zLH88dCu7ZO/BVh213LZTq/UHb6lI7kWalygk53qtdEx2cywjWFOW23Rg6xybatCEZ2/ZrpGZoBGnu63otAp4h2Nnj/VkOio3pGwD8vavmZ4xPrcECPAwtMPJsYf44Ptu2JdXizi4iY8I0/HKitQ113I4NbDcAiMKbTXSbOfqC+ldcgW3+9xShx/kuMFTKeJOy4LI4GR6gykzkV6+vfnalp24x/SIEjuohBarCRQKo4megHqZOzdMYAHqq0QuNubXURNb0Mvz1sE7Y8AFIxwSfXdQGi5hcQQ==', } + + ssh_authorized_key { 'ssh_key_neoclust': + ensure => 'absent', + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDGyI8oIP8SgahPbMZ04Msr/vnI2gf4yx//QhEnZv8b++WIH0oibfK8g5Lz4HXReJRHzNXN1EhKQXoClgAKwv7zqkTLxV44tVcz8cwvfldkKNB+QxfL74JgsxCyNW8mpJdrJ71kbkT4Jt6AxeEd10ltQyqT7QDQMM7fxH8dbOCMcc7jtgOqwPXLy7hEumqkYxNuMxjrAbiDk2Nx0ddP2Ta4NJjSsGzUzSPsGhLVCO3+Wv6Ymss9Vacbe684ERwqz6odi5ZX0utfXXNphqqAckKCxurrI+LoWzt9MgWtR9iJC1joVDqRbggNm6bNNPZIdhmi5/yJrk3x7qwXb7uQNiE7', + } + + ssh_authorized_key { 'ssh_key_maat': + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAACAQDNQqKZkAhPiMFoeE3uqioaTFLDAP6cTwBsRA7angVMDpAThbYxGK439oe3xaj/cgGrlEApAnCmEPL81in6hubQaTRMR/RigA3FEkoO3H/J2Xng1rD+aVQFFK0EerjzxDa+bxUu7eRcHv1ar49LY7spNjk0LzNtI/n32L+t3WifCE/ithHi80Qh2kMq36kTm10wW4Gxpz9tYzSQz/f7dfrzhX+yOVUbmnevuS1BDeF21hmxmltBFQZvBh3jiUiWeTMHePHaod8jI8voJkxXJ+TxsniJ3AfxgCaMmIoU0a0rBxeTpzQVkUHJUsmsmji8WdeW9J9gNwXYYv2PuSli8iz5mAWG0eo6y2W+tOHNy6RhvcIkPi4pViycxBjQvoxki5nCZDXo1KwWCYoJ0wg5YIrqdqBb70ibAqMOS1wXSO5KwWbUoVYrP+tSvz+i1EQtgEHtamgCzFAkJXQrjXhvJ/L1GVJLsvqTpee+kN/9NnbH8GnHKvnenvE7ecITcMoy8hODulYaqZrx+0jWivTv5UpHO7gX9RwsDB2nviT4rluYWjIugIjCnBJIroD1QP6UWFFwG6MM44QPaByXjz8AC7vw1fNefhWFmS+CT7dQ8Vd2zglP4gQwlWePTC8sASHDLSoe0nIXGXcfY2Af8bThV1fMEteI850thUvIKfrx34z4rw==', + } + + ssh_authorized_key { 'ssh_key_wally': + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEAsB/PAEQJE/M5c3keyef6rKQvCtTk5cdw6ujXl6n8G7D7Q6h4IgIccd5mYcBU7ij2S5N3lfOQmKJqf2Pa5pByLfXlQnhCLzsgL9X45WJmpsoVK1MzjDY8iY+aL/74tj3wiMzuzAAwwpE3EftyfscxhSwf2e11B3qDzVRmNnxPVKlm85nTygnrZ0ag4nOC6O4yC3Hh1ULhKGtNAsGNF2yRGs7IcN9ytcVhGF3WGJfRI2c2kIuKW/lXxeE04sWWb+k019ys4ah0iQoLja6xVSHgxbVlm3oDz+mGGsPtoSvtoWpvF3q9FKqGclJpboWRMo3jyP6yDRVcTMXUSONmq3N8uw==', + } + + ssh_authorized_key { 'ssh_key_danf': + type => 'ssh-rsa', + key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQCgWFg4EsUkZ5uh34ScVbfwhVdP7kTLRwsojeF+DgmwXSPbM9NUxiCmyFrHuh3m6bxG3BPMwrDskqUrQ3z/5WX6dB/CzSP/j03EkslzaE7eTzIpGt/vKIuZHR+4Z9FZcY1pyoI44rdgW5MVC+yBoJkvBerOkvNzfiRSfQ9R4eopPNTif3vb4MP/cFzFfa3o8NMqHxhgGFhF945NlzCUmnec13sNggx1wGNFHMpWttSaQ0izgvSdb61WSswNnCjBF5t3oyh7DgI80TN/XfXfDWZPjkQUzLrh9inuPollAWfreeInoCmF8ou268efaRoSfRMZ3qdRkJLDDy2Os8eL/d3d', + } } diff --git a/deployment/common/manifests/i18n.pp b/deployment/common/manifests/i18n.pp index 9ef731ad..43b1fc3a 100644 --- a/deployment/common/manifests/i18n.pp +++ b/deployment/common/manifests/i18n.pp @@ -1,8 +1,12 @@ class common::i18n { package { 'locales-en': } - # push the locale everywhere, as it affect facter + # push the locale everywhere, as it affects facter file { '/etc/sysconfig/i18n': content => template('common/i18n'), } + + file { '/etc/locale.conf': + content => template('common/locale.conf'), + } } diff --git a/deployment/common/manifests/init.pp b/deployment/common/manifests/init.pp index acdaea7e..c7b7486d 100644 --- a/deployment/common/manifests/init.pp +++ b/deployment/common/manifests/init.pp @@ -8,6 +8,7 @@ class common { include common::export_ssh_keys include common::import_ssh_keys include common::i18n + include common::sudo_sysadmin include ntp include common::urpmi_update include puppet::client @@ -19,6 +20,11 @@ class common { file { '/srv/': ensure => directory } + + host { "${::hostname}.${::domain}": + ip => '127.0.0.1', + host_aliases => [ "${::hostname}", 'localhost' ], + } } class default_mageia_server inherits default_mageia_server_no_smtp { diff --git a/deployment/common/manifests/sudo_sysadmin.pp b/deployment/common/manifests/sudo_sysadmin.pp new file mode 100644 index 00000000..1247c02c --- /dev/null +++ b/deployment/common/manifests/sudo_sysadmin.pp @@ -0,0 +1,7 @@ +class common::sudo_sysadmin { + include sudo + + sudo::sudoers_config { '00-sysadmin': + content => template('common/sudoers.sysadmin') + } +} diff --git a/deployment/common/templates/locale.conf b/deployment/common/templates/locale.conf new file mode 100644 index 00000000..e9fc2e06 --- /dev/null +++ b/deployment/common/templates/locale.conf @@ -0,0 +1,20 @@ +<%- +# should not be changed +locale = 'en_US.UTF-8' + +-%> +LC_TELEPHONE=<%= locale %> +LC_CTYPE=<%= locale %> +LANGUAGE=<%= locale %>:<%= locale.split('.')[0] %>:<%= locale.split('.')[0].split('_')[0] %> +LC_MONETARY=<%= locale %> +LC_ADDRESS=<%= locale %> +LC_COLLATE=<%= locale %> +LC_PAPER=<%= locale %> +LC_NAME=<%= locale %> +LC_NUMERIC=<%= locale %> +LC_MEASUREMENT=<%= locale %> +LC_TIME=<%= locale %> +LANG=<%= locale %> +LC_IDENTIFICATION=<%= locale %> +LC_MESSAGES=<%= locale %> + diff --git a/deployment/common/templates/sudoers.sysadmin b/deployment/common/templates/sudoers.sysadmin new file mode 100644 index 00000000..874b1858 --- /dev/null +++ b/deployment/common/templates/sudoers.sysadmin @@ -0,0 +1 @@ +%mga-sysadmin ALL=(ALL) ALL diff --git a/deployment/dns/manifests/reverse_zone.pp b/deployment/dns/manifests/reverse_zone.pp index 264830c7..9095251d 100644 --- a/deployment/dns/manifests/reverse_zone.pp +++ b/deployment/dns/manifests/reverse_zone.pp @@ -1,5 +1,5 @@ define dns::reverse_zone { bind::zone::reverse { $name: - content => template("dns/$name.zone") + content => template("dns/${name}.zone") } } diff --git a/deployment/dns/manifests/zone.pp b/deployment/dns/manifests/zone.pp index c11f7d02..7d4da311 100644 --- a/deployment/dns/manifests/zone.pp +++ b/deployment/dns/manifests/zone.pp @@ -1,5 +1,5 @@ define dns::zone { bind::zone::master { $name: - content => template("dns/$name.zone") + content => template("dns/${name}.zone") } } diff --git a/deployment/dns/templates/2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa.zone b/deployment/dns/templates/2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa.zone index 166408b4..8ab67138 100644 --- a/deployment/dns/templates/2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa.zone +++ b/deployment/dns/templates/2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa.zone @@ -1,10 +1,10 @@ $TTL 3D @ IN SOA ns0.mageia.org. root.mageia.org. ( - 2012110200 ; Serial + 2024090202 ; Serial 3600 ; Refresh 3600 ; Retry - 2419200 ; Expire - 86400 ; Minimum TTL + 3600000 ; Expire + 3600 ; Minimum TTL ) ; nameservers diff --git a/deployment/dns/templates/7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa.zone b/deployment/dns/templates/7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa.zone index 8a7007df..fdb83e63 100644 --- a/deployment/dns/templates/7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa.zone +++ b/deployment/dns/templates/7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa.zone @@ -1,10 +1,10 @@ $TTL 3D @ IN SOA ns0.mageia.org. root.mageia.org. ( - 2012092801 ; Serial + 2024090202 ; Serial 3600 ; Refresh 3600 ; Retry - 2419200 ; Expire - 86400 ; Minimum TTL + 3600000 ; Expire + 3600 ; Minimum TTL ) ; nameservers @@ -12,10 +12,8 @@ $TTL 3D @ IN NS ns1.mageia.org. 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR gw-ipv6.mageia.org. -2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR alamut.mageia.org. -3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR valstar.mageia.org. 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR ecosse.mageia.org. -5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR jonund.mageia.org. 6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR fiona.mageia.org. 7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR sucuk.mageia.org. 8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR rabbit.mageia.org. +9.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR duvel.mageia.org. diff --git a/deployment/dns/templates/mageia.fr.zone b/deployment/dns/templates/mageia.fr.zone deleted file mode 100644 index 70ecc840..00000000 --- a/deployment/dns/templates/mageia.fr.zone +++ /dev/null @@ -1,27 +0,0 @@ -; cfengine-distributed file -; local modifications will be lost -; $Id$ -$TTL 3D -@ IN SOA ns0.mageia.org. mageia.fr. ( - 2010110200 ; Serial - 21600 ; Refresh - 3600 ; Retry - 2419200 ; Expire - 86400 ; Minmun TTL - ) - -; nameservers -@ IN NS ns0.mageia.org. -@ IN NS ns1.mageia.org. - -@ IN MX 10 mx0.zarb.org. -@ IN MX 20 mx1.zarb.org. - -; MX -;@ IN MX 10 mx0.zarb.org. - -; machines -mageia.fr. IN A 212.85.158.22 - -; aliases -www IN CNAME mageia.fr. diff --git a/deployment/dns/templates/mageia.org.zone b/deployment/dns/templates/mageia.org.zone index 69b43b75..a04ca19b 100644 --- a/deployment/dns/templates/mageia.org.zone +++ b/deployment/dns/templates/mageia.org.zone @@ -1,138 +1,174 @@ +<%- + # nodes list defined in puppet/manifests/nodes_ip.pp + nodes = scope.lookupvar('::nodes_ipaddr') +-%> ; puppet-distributed file ; local modifications will be lost ; $Id$ -$TTL 1h +$TTL 30m @ IN SOA ns0.mageia.org. root.mageia.org. ( - 2012110200 ; Serial - 21600 ; Refresh + 2025100701 ; Serial + 7200 ; Refresh 3600 ; Retry - 2419200 ; Expire - 86400 ; Minmun TTL + 3600000 ; Expire + 300 ; Minimum TTL ) ; nameservers @ IN NS ns0.mageia.org. @ IN NS ns1.mageia.org. -@ IN MX 10 mx0.zarb.org. -@ IN MX 20 mx1.zarb.org. +@ IN MX 10 sucuk.mageia.org. +@ IN MX 20 neru.mageia.org. + +; DKIM for mageia.org +sucuk._domainkey IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGH25Jb2Al84XlTfSWuqZL8f6K6b+QhJjvV3zbF1/t31WmLwEt0So+p3FbFeKmaq/e0nJ+wKteTSVZsl3xwux+MaARKJDpEXslEgy+ojCedWqqpP6xLUjPuYPimGPljwkLwDoJxwvjiLa2POebec7C+R/nzaGm2nnTFwYQomqlvQIDAQAB" +sucuk._domainkey.group IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBRrdmAaYpDBHCtzkephaLX9LrMFJvgq84dS0ogTIb0xD32qxQF69FU/gEUlfTjzJooTJQC3PK7R3oLnfoWttMlbHCGg/llSfoSI0gD/4UolZokzWZY3qdqMz+zKi9+bfjz0y4Fwx5EPyda1ihHhVB6c+wq6cekhDNOH8PHhO74QIDAQAB" +sucuk._domainkey.duvel IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHYgFMZTHMYlymX0WJ17ZvgchABE+5O/c6np1gj5sBV2BPIJGs+h/i+Iq6jLYVhSOWEI+6wQKza/8r3Vr4ddi3/UPDzllfqMnKsbPHC/LscyIkQmpNiO2n0nIUhKbuVU1SsRC1B8svO9iNmEjg33/lrLiaV3DtDbGr0ozmBmeFVwIDAQAB" +sucuk._domainkey.fiona IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDeFoY9MTeZD4Z3OnxUJvp6Nr5UF6+rBwCg0TwVWwe/17uCQ4M6ptDxPSGgVIMYJowg/VUcbqNLlt56kluC4mO/gVVUyPQe6EjYib+NV5PkvgHx2TOJfb27ANPiZ4f57eEFqmE3eD7SxqUqF9j2Vobt0J+XgFuyFUBzHZsRTNUpzQIDAQAB" +sucuk._domainkey.forums IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEVhhONroS/ayEPs+9fmom34EWsny7asKVxIuyJh8EzvPJmx6ODYtX/tN1ul++3xoFNHeAe5YSSGyK+7EgJ5E5wlhw6FwnHPnYp/eMsShDI2dyfYsQnS2Yc1VXkI9s83ZWaVTL9uPRDETMKDIF+QjljFQZAN+eaH55q9u3EZRrWwIDAQAB" +sucuk._domainkey.identity IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBv4aqFb9cQQkPB30zRfCtcquWKsP5G2Nhh3HSEdN0fFvOegQnGykuGq6lDED9iJuiNSVGO2cjtWtFTwX3+1/W1AW7pmaUD7U9HzPoZgxGPWtvFcJ/tZ1mjKNoGaPa5vLaVpXwxNKjPUCI+w2t5cM8JPnemW1Vm/LeEJ0XLE0InwIDAQAB" +sucuk._domainkey.madb IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI9WOO3aRQLLnXc08q9HP15VY79TQZR5GqdBcYu0H+jAiuR+OKz6NUSNoYdeNQ4FSvrz27elW6thNcKQg4wYNT4tsJ8d4OU5ScFcrPJszPucVyMpkl/ybCgVq0CmXgOh1yXYwl2YY4AfzUQ6skpTE5G2abIWBvPOvs8Q92vYJ1nwIDAQAB" +sucuk._domainkey.rabbit IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZYdG5dEd0CHAYGPRG+OXm2gJTDVpjmsKkn5+4BISToAOXXyogRcJN/P6oPySlG+CyUl5PW/2nBIiiUfHNKxVSa9gPO3vS0nlEppSHulkhth4deNu8YXRgJQp31IgaD0/Cbu7CKcDJbxTKGdnMV7XPKoIxB/Mjn0TxUS+WC2WY6QIDAQAB" +sucuk._domainkey.sucuk IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdzn4W4Tl4sJ0pfhktNVlWRYFXnIwaMENqmi2vgc/P8M/zVxysVuWPcEwhy+IiVT8tMleXMt9dreErzJS+8ZmMd8oTqRXM55ZzRuBtqiecKnbIrXpecYUhh+2o0BMouTRHZvrPK5PV6Y2PrXkXwLF8qOS/eslZDk7hLRk2XBVDWwIDAQAB" +sucuk._domainkey.ml IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4uPUsb1kvNCXT1AsEBldhU/9akmeRrRHOQtI8g60K+y2fRRur5l+TJDZ/+bnyVS69AMhyfeWEaWGhQytvmkKZBQyHZ6JzS2him+HT/x7xCYOHlQ5vixy0t4jYqbYZ04pdokJ4jcJ3pU7CFisgzk2Ln7HA4JDD1Dc+kCYbOvivtQIDAQAB" +sucuk._domainkey.neru IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4uPUsb1kvNCXT1AsEBldhU/9akmeRrRHOQtI8g60K+y2fRRur5l+TJDZ/+bnyVS69AMhyfeWEaWGhQytvmkKZBQyHZ6JzS2him+HT/x7xCYOHlQ5vixy0t4jYqbYZ04pdokJ4jcJ3pU7CFisgzk2Ln7HA4JDD1Dc+kCYbOvivtQIDAQAB" ; TODO use a loop here -ml IN MX 10 alamut.mageia.org. -ml IN MX 20 krampouezh.mageia.org. +ml IN MX 10 sucuk.mageia.org. +ml IN MX 20 neru.mageia.org. -group IN MX 10 alamut.mageia.org. -group IN MX 20 krampouezh.mageia.org. +; Sender Policy Framework for mailing lists & some automated mails +@ IN TXT "v=spf1 include:smtp.dnamail.fi mx ~all" +ml IN TXT "v=spf1 mx ~all" +group IN TXT "v=spf1 mx ~all" +group IN MX 10 sucuk.mageia.org. +group IN MX 20 neru.mageia.org. -; MX -;@ IN MX 10 mx0.zarb.org. ; machines -;mageia.org. IN A 212.85.158.22 -; mageia.org set to IP of champagne : -mageia.org. IN A 217.70.188.116 -www-zarb IN A 212.85.158.22 - -krampouezh IN A 95.142.164.207 -krampouezh IN AAAA 2001:4b98:dc0:51:216:3eff:fe6b:4ea9 - -champagne IN A 217.70.188.116 -champagne IN AAAA 2001:4b98:dc0:41:216:3eff:fe4f:5a18 - -; lost oasis -alamut IN A 212.85.158.146 -alamut IN AAAA 2a02:2178:2:7::2 -alamut IN SSHFP 1 1 ef093dc95002c4af6623f02238749fd59fe81eec -alamut IN SSHFP 2 1 179cfa0660550698c4d98f488772b7c7896d96b5 +<%- + nodes_txt = '' + nodes.keys.sort.each{|nodename| + spf = '' + if nodes[nodename].has_key?('ipv4') + nodes_txt += nodename + ' IN A ' + nodes[nodename]['ipv4'] + "\n" + spf += ' ip4:' + nodes[nodename]['ipv4'] + end + if nodes[nodename].has_key?('ipv6') + nodes_txt += nodename + ' IN AAAA ' + nodes[nodename]['ipv6'] + "\n" + spf += ' ip6:' + nodes[nodename]['ipv6'] + end + nodes_txt += nodename + ' IN TXT "v=spf1 ' + spf + ' mx:mageia.org ~all" ' + "\n" + } +-%> +<%= nodes_txt %> + +;SSHFP + +; sucuk +ns0 IN A <%= nodes['sucuk']['ipv4'] %> +ns0 IN AAAA <%= nodes['sucuk']['ipv6'] %> +; neru +ns1 IN A <%= nodes['neru']['ipv4'] %> +ns1 IN AAAA <%= nodes['neru']['ipv6'] %> + +; mageia.org set to IP of neru +mageia.org. IN A <%= nodes['neru']['ipv4'] %> +mageia.org. IN AAAA <%= nodes['neru']['ipv6'] %> + +; madb on mageia.madb.org +;madb IN A 163.172.201.211 +; temporarily for hosting a redirect while the real madb is down +madb IN CNAME neru + ; since we have a subdomain, we cannot use a CNAME -ml IN A 212.85.158.146 -ml IN AAAA 2a02:2178:2:7::2 -; mga torrent server and tracker -torrent IN A 212.85.158.146 -torrent IN AAAA 2a02:2178:2:7::2 - -valstar IN A 212.85.158.147 -valstar IN AAAA 2a02:2178:2:7::3 -valstar IN SSHFP 1 1 f08e336f678d7c4a8772f17770976af7dd4d7a4f -valstar IN SSHFP 2 1 c0c45ed25aa8a9f1723a1ae077dcee61677a56a6 - -ecosse IN A 212.85.158.148 -ecosse IN AAAA 2a02:2178:2:7::4 -jonund IN A 212.85.158.149 -jonund IN AAAA 2a02:2178:2:7::5 -fiona IN A 212.85.158.150 -fiona IN AAAA 2a02:2178:2:7::6 -sucuk IN A 212.85.158.151 -sucuk IN AAAA 2a02:2178:2:7::7 -rabbit IN A 212.85.158.152 -rabbit IN AAAA 2a02:2178:2:7::8 - -arm1 IN A 10.42.0.51 -arm2 IN A 10.42.0.52 - -; alamut -ns0 IN A 212.85.158.146 -; krampouezh -ns1 IN A 95.142.164.207 +ml IN A <%= nodes['sucuk']['ipv4'] %> +ml IN AAAA <%= nodes['sucuk']['ipv6'] %> ; aliases -;www IN CNAME www-zarb -www IN CNAME champagne -www-test IN CNAME champagne -static IN CNAME champagne -start IN CNAME champagne -blog IN CNAME champagne -planet IN CNAME champagne -hugs IN CNAME champagne -releases IN CNAME champagne -dashboard IN CNAME champagne -nav IN CNAME champagne -doc IN CNAME champagne -rsync IN CNAME valstar - -svn IN CNAME valstar -git IN CNAME valstar -meetbot IN CNAME krampouezh - -tmp IN CNAME alamut - -puppetmaster IN CNAME valstar -puppet IN CNAME valstar -pkgsubmit IN CNAME valstar -binrepo IN CNAME valstar -repository IN CNAME valstar -maintdb IN CNAME valstar -ldap IN CNAME valstar - -ldap-master IN CNAME valstar -ldap-slave-1 IN CNAME krampouezh - -identity IN CNAME alamut -identity-trunk IN CNAME alamut -mirrors IN CNAME alamut -epoll IN CNAME alamut -pgsql IN CNAME alamut -bugs IN CNAME alamut -transifex IN CNAME alamut -svnweb IN CNAME alamut -xymon IN CNAME alamut -check IN CNAME alamut -wiki IN CNAME alamut -gitweb IN CNAME alamut -pkgcpan IN CNAME alamut -perl IN CNAME alamut -tmp IN CNAME alamut - +ldap-slave-1 IN CNAME neru + +archives IN CNAME neru +blog IN CNAME neru +dashboard IN CNAME neru +doc IN CNAME neru +hugs IN CNAME neru +meetbot IN CNAME neru +planet IN CNAME neru +releases IN CNAME neru +start IN CNAME neru +static IN CNAME neru +www-test IN CNAME neru + +rsync IN CNAME duvel +svn IN CNAME duvel +git IN CNAME duvel +puppetmaster IN CNAME duvel +puppet IN CNAME duvel +pkgsubmit IN CNAME duvel +binrepo IN CNAME duvel +repository IN CNAME duvel +maintdb IN CNAME duvel +ldap IN CNAME duvel +ldap-master IN CNAME duvel +advisories IN CNAME duvel +projects IN CNAME duvel bcd IN CNAME rabbit +epoll IN CNAME sucuk +forums IN CNAME sucuk +forum IN CNAME sucuk + +send IN CNAME sucuk +bugs IN CNAME sucuk +check IN CNAME sucuk +gitweb IN CNAME sucuk +identity IN A <%= nodes['sucuk']['ipv4'] %> +identity-trunk IN CNAME sucuk +mirrors IN CNAME sucuk +nav IN CNAME sucuk +people IN CNAME sucuk +perl IN CNAME sucuk +pg IN CNAME sucuk +pkgcpan IN CNAME sucuk +svnweb IN CNAME sucuk +treasurer IN CNAME sucuk +wiki IN CNAME sucuk +www IN CNAME sucuk +xymon IN CNAME sucuk + ; build nodes aliases -jonund0 IN CNAME jonund -jonund1 IN CNAME jonund ecosse0 IN CNAME ecosse ecosse1 IN CNAME ecosse - -; temporary, until the vm is moved elsewhere -forums IN CNAME alamut -forum IN CNAME alamut -;wiki IN A 88.191.83.84 +rabbit0 IN CNAME rabbit +rabbit1 IN CNAME rabbit +rabbit2 IN CNAME rabbit +ec2aa1-a IN CNAME ec2aa1 +ec2aa1-b IN CNAME ec2aa1 +ec2aa2-a IN CNAME ec2aa2 +ec2aa2-b IN CNAME ec2aa2 +ec2aa3-a IN CNAME ec2aa3 +ec2aa3-b IN CNAME ec2aa3 +ec2x1-a IN CNAME ec2x1 +ec2x1-b IN CNAME ec2x1 +ec2x2-a IN CNAME ec2x2 +ec2x2-b IN CNAME ec2x2 +pktaa1-a IN CNAME pktaa1 +pktaa1-b IN CNAME pktaa1 +pktaa1-c IN CNAME pktaa1 +pktaa1-d IN CNAME pktaa1 +pktaa1-e IN CNAME pktaa1 +pktaa1-f IN CNAME pktaa1 +ociaa1-a IN CNAME ociaa1 +ociaa1-b IN CNAME ociaa1 +ociaa1-c IN CNAME ociaa1 +ociaa2-a IN CNAME ociaa2 +ociaa2-b IN CNAME ociaa2 +ociaa2-c IN CNAME ociaa2 +ncaa1-a IN CNAME ncaa1 +ncaa1-b IN CNAME ncaa1 +ncaa1-c IN CNAME ncaa1 + +<%# vim: set filetype=bindzone : -%> diff --git a/deployment/forums/manifests/init.pp b/deployment/forums/manifests/init.pp index d75bdb75..0ff256cd 100644 --- a/deployment/forums/manifests/init.pp +++ b/deployment/forums/manifests/init.pp @@ -5,18 +5,18 @@ class forums { phpbb::instance { 'de': } phpbb::redirection_instance{ 'fr': - url => 'https://forums.mageia.org/en/viewforum.php?f=19' + url => "https://forums.${::domain}/en/viewforum.php?f=19" } phpbb::redirection_instance{ 'es': - url => 'https://forums.mageia.org/en/viewforum.php?f=22' + url => "https://forums.${::domain}/en/viewforum.php?f=22" } phpbb::redirection_instance{ 'zh-cn': - url => 'https://forums.mageia.org/en/viewforum.php?f=27' + url => "https://forums.${::domain}/en/viewforum.php?f=27" } phpbb::redirection_instance{ 'pt-br': - url => 'https://forums.mageia.org/en/viewforum.php?f=28' + url => "https://forums.${::domain}/en/viewforum.php?f=28" } } diff --git a/deployment/lists/manifests/init.pp b/deployment/lists/manifests/init.pp index 511caa9a..3f06aa1f 100644..100755 --- a/deployment/lists/manifests/init.pp +++ b/deployment/lists/manifests/init.pp @@ -1,197 +1,377 @@ class lists { - sympa::public_list {'atelier-discuss': + # When adding a new list, also add it to the wiki page : + # https://wiki.mageia.org/en/Mailing_lists + + # Note: an e-mail of "FOO@group.${::domain}" corresponds to LDAP group + # mga-FOO, but only for a user sending from that group; the members are + # not expanded. subscriber_ldap_group and sender_ldap_group are expanded to + # their group members. + + sympa::list::announce { 'announce': + subject => 'Mageia announces', + reply_to => "discuss@ml.${::domain}", + sender_email => [ "sysadmin@group.${::domain}"], + } + + sympa::list::announce {'atelier-bugs': + subject => 'Atelier bug reports from bugzilla', + reply_to => "atelier-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'atelier', + } + + sympa::list::announce {'atelier-commits': + subject => 'Commits on atelier repositories (Artwork, Web, etc ...)', + reply_to => "atelier-discuss@ml.${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], + topics => 'atelier', + } + + sympa::list::public {'atelier-discuss': subject => 'Discussions about artwork, web, marketing, communication', topics => 'atelier', } + sympa::list::public {'basesystem': + subject => 'Development discussion list about mageia basesystem', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::private { 'blog-moderation': + subject => 'Blog comments moderation', + subscriber_ldap_group => 'mga-blog-moderators', + sender_email => [ "wordpress@blog.${::domain}" ], + topics => 'atelier', + } + + sympa::list::public {'bugsquad-discuss': + subject => 'Bugsquad team discussions', + topics => 'bugsquad', + } + + sympa::list::public {'dev': + subject => 'Development discussion list', + topics => 'developers', + } + + sympa::list::public {'discuss': + subject => 'General discussion list', + topics => 'users', + } + + sympa::list::public {'gnome': + subject => 'Development discussion list about mageia Gnome integration', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'i18n-discuss': + subject => 'Translation team discussions', + topics => 'i18n', + } + + sympa::list::announce { 'i18n-bugs': + subject => 'Translation bug reports from bugzilla', + reply_to => "i18n-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'i18n', + } + + sympa::list {'i18n-reports': + subject => 'Automated reports for translations', + reply_to => "i18n-discuss@ml.${::domain}", + sender_subscriber => true, + sender_email => [ + # 'r2d2@vargas.calenco.com', + # "blog@${::domain}", + "root@${::domain}", + "subversion_noreply@ml.${::domain}", + ], + topics => 'i18n', + } + # please check that the list use the proper code for # language ( not to be confused with tld or country code ) - sympa::public_list {'i18n-af': + sympa::list::public {'i18n-af': subject => 'Translation to Afrikaans', topics => 'i18n', } - sympa::public_list {'i18n-de': + sympa::list::public {'i18n-ar': + subject => 'Translation to Arabic', + topics => 'i18n', + } + + sympa::list::public {'i18n-de': subject => 'Translation to German', topics => 'i18n', } - sympa::public_list {'i18n-et': + sympa::list::public {'i18n-el': + subject => 'Translation to Greek', + topics => 'i18n', + } + + sympa::list::public {'i18n-en': + subject => 'Translation to English', + topics => 'i18n', + } + + sympa::list::public {'i18n-et': subject => 'Translation to Estonian', topics => 'i18n', } - sympa::public_list {'i18n-fr': + sympa::list::public {'i18n-fr': subject => 'Translation to French', topics => 'i18n', } - sympa::public_list {'i18n-el': - subject => 'Translation to Greek', + sympa::list::public {'i18n-hu': + subject => 'Translation to Hungarian', topics => 'i18n', } - sympa::public_list {'i18n-nl': - subject => 'Translation to Dutch', + sympa::list::public {'i18n-it': + subject => 'Translation to Italian', topics => 'i18n', } - sympa::public_list {'i18n-pt_br': - subject => 'Translation to Brazilian Portuguese', + sympa::list::public {'i18n-nl': + subject => 'Translation to Dutch', topics => 'i18n', } - sympa::public_list {'i18n-pl': + sympa::list::public {'i18n-pl': subject => 'Translation to Polish', topics => 'i18n', } - sympa::public_list {'i18n-ru': - subject => 'Translation to Russian', + sympa::list::public {'i18n-pt_br': + subject => 'Translation to Brazilian Portuguese', topics => 'i18n', } - sympa::public_list {'i18n-tr': - subject => 'Translation to Turkish', + sympa::list::public {'i18n-pt_pt': + subject => 'Translation to Portuguese', topics => 'i18n', } - sympa::public_list {'i18n-it': - subject => 'Translation to Italian', + sympa::list::public {'i18n-ro': + subject => 'Translation to Romanian', topics => 'i18n', } - sympa::public_list {'i18n-en': - subject => 'Translation to English', + sympa::list::public {'i18n-ru': + subject => 'Translation to Russian', topics => 'i18n', } - sympa::public_list {'i18n-ro': - subject => 'Translation to Romanian', + sympa::list::public {'i18n-tr': + subject => 'Translation to Turkish', topics => 'i18n', } - sympa::public_list {'i18n-zh_tw': + sympa::list::public {'i18n-zh_tw': subject => 'Translation to Taiwanese', topics => 'i18n', } - sympa::public_list {'qa-discuss': + sympa::list::public {'isobuild': + subject => 'Development discussion list about Mageia isos', + topics => 'developers', + } + + sympa::list::public {'java': + subject => 'Development discussion list about Java', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'kde': + subject => 'Development discussion list about KDE', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'kernel': + subject => 'Development discussion list about Kernel', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'mageiatools': + subject => 'Development discussion list about Mageiatools', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'perl': + subject => 'Development discussion list about Perl', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'php': + subject => 'Development discussion list about Php', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'python': + subject => 'Development discussion list about Python', + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::public {'qa-discuss': subject => 'Discussions about QA tasks and requests', topics => 'qa', } - sympa::announce_list_email {'qa-bugs': + sympa::list::public {'rpmstack': + subject => 'Development discussion list about Mageia rpm stack', + topics => 'developers', + } + + sympa::list::announce {'qa-bugs': subject => 'QA bug reports from bugzilla', - reply_to => "qa-discuss@ml.$::domain", - sender_email => "bugzilla-daemon@$::domain", + reply_to => "qa-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], topics => 'qa', } - sympa::public_list {'forums-discuss': - subject => 'Discuss forums matters, policies and processes, as well as publish summaries of notable events/feedback', + sympa::list::announce {'qa-reports': + subject => 'Automated reports from QA tools', + reply_to => "qa-discuss@ml.${::domain}", + sender_email => [ "buildsystem-daemon@${::domain}" ], + topics => 'qa', + } + + sympa::list::announce {'qa-commits': + subject => 'Update advisories commits', + reply_to => "qa-discuss@ml.${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], + topics => 'qa', + } + + sympa::list::public {'forums-discuss': + subject => 'Discuss forums matters, policies and processes, and publish summaries of notable events/feedback', topics => 'forums', } - sympa::announce_list_email {'forums-bugs': + sympa::list::announce {'forums-bugs': subject => 'Forums bug reports from bugzilla', - reply_to => "forums-discuss@ml.$::domain", - sender_email => "bugzilla-daemon@$::domain", + reply_to => "forums-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], topics => 'forums', } - sympa::public_list {'doc-discuss': + sympa::list::public {'doc-discuss': subject => 'Discussions about Mageia documentation', topics => 'doc', } - sympa::announce_list_email { 'doc-bugs': + sympa::list::announce { 'doc-bugs': subject => 'Documentation bug reports from bugzilla', - reply_to => "doc-discuss@ml.$::domain", - sender_email => "bugzilla-daemon@$::domain", + reply_to => "doc-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], topics => 'doc', } - sympa::announce_list_email { 'packages-commits': + sympa::list::announce { 'packages-commits': subject => 'Commits on packages repository', - # FIXME change once we migrate - reply_to => "mageia-dev@$::domain", - sender_email => "root@$::domain", + reply_to => "dev@ml.${::domain}", + sender_email => [ "subversion_noreply@ml.${::domain}", "binrepo_noreply@ml.${::domain}" ], topics => 'developers', } - sympa::announce_list_email { 'mirrors-announce': + sympa::list::announce { 'mirrors-announce': subject => 'Important announces about mirrors updates', - # FIXME change once we migrate - reply_to => "mageia-sysadm@$::domain", - sender_email => "root@$::domain", + reply_to => "sysadmin-discuss@ml.${::domain}", + sender_email => [ "root@${::domain}" ], topics => 'sysadmin', } - sympa::announce_list_email {'sysadmin-commits': + sympa::list::announce {'sysadmin-commits': subject => 'Commits on sysadmin repository', - # FIXME change once we migrate - reply_to => "mageia-sysadm@$::domain", - sender_email => "root@$::domain", + reply_to => "sysadmin-discuss@ml.${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], + topics => 'sysadmin', + } + + sympa::list::public {'sysadmin-discuss': + subject => 'Sysadmin team discussions', topics => 'sysadmin', } - sympa::announce_list_email {'sysadmin-reports': + sympa::list::announce {'sysadmin-reports': subject => 'Automated reports from various pieces of infrastructure', - # FIXME change once we migrate - reply_to => "mageia-sysadm@$::domain", - sender_email => "root@$::domain", + reply_to => "sysadmin-discuss@ml.${::domain}", + sender_email => [ "root@${::domain}" ], topics => 'sysadmin', } - sympa::announce_list_email { 'sysadmin-bugs': + sympa::list::announce { 'sysadmin-bugs': subject => 'Sysadmin bug reports from bugzilla', - # FIXME change once we migrate - reply_to => "mageia-sysadm@$::domain", - sender_email => "bugzilla-daemon@$::domain", + reply_to => "sysadmin-discuss@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], topics => 'sysadmin', + critical => true, } - sympa::announce_list_email { 'soft-commits': + sympa::list::announce { 'soft-commits': subject => 'Commits on soft repository', - # FIXME change once we migrate - reply_to => "mageia-dev@$::domain", - sender_email => "root@$::domain", + reply_to => "dev@ml.${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], topics => 'developers', } - sympa::announce_list_email { 'bugs': + sympa::list::announce { 'bugs': subject => 'Bug reports from bugzilla', - # FIXME change once we migrate - reply_to => "mageia-dev@$::domain", - sender_email => "bugzilla-daemon@$::domain", + reply_to => "dev@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], + topics => 'developers', + } + + sympa::list::announce { 'pkg-bugs': + subject => 'Packaging bug reports from bugzilla', + reply_to => "dev@ml.${::domain}", + sender_email => [ "bugzilla_noreply@ml.${::domain}" ], topics => 'developers', } - sympa::announce_list_email { 'updates-announce': + sympa::list::announce { 'updates-announce': subject => 'Packages update for stable release', - reply_to => "mageia-dev@$::domain", - sender_email => "buildsystem-daemon@$::domain", + reply_to => "dev@ml.${::domain}", + sender_email => [ "buildsystem-daemon@${::domain}" ], topics => 'developers', } - sympa::announce_list_email { 'changelog': + sympa::list::announce { 'backports-announce': + subject => 'Package backports for stable release', + reply_to => "dev@ml.${::domain}", + sender_ldap_group => "mga-qa-committers", + topics => 'developers', + } + + sympa::list::announce { 'changelog': subject => 'Announces for new packages uploaded', - # FIXME change once we migrate - reply_to => "mageia-dev@$::domain", - sender_email => "buildsystem-daemon@$::domain", + reply_to => "dev@ml.${::domain}", + sender_email => [ "buildsystem-daemon@${::domain}" ], topics => 'developers', } - sympa::announce_list_email { 'board-commits': + sympa::list::announce { 'board-commits': subject => 'Commits on Mageia.Org status and organisation documents', - reply_to => "board-public@ml.$::domain", - sender_email => "root@$::domain", + reply_to => "board-public@ml.${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], topics => 'governance', subscriber_ldap_group => 'mga-board', } - sympa::public_restricted_list { 'board-public': + sympa::list::public_restricted { 'board-public': subject => 'Public board discussion', subscriber_ldap_group => 'mga-board', topics => 'governance', @@ -203,14 +383,38 @@ class lists { topics => 'governance', } - sympa::public_restricted_list { 'council': + sympa::list::announce {'treasurer-commits': + subject => 'Commits on Mageia.Org association treasurer repository', + reply_to => "treasurer@${::domain}", + sender_email => [ "root@${::domain}", "subversion_noreply@ml.${::domain}" ], + topics => 'governance', + } + + sympa::list::public_restricted { 'council': subject => 'Council discussions', subscriber_ldap_group => 'mga-council', topics => 'governance', } - sympa::public_list {'local-discuss': + sympa::list::public {'local-discuss': subject => 'Discussions about Local Community Team', topics => 'local', } + + sympa::list::public {'discuss-fr': + subject => 'French discussions about Mageia', + topics => 'users', + } + + sympa::list::public {'discuss-pt-br': + subject => 'Discussions about Mageia in Brazilian Portuguese', + topics => 'users', + } + + sympa::list::private { 'mageia-association-members': + subject => 'Discussions between association members', + subscriber_ldap_group => 'mga-association-members', + topics => 'Mageia Association Members', + } } + diff --git a/deployment/main_mirror/files/mirror/mirror.readme b/deployment/main_mirror/files/mirror/mirror.readme index 3fd50aa4..5846d12e 100644 --- a/deployment/main_mirror/files/mirror/mirror.readme +++ b/deployment/main_mirror/files/mirror/mirror.readme @@ -10,27 +10,37 @@ This document describes the way to implement a Mageia Mirror. 1) Prerequisite --------------- -The expected size of the mirror is around 700GB. +The expected size of the mirror is around 1.8-2TB. +The mirror only contains the last 2 stable releases + the development +branch called cauldron. + +For older unsupported releases, you can find them at the archive +provided by distrib-coffee mirror: +https://distrib-coffee.ipsl.jussieu.fr/pub/linux/Mageia-archive/ + +Look here to see the (planned) end of support date for each version: +https://www.mageia.org/en/support/#lifecycle You need rsync software to synchronise the tree. 2) Official source ------------------ -For public mirror, we encourage you to use one of our Tier1 mirror. +For a public mirror, we encourage you to use one of our Tier1 mirrors. + +The servers below synchronise the tree directly from the Mageia rsync server. -Theses servers synchronises the tree directly from the Mageia rsync server. + Check https://mirrors.mageia.org/ for their bandwidths. + Check https://mirrors.mageia.org/status for their current statuses. - o rsync://distrib-coffee.ipsl.jussieu.fr/mageia/ - located in Paris (France) - o rsync://ftp.LinuxCabal.org/Mageia/ - located in Lucern (Switzerland) o rsync://mageia.c3sl.ufpr.br/mageia/ located in Curitiba (Brasil) o rsync://mirrors.kernel.org/mirrors/mageia/ located in USA and Europe - o rsync://ftp.acc.umu.se/mirror/mageia/ + o rsync://mirror.accum.se/mirror/mageia/ located in Umea (Sweden) + o rsync://mirror.math.princeton.edu/pub/mageia/ + located in Princeton (USA) 3) Rsync options ---------------- @@ -50,6 +60,7 @@ load on the remote server ----------------------------- The tree must be synchronized at least every 2 hours. +Tier 1 mirrors should preferably sync at least every hour. Please ensure that another rsync process is not started while a first one is still running. Use a lock file. @@ -57,7 +68,7 @@ one is still running. Use a lock file. 5) Registering your mirror -------------------------- -Goto at http://mirrors.mageia.org/new and enter all possible protocol. +Go to https://mirrors.mageia.org/new and enter all possible protocols. 6) Subscribe to the mirrors-announce mailing list ------------------------------------------------- diff --git a/deployment/main_mirror/manifests/init.pp b/deployment/main_mirror/manifests/init.pp index a4e8cc76..9b26a64d 100644 --- a/deployment/main_mirror/manifests/init.pp +++ b/deployment/main_mirror/manifests/init.pp @@ -8,14 +8,14 @@ class main_mirror { $mirror = '/distrib' file { [$mirror, - "$mirror/mirror", - "$mirror/archive"]: + "${mirror}/mirror", + "${mirror}/archive"]: ensure => directory, } file { - "$mirror/README": source => 'puppet:///modules/main_mirror/README'; - "$mirror/mirror/mirror.readme": source => 'puppet:///modules/main_mirror/mirror/mirror.readme'; - "$mirror/mirror/paths.readme": source => 'puppet:///modules/main_mirror/mirror/paths.readme'; + "${mirror}/README": source => 'puppet:///modules/main_mirror/README'; + "${mirror}/mirror/mirror.readme": source => 'puppet:///modules/main_mirror/mirror/mirror.readme'; + "${mirror}/mirror/paths.readme": source => 'puppet:///modules/main_mirror/mirror/paths.readme'; } } diff --git a/deployment/main_mirror/templates/rsyncd.conf b/deployment/main_mirror/templates/rsyncd.conf index a8d38b82..9fc93860 100644 --- a/deployment/main_mirror/templates/rsyncd.conf +++ b/deployment/main_mirror/templates/rsyncd.conf @@ -8,45 +8,24 @@ gid = nogroup comment = Mageia Mirror Tree hosts allow = \ 10.42.0.0/24 \ - rabbit.<%= domain %> \ - alamut.<%= domain %> \ - arm1.<%= domain %> \ - arm2.<%= domain %> \ + 2a02:2178:2:7::/64 \ + rabbit.<%= @domain %> \ + sucuk.<%= @domain %> \ distrib-coffee.ipsl.jussieu.fr \ - distribipsl.aero.jussieu.fr \ - ibiblio.org \ - 152.46.7.122 \ - 152.19.134.16 \ - 152.19.134.30 \ - 2610:28:3090:3000:250:56ff:fe96:23 \ - ftp.LinuxCabal.org \ - 178.22.68.98 \ - sagres.c3sl.ufpr.br \ - 2801:82:80ff:8000::c \ - 2801:82:80ff:8000::2 \ - zeus1.kernel.org \ - zeus2.kernel.org \ - zeus3.kernel.org \ - zeus4.kernel.org \ - 2001:4f8:8:10::/64 \ - 2001:4f8:1:10::/64 \ - 2001:500:60:10::/64 \ - 2001:6b0:e:4017::/64 \ - churchill.acc.umu.se \ - 130.239.18.141 \ - 2001:6b0:e:2018::141 \ - -[newrelease] - path = /distrib/newrelease/ - comment = Mageia Next Release - hosts allow = \ - rabbit.<%= domain %> \ - -[bootstrap] - path = /distrib/bootstrap/ - comment = Mageia Bootstrap - hosts allow = \ - rabbit.<%= domain %> \ - distrib-coffee.ipsl.jussieu.fr \ - distribipsl.aero.jussieu.fr \ + ftp.proxad.net \ + jobbot0.ibiblio.org \ + jobbot1.ibiblio.org \ + mirror.math.princeton.edu \ + poincare.accum.se \ + poincare.acc.umu.se \ + sagres.c3sl.ufpr.br \ + sv.mirrors.kernel.org \ + ny.mirrors.kernel.org \ + 147.75.69.246 \ + 2001:14ba:a417:eb00::1 \ + 2001:14ba:a417:eb00::2 +[git] + path = /git + comment = Mageia Git repos + hosts allow = sucuk.<%= @domain %> diff --git a/deployment/mga_buildsystem/manifests/buildnode.pp b/deployment/mga_buildsystem/manifests/buildnode.pp new file mode 100644 index 00000000..f6bf70ea --- /dev/null +++ b/deployment/mga_buildsystem/manifests/buildnode.pp @@ -0,0 +1,4 @@ +class mga_buildsystem::buildnode { + include mga_buildsystem::config + include buildsystem::buildnode +} diff --git a/deployment/mga_buildsystem/manifests/config.pp b/deployment/mga_buildsystem/manifests/config.pp new file mode 100644 index 00000000..c0c62cc4 --- /dev/null +++ b/deployment/mga_buildsystem/manifests/config.pp @@ -0,0 +1,668 @@ +class mga_buildsystem::config { + class { 'buildsystem::var::signbot': + keyid => '80420F66', + keyemail => "packages@${::domain}", + keyname => 'Mageia Packages', + } + + class { 'buildsystem::var::groups': + packagers => 'mga-packagers', + packagers_committers => 'mga-packagers-committers', + } + + class { 'buildsystem::var::webstatus' : + package_commit_url => "https://svnweb.${::domain}/packages?view=revision&revision=%d", + theme_name => 'mageia', + } + + class { 'buildsystem::var::iurt': + timeout_multiplier => $::architecture ? { + /arm/ => 4, + 'aarch64' => 2, + default => 1, + } + } + + class { 'buildsystem::var::scheduler' : + admin_mail => "sysadmin@group.${::domain}", + build_nodes => { + 'i586' => [ 'ecosse0', 'rabbit0', 'ecosse1', 'rabbit1', 'rabbit2' ], + 'i686' => [ 'ecosse0', 'rabbit0', 'ecosse1', 'rabbit1', 'rabbit2' ], + 'x86_64' => [ 'rabbit0', 'ecosse0', 'rabbit1', 'ecosse1', 'rabbit2' ], + 'armv7hl' => [ 'ncaa1-a', 'ncaa1-b', 'ncaa1-c', 'ociaa1-a', 'ociaa1-b'], + 'aarch64' => [ 'ncaa1-a', 'ncaa1-b', 'ncaa1-c', 'ociaa1-a', 'ociaa1-b'], + }, + build_nodes_aliases => { + 'ecosse0' => "ecosse.${::domain}", + 'ecosse1' => "ecosse.${::domain}", + 'rabbit0' => "rabbit.${::domain}", + 'rabbit1' => "rabbit.${::domain}", + 'rabbit2' => "rabbit.${::domain}", + 'ociaa1-a' => "ociaa1.${::domain}", + 'ociaa1-b' => "ociaa1.${::domain}", + 'ociaa1-c' => "ociaa1.${::domain}", + }, + build_src_node => 'duvel', + } + include buildsystem::var::repository + class { 'buildsystem::var::binrepo': + uploadmail_from => "binrepo_noreply@ml.${::domain}", + uploadmail_to => "packages-commits@ml.${::domain}", + } + + $svn_hostname = "svn.${::domain}" + $svn_root_packages = "svn://${svn_hostname}/svn/packages" + $svn_root_packages_ssh = "svn+ssh://${svn_hostname}/svn/packages" + class { 'buildsystem::var::mgarepo': + submit_host => "pkgsubmit.${::domain}", + svn_hostname => $svn_hostname, + svn_root_packages => $svn_root_packages, + svn_root_packages_ssh => $svn_root_packages_ssh, + oldurl => "${svn_root_packages_ssh}/misc", + conf => { + 'global' => { + 'ldap-server' => "ldap.${::domain}", + 'ldap-base' => "ou=People,${::dc_suffix}", + 'ldap-filterformat' => '(&(objectClass=inetOrgPerson)(uid=$username))', + 'ldap-resultformat' => '$cn <$mail>', + } + } + } + + include stdlib + + $std_arch = ['x86_64', 'i586'] + $x86_arch = ['x86_64', 'i686'] + $arm32_arch = ['armv5tl', 'armv7hl'] + $std_repos = { + 'release' => { + 'media_type' => [ 'release' ], + 'requires' => [], + 'order' => 0, + }, + 'updates' => { + 'media_type' => [ 'updates' ], + 'updates_for' => 'release', + 'requires' => [ 'release' ], + 'order' => 1, + }, + 'updates_testing' => { + 'media_type' => [ 'testing' ], + 'noauto' => '1', + 'requires' => [ 'updates' ], + 'order' => 2, + }, + 'backports' => { + 'media_type' => [ 'backports' ], + 'noauto' => '1', + 'requires' => [ 'updates' ], + 'order' => 3, + }, + 'backports_testing' => { + 'media_type' => [ 'testing' ], + 'noauto' => '1', + 'requires' => [ 'backports' ], + 'order' => 4, + }, + } + $std_medias = { + 'core' => { + 'repos' => $std_repos, + 'media_type' => [ 'official', 'free' ], + 'order' => 0, + }, + 'nonfree' => { + 'repos' => $std_repos, + 'media_type' => [ 'official' ], + 'noauto' => '1', + 'requires' => [ 'core' ], + 'order' => 1, + }, + 'tainted' => { + 'repos' => $std_repos, + 'media_type' => [ 'official' ], + 'noauto' => '1', + 'requires' => [ 'core' ], + 'order' => 2, + }, + } + $std_base_media = [ 'core/release', 'core/updates' ] + $infra_medias = { + 'infra' => { + 'repos' => { + 'updates' => { + 'media_type' => [ 'updates' ], + 'requires' => [ 'release' ], + 'order' => 0, + }, + }, + 'media_type' => [ 'infra' ], + 'requires' => [ 'core' ], + 'order' => 0, + }, + } + $std_macros = { + 'distsuffix' => '.mga', + 'distribution' => 'Mageia', + 'vendor' => 'Mageia.Org', + '_real_vendor' => 'mageia', + } + $repo_allow_from_ips = [ + $::nodes_ipaddr[duvel][ipv6], + $::nodes_ipaddr[duvel][ipv4], + $::nodes_ipaddr[ecosse][ipv6], + $::nodes_ipaddr[ecosse][ipv4], + $::nodes_ipaddr[fiona][ipv6], + $::nodes_ipaddr[fiona][ipv4], + '10.42.0', + $::nodes_ipaddr[rabbit][ipv4], + $::nodes_ipaddr[rabbit][ipv6], + $::nodes_ipaddr[sucuk][ipv4], + $::nodes_ipaddr[sucuk][ipv6], + '85.134.55.73', + $::nodes_ipaddr[neru][ipv4], + $::nodes_ipaddr[neru][ipv6], + '2001:bc8:4400:2700::2729', + '147.75.83.250', + '2604:1380:2000:f100::1', + '2a05:d014:e9:2c00::/56', + '147.75.69.244/30', + '2604:1380:1001:4900::/127', + # Will be new neru + '51.15.220.93', + '2001:bc8:628:1f00::1', + # Oracle cloud VMs + '2603:c026:c101:f00::/64', + $::nodes_ipaddr[ncaa1][ipv4], + $::nodes_ipaddr[ncaa1][ipv6], + ] + $repo_allow_from_domains = [ + ".${::domain}", + ] + + # the list of checks, actions, posts for cauldron in youri-upload + $cauldron_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'markrelease', + 'sign', + 'install', + 'link', + 'unpack_release_notes', + 'unpack_gfxboot_theme', + 'unpack_meta_task', + 'unpack_installer_images', + 'unpack_installer_images_nonfree', + 'unpack_installer_stage2', + 'unpack_installer_advertising', + 'unpack_installer_rescue', + 'unpack_syslinux', + 'unpack_pci_usb_ids', + 'archive', + 'mail', + 'maintdb', + ], + 'posts' => [ + 'genhdlist2_zstd', + 'createrepo_cauldron', + 'appstream_cauldron', + 'clean_rpmsrate', + 'mirror', + ], + } + + # TODO: mga >= 6 should use std config + createrepo, not a different one + $mga6_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'sign', + 'install', + 'link', + 'archive', + 'mail', + ], + 'posts' => [ + 'genhdlist2', + 'createrepo_mga6', + 'appstream_mga6', + 'mirror', + ], + } + + $mga7_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'sign', + 'install', + 'link', + 'archive', + 'mail', + ], + 'posts' => [ + 'genhdlist2', + 'createrepo_mga7', + 'appstream_mga7', + 'mirror', + ], + } + + $mga8_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'sign', + 'install', + 'link', + 'archive', + 'mail', + ], + 'posts' => [ + 'genhdlist2', + 'createrepo_mga8', + 'appstream_mga8', + 'mirror', + ], + } + + $mga9_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'sign', + 'install', + 'link', + 'archive', + 'mail', + ], + 'posts' => [ + 'genhdlist2', + 'createrepo_mga9', + 'appstream_mga9', + 'mirror', + ], + } + + # the list of checks, actions, posts for infra distros in youri-upload + $infra_youri_upload_targets = { + 'checks' => [ + 'version', + 'tag', + 'acl', + 'rpmlint', + 'recency', + ], + 'actions' => [ + 'sign', + 'install', + 'link', + 'archive', + ], + 'posts' => [ + 'genhdlist2', + ], + } + + # the list of checks, actions, posts for cauldron in youri-todo + $cauldron_youri_todo_targets = { + 'checks' => [ + 'source', + 'deps', + 'version', + 'tag', + 'acl', + 'host', + 'rpmlint', + 'recency', + 'queue_recency', + ], + 'actions' => [ + 'send', + 'dependencies', + 'rpminfo', + 'ulri', + ], + } + + # the list of checks, actions, posts for stable and infra distros in youri-todo + $std_youri_todo_targets = { + 'checks' => [ + 'source', + 'version', + 'tag', + 'acl', + 'host', + 'rpmlint', + 'recency', + 'queue_recency', + ], + 'actions' => [ + 'send', + 'dependencies', + 'rpminfo', + 'ulri', + ], + } + + # rpmlint check options for stable and cauldron + $mga_rpmlint = { + 'config' => '/usr/share/rpmlint/config', + 'path' => '/usr/bin/rpmlint', + 'results' => [ + 'buildprereq-use', + 'no-description-tag', + 'no-summary-tag', + 'non-standard-group', + 'non-xdg-migrated-menu', + 'percent-in-conflicts', + 'percent-in-dependency', + 'percent-in-obsoletes', + 'percent-in-provides', + 'summary-ended-with-dot', + 'unexpanded-macro', + 'unknown-lsb-keyword', + 'malformed-line-in-lsb-comment-block', + 'empty-%postun', + 'empty-%post', + 'invalid-desktopfile', + 'standard-dir-owned-by-package', + 'use-tmp-in-%postun', + 'bogus-variable-use-in-%posttrans', + 'dir-or-file-in-usr-local', + 'dir-or-file-in-tmp', + 'dir-or-file-in-mnt', + 'dir-or-file-in-opt', + 'dir-or-file-in-home', + 'dir-or-file-in-var-local', + 'tmpfiles-conf-in-etc', + 'non-ghost-in-run', + 'non-ghost-in-var-run', + 'non-ghost-in-var-lock', + 'systemd-unit-in-etc', + 'udev-rule-in-etc', + ], + } + + # list of users allowed to submit packages when cauldron is frozen + $cauldron_authorized_users = str_join(group_members('mga-release_managers'), '|') + $cauldron_version_check = { + 'authorized_sections' => '^[a-z]+/updates_testing$', + #'authorized_sections' => 'none_section_authorized', + #'authorized_packages' => 'none_package_authorized', + 'authorized_packages' => 'drak|^(urpmi|perl-(MDK-Common|Gtk3|Glib(-Object-Introspection)?|URPM)|mgaonline|net_monitor|perl_checker|mandi|indexhtml|ldetect(-lst)?|msec|manatools|rpm-(mageia-setup|helper)|(mga-|mageia).*|iurt)$', + 'authorized_arches' => 'none', + 'authorized_users' => "^${cauldron_authorized_users}\$", + 'mode' => 'normal', + #'mode' => 'version_freeze', + #'mode' => 'freeze', + } + + # for EOL distributions + $frozen_version_check = { + 'authorized_packages' => 'none_package_authorized', + 'authorized_sections' => 'none_section_authorized', + 'authorized_arches' => 'none', + 'mode' => 'freeze', + } + + # for supported stable distributions + $std_version_check = { + 'authorized_packages' => 'none_package_authorized', + 'authorized_sections' => '^(core|nonfree|tainted)/(updates_testing|backports_testing)$', + 'authorized_arches' => 'none', + 'mode' => 'freeze', + } + + $infra_authorized_users = str_join(group_members('mga-sysadmin'), '|') + $infra_version_check = { + 'authorized_users' => "^${infra_authorized_users}\$", + 'mode' => 'freeze', + } + + class { 'buildsystem::var::distros': + default_distro => 'cauldron', + repo_allow_from_ips => $repo_allow_from_ips, + repo_allow_from_domains => $repo_allow_from_domains, + distros => { + 'cauldron' => { + 'arch' => concat($x86_arch, ['armv7hl', 'aarch64']), + 'mandatory_arch' => concat($x86_arch, ['aarch64']), + 'no_media_cfg_update' => true, + 'medias' => $std_medias, + 'base_media' => $std_base_media, + 'branch' => 'Devel', + 'version' => '10', + 'submit_allowed' => "${svn_root_packages}/cauldron", + 'macros' => $std_macros, + 'youri' => { + 'upload' => { + 'targets' => $cauldron_youri_upload_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + }, + }, + 'todo' => { + 'targets' => $cauldron_youri_todo_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + 'version' => $cauldron_version_check, + }, + }, + }, + }, + + + '8' => { + 'arch' => concat($std_arch, ['armv7hl', 'aarch64']), + 'mandatory_arch' => concat($std_arch, ['aarch64']), + 'no_media_cfg_update' => true, + 'medias' => $std_medias, + 'base_media' => $std_base_media, + 'branch' => 'Official', + 'version' => '8', + 'submit_allowed' => "${svn_root_packages}/updates/8", + 'backports_allowed' => "${svn_root_packages}/backports/8", + 'macros' => $std_macros, + 'youri' => { + 'upload' => { + 'targets' => $mga8_youri_upload_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + }, + }, + 'todo' => { + 'targets' => $std_youri_todo_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + 'version' => $std_version_check, + }, + }, + }, + }, + + '9' => { + 'arch' => concat($std_arch, ['armv7hl', 'aarch64']), + 'mandatory_arch' => concat($std_arch, ['aarch64']), + 'no_media_cfg_update' => true, + 'medias' => $std_medias, + 'base_media' => $std_base_media, + 'branch' => 'Official', + 'version' => '9', + 'submit_allowed' => "${svn_root_packages}/updates/9", + 'backports_allowed' => "${svn_root_packages}/backports/9", + 'macros' => $std_macros, + 'youri' => { + 'upload' => { + 'targets' => $mga9_youri_upload_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + }, + }, + 'todo' => { + 'targets' => $std_youri_todo_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + 'version' => $std_version_check, + }, + }, + }, + }, + + 'infra_8' => { + 'arch' => concat($std_arch, ['armv7hl', 'aarch64']), + 'medias' => $infra_medias, + 'base_media' => [ '8/core/release', '8/core/updates', 'infra/updates' ], + 'branch' => 'Official', + 'version' => '8', + 'submit_allowed' => "${svn_root_packages}/updates/infra_8", + 'macros' => $std_macros, + 'based_on' => { + '8' => { + 'core' => [ 'release', 'updates' ], + }, + }, + 'youri' => { + 'upload' => { + 'targets' => $infra_youri_upload_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + }, + }, + 'todo' => { + 'targets' => $std_youri_todo_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + 'version' => $infra_version_check, + }, + }, + }, + 'no_mirror' => true, + }, + + 'infra_9' => { + 'arch' => concat($std_arch, ['armv7hl', 'aarch64']), + 'medias' => $infra_medias, + 'base_media' => [ '9/core/release', '9/core/updates', 'infra/updates' ], + 'branch' => 'Official', + 'version' => '9', + 'submit_allowed' => "${svn_root_packages}/updates/infra_9", + 'macros' => $std_macros, + 'based_on' => { + '9' => { + 'core' => [ 'release', 'updates' ], + }, + }, + 'youri' => { + 'upload' => { + 'targets' => $infra_youri_upload_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + }, + }, + 'todo' => { + 'targets' => $std_youri_todo_targets, + 'checks' => { + 'rpmlint' => $mga_rpmlint, + 'version' => $infra_version_check, + }, + }, + }, + 'no_mirror' => true, + }, + } + } + $checks_tag_options = { + 'tags' => { + 'release' => inline_template("^[^~]*<%= std_macros['distsuffix'] %>\\d+"), + 'distribution' => inline_template("^<%= std_macros['distribution'] %>"), + 'vendor' => inline_template("^<%= std_macros['vendor'] %>$"), + }, + } + class { 'buildsystem::var::youri': + packages_archivedir => "${buildsystem::var::scheduler::homedir}/old", + youri_conf => { + 'upload' => { + 'checks' => { + 'tag' => { + 'options' => $checks_tag_options, + }, + 'rpmlint' => { + 'options' => { + 'results' => [ + 'buildprereq-use', + 'no-description-tag', + 'no-summary-tag', + 'non-standard-group', + 'non-xdg-migrated-menu', + 'percent-in-conflicts', + 'percent-in-dependency', + 'percent-in-obsoletes', + 'percent-in-provides', + 'summary-ended-with-dot', + 'unexpanded-macro', + 'unknown-lsb-keyword', + 'malformed-line-in-lsb-comment-block', + 'empty-%postun', + 'empty-%post', + 'invalid-desktopfile', + 'standard-dir-owned-by-package', + 'use-tmp-in-%postun', + 'bogus-variable-use-in-%posttrans', + 'dir-or-file-in-usr-local', + 'dir-or-file-in-tmp', + 'dir-or-file-in-mnt', + 'dir-or-file-in-opt', + 'dir-or-file-in-home', + 'dir-or-file-in-var-local', + ], + }, + }, + }, + 'actions' => { + 'mail' => { + 'options' => { + 'to' => "changelog@ml.${::domain}", + 'reply_to' => "dev@ml.${::domain}", + 'from' => "buildsystem-daemon@${::domain}", + 'prefix' => 'RPM', + }, + }, + }, + }, + 'todo' => { + 'checks' => { + 'tag' => { + 'options' => $checks_tag_options, + }, + }, + }, + } + } +} diff --git a/deployment/mga_buildsystem/manifests/mainnode.pp b/deployment/mga_buildsystem/manifests/mainnode.pp index 6ad140d2..b614cdbd 100644 --- a/deployment/mga_buildsystem/manifests/mainnode.pp +++ b/deployment/mga_buildsystem/manifests/mainnode.pp @@ -1,27 +1,14 @@ class mga_buildsystem::mainnode { + include mga_buildsystem::config include buildsystem::mainnode - include buildsystem::sync20101 include buildsystem::release include buildsystem::maintdb include buildsystem::binrepo include buildsystem::repoctl + include buildsystem::webstatus - # Forward ports to arm1 and arm2 ssh, to access them from outside - xinetd::port_forward {"forward_arm1": - target_ip => 'arm1.mageia.org', - target_port => '22', - port => '4251', - proto => 'tcp', - } - xinetd::port_forward {"forward_arm2": - target_ip => 'arm2.mageia.org', - target_port => '22', - port => '4252', - proto => 'tcp', - } - - $rpmlint_packages = [ "rpmlint-mageia-policy", "rpmlint-mageia-mga2-policy"] + $rpmlint_packages = [ 'rpmlint-mageia-policy'] package { $rpmlint_packages: - ensure => installed, + ensure => installed } } diff --git a/deployment/mgagit/files/git_multimail.py b/deployment/mgagit/files/git_multimail.py new file mode 100644 index 00000000..0c5c8d7b --- /dev/null +++ b/deployment/mgagit/files/git_multimail.py @@ -0,0 +1,4383 @@ +#! /usr/bin/env python3 + +__version__ = '1.7.dev' + +# Copyright (c) 2015-2022 Matthieu Moy and others +# Copyright (c) 2012-2014 Michael Haggerty and others +# Derived from contrib/hooks/post-receive-email, which is +# Copyright (c) 2007 Andy Parkins +# and also includes contributions by other authors. +# +# This file is part of git-multimail. +# +# git-multimail is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License version +# 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# <http://www.gnu.org/licenses/>. + +"""Generate notification emails for pushes to a git repository. + +This hook sends emails describing changes introduced by pushes to a +git repository. For each reference that was changed, it emits one +ReferenceChange email summarizing how the reference was changed, +followed by one Revision email for each new commit that was introduced +by the reference change. + +Each commit is announced in exactly one Revision email. If the same +commit is merged into another branch in the same or a later push, then +the ReferenceChange email will list the commit's SHA1 and its one-line +summary, but no new Revision email will be generated. + +This script is designed to be used as a "post-receive" hook in a git +repository (see githooks(5)). It can also be used as an "update" +script, but this usage is not completely reliable and is deprecated. + +To help with debugging, this script accepts a --stdout option, which +causes the emails to be written to standard output rather than sent +using sendmail. + +See the accompanying README file for the complete documentation. + +""" + +import sys +import os +import re +import bisect +import socket +import subprocess +import shlex +import optparse +import logging +import smtplib +try: + import ssl +except ImportError: + # Python < 2.6 do not have ssl, but that's OK if we don't use it. + pass +import time + +import uuid +import base64 + +PYTHON3 = sys.version_info >= (3, 0) + +if sys.version_info <= (2, 5): + def all(iterable): + for element in iterable: + if not element: + return False + return True + + +def is_ascii(s): + return all(ord(c) < 128 and ord(c) > 0 for c in s) + + +if PYTHON3: + def is_string(s): + return isinstance(s, str) + + def str_to_bytes(s): + return s.encode(ENCODING) + + def bytes_to_str(s, errors='strict'): + return s.decode(ENCODING, errors) + + unicode = str + + def write_str(f, msg): + # Try outputting with the default encoding. If it fails, + # try UTF-8. + try: + f.buffer.write(msg.encode(sys.getdefaultencoding())) + except UnicodeEncodeError: + f.buffer.write(msg.encode(ENCODING)) + + def read_line(f): + # Try reading with the default encoding. If it fails, + # try UTF-8. + out = f.buffer.readline() + try: + return out.decode(sys.getdefaultencoding()) + except UnicodeEncodeError: + return out.decode(ENCODING) + + import html + + def html_escape(s): + return html.escape(s) + +else: + def is_string(s): + try: + return isinstance(s, basestring) + except NameError: # Silence Pyflakes warning + raise + + def str_to_bytes(s): + return s + + def bytes_to_str(s, errors='strict'): + return s + + def write_str(f, msg): + f.write(msg) + + def read_line(f): + return f.readline() + + def next(it): + return it.next() + + import cgi + + def html_escape(s): + return cgi.escape(s, True) + +try: + from email.charset import Charset + from email.utils import make_msgid + from email.utils import getaddresses + from email.utils import formataddr + from email.utils import formatdate + from email.header import Header +except ImportError: + # Prior to Python 2.5, the email module used different names: + from email.Charset import Charset + from email.Utils import make_msgid + from email.Utils import getaddresses + from email.Utils import formataddr + from email.Utils import formatdate + from email.Header import Header + + +DEBUG = False + +ZEROS = '0' * 40 +LOGBEGIN = '- Log -----------------------------------------------------------------\n' +LOGEND = '-----------------------------------------------------------------------\n' + +ADDR_HEADERS = set(['from', 'to', 'cc', 'bcc', 'reply-to', 'sender']) + +# It is assumed in many places that the encoding is uniformly UTF-8, +# so changing these constants is unsupported. But define them here +# anyway, to make it easier to find (at least most of) the places +# where the encoding is important. +(ENCODING, CHARSET) = ('UTF-8', 'utf-8') + + +REF_CREATED_SUBJECT_TEMPLATE = ( + '%(emailprefix)s%(refname_type)s %(short_refname)s created' + ' (now %(newrev_short)s)' + ) +REF_UPDATED_SUBJECT_TEMPLATE = ( + '%(emailprefix)s%(refname_type)s %(short_refname)s updated' + ' (%(oldrev_short)s -> %(newrev_short)s)' + ) +REF_DELETED_SUBJECT_TEMPLATE = ( + '%(emailprefix)s%(refname_type)s %(short_refname)s deleted' + ' (was %(oldrev_short)s)' + ) + +COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE = ( + '%(emailprefix)s%(refname_type)s %(short_refname)s updated: %(oneline)s' + ) + +REFCHANGE_HEADER_TEMPLATE = """\ +Date: %(send_date)s +To: %(recipients)s +Subject: %(subject)s +MIME-Version: 1.0 +Content-Type: text/%(contenttype)s; charset=%(charset)s +Content-Transfer-Encoding: 8bit +Message-ID: %(msgid)s +From: %(fromaddr)s +Reply-To: %(reply_to)s +Thread-Index: %(thread_index)s +X-Git-Host: %(fqdn)s +X-Git-Repo: %(repo_shortname)s +X-Git-Refname: %(refname)s +X-Git-Reftype: %(refname_type)s +X-Git-Oldrev: %(oldrev)s +X-Git-Newrev: %(newrev)s +X-Git-NotificationType: ref_changed +X-Git-Multimail-Version: %(multimail_version)s +Auto-Submitted: auto-generated +""" + +REFCHANGE_INTRO_TEMPLATE = """\ +This is an automated email from the git hooks/post-receive script. + +%(pusher)s pushed a change to %(refname_type)s %(short_refname)s +in repository %(repo_shortname)s. + +""" + + +FOOTER_TEMPLATE = """\ + +-- \n\ +To stop receiving notification emails like this one, please contact +%(administrator)s. +""" + + +REWIND_ONLY_TEMPLATE = """\ +This update removed existing revisions from the reference, leaving the +reference pointing at a previous point in the repository history. + + * -- * -- N %(refname)s (%(newrev_short)s) + \\ + O -- O -- O (%(oldrev_short)s) + +Any revisions marked "omit" are not gone; other references still +refer to them. Any revisions marked "discard" are gone forever. +""" + + +NON_FF_TEMPLATE = """\ +This update added new revisions after undoing existing revisions. +That is to say, some revisions that were in the old version of the +%(refname_type)s are not in the new version. This situation occurs +when a user --force pushes a change and generates a repository +containing something like this: + + * -- * -- B -- O -- O -- O (%(oldrev_short)s) + \\ + N -- N -- N %(refname)s (%(newrev_short)s) + +You should already have received notification emails for all of the O +revisions, and so the following emails describe only the N revisions +from the common base, B. + +Any revisions marked "omit" are not gone; other references still +refer to them. Any revisions marked "discard" are gone forever. +""" + + +NO_NEW_REVISIONS_TEMPLATE = """\ +No new revisions were added by this update. +""" + + +DISCARDED_REVISIONS_TEMPLATE = """\ +This change permanently discards the following revisions: +""" + + +NO_DISCARDED_REVISIONS_TEMPLATE = """\ +The revisions that were on this %(refname_type)s are still contained in +other references; therefore, this change does not discard any commits +from the repository. +""" + + +NEW_REVISIONS_TEMPLATE = """\ +The %(tot)s revisions listed above as "new" are entirely new to this +repository and will be described in separate emails. The revisions +listed as "add" were already present in the repository and have only +been added to this reference. + +""" + + +TAG_CREATED_TEMPLATE = """\ + at %(newrev_short)-8s (%(newrev_type)s) +""" + + +TAG_UPDATED_TEMPLATE = """\ +*** WARNING: tag %(short_refname)s was modified! *** + + from %(oldrev_short)-8s (%(oldrev_type)s) + to %(newrev_short)-8s (%(newrev_type)s) +""" + + +TAG_DELETED_TEMPLATE = """\ +*** WARNING: tag %(short_refname)s was deleted! *** + +""" + + +# The template used in summary tables. It looks best if this uses the +# same alignment as TAG_CREATED_TEMPLATE and TAG_UPDATED_TEMPLATE. +BRIEF_SUMMARY_TEMPLATE = """\ +%(action)8s %(rev_short)-8s %(text)s +""" + + +NON_COMMIT_UPDATE_TEMPLATE = """\ +This is an unusual reference change because the reference did not +refer to a commit either before or after the change. We do not know +how to provide full information about this reference change. +""" + + +REVISION_HEADER_TEMPLATE = """\ +Date: %(send_date)s +To: %(recipients)s +Cc: %(cc_recipients)s +Subject: %(emailprefix)s%(num)02d/%(tot)02d: %(oneline)s +MIME-Version: 1.0 +Content-Type: text/%(contenttype)s; charset=%(charset)s +Content-Transfer-Encoding: 8bit +From: %(fromaddr)s +Reply-To: %(reply_to)s +In-Reply-To: %(reply_to_msgid)s +References: %(reply_to_msgid)s +Thread-Index: %(thread_index)s +X-Git-Host: %(fqdn)s +X-Git-Repo: %(repo_shortname)s +X-Git-Refname: %(refname)s +X-Git-Reftype: %(refname_type)s +X-Git-Rev: %(rev)s +X-Git-NotificationType: diff +X-Git-Multimail-Version: %(multimail_version)s +Auto-Submitted: auto-generated +""" + +REVISION_INTRO_TEMPLATE = """\ +This is an automated email from the git hooks/post-receive script. + +%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s +in repository %(repo_shortname)s. + +""" + +LINK_TEXT_TEMPLATE = """\ +View the commit online: +%(browse_url)s + +""" + +LINK_HTML_TEMPLATE = """\ +<p><a href="%(browse_url)s">View the commit online</a>.</p> +""" + + +REVISION_FOOTER_TEMPLATE = FOOTER_TEMPLATE + + +# Combined, meaning refchange+revision email (for single-commit additions) +COMBINED_HEADER_TEMPLATE = """\ +Date: %(send_date)s +To: %(recipients)s +Subject: %(subject)s +MIME-Version: 1.0 +Content-Type: text/%(contenttype)s; charset=%(charset)s +Content-Transfer-Encoding: 8bit +Message-ID: %(msgid)s +From: %(fromaddr)s +Reply-To: %(reply_to)s +X-Git-Host: %(fqdn)s +X-Git-Repo: %(repo_shortname)s +X-Git-Refname: %(refname)s +X-Git-Reftype: %(refname_type)s +X-Git-Oldrev: %(oldrev)s +X-Git-Newrev: %(newrev)s +X-Git-Rev: %(rev)s +X-Git-NotificationType: ref_changed_plus_diff +X-Git-Multimail-Version: %(multimail_version)s +Auto-Submitted: auto-generated +""" + +COMBINED_INTRO_TEMPLATE = """\ +This is an automated email from the git hooks/post-receive script. + +%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s +in repository %(repo_shortname)s. + +""" + +COMBINED_FOOTER_TEMPLATE = FOOTER_TEMPLATE + + +class CommandError(Exception): + def __init__(self, cmd, retcode): + self.cmd = cmd + self.retcode = retcode + Exception.__init__( + self, + 'Command "%s" failed with retcode %s' % (' '.join(cmd), retcode,) + ) + + +class ConfigurationException(Exception): + pass + + +# The "git" program (this could be changed to include a full path): +GIT_EXECUTABLE = 'git' + + +# How "git" should be invoked (including global arguments), as a list +# of words. This variable is usually initialized automatically by +# read_git_output() via choose_git_command(), but if a value is set +# here then it will be used unconditionally. +GIT_CMD = None + + +def choose_git_command(): + """Decide how to invoke git, and record the choice in GIT_CMD.""" + + global GIT_CMD + + if GIT_CMD is None: + try: + # Check to see whether the "-c" option is accepted (it was + # only added in Git 1.7.2). We don't actually use the + # output of "git --version", though if we needed more + # specific version information this would be the place to + # do it. + cmd = [GIT_EXECUTABLE, '-c', 'foo.bar=baz', '--version'] + read_output(cmd) + GIT_CMD = [GIT_EXECUTABLE, '-c', 'i18n.logoutputencoding=%s' % (ENCODING,)] + except CommandError: + GIT_CMD = [GIT_EXECUTABLE] + + +def read_git_output(args, input=None, keepends=False, **kw): + """Read the output of a Git command.""" + + if GIT_CMD is None: + choose_git_command() + + return read_output(GIT_CMD + args, input=input, keepends=keepends, **kw) + + +def read_output(cmd, input=None, keepends=False, **kw): + if input: + stdin = subprocess.PIPE + input = str_to_bytes(input) + else: + stdin = None + errors = 'strict' + if 'errors' in kw: + errors = kw['errors'] + del kw['errors'] + p = subprocess.Popen( + tuple(str_to_bytes(w) for w in cmd), + stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw + ) + (out, err) = p.communicate(input) + out = bytes_to_str(out, errors=errors) + retcode = p.wait() + if retcode: + raise CommandError(cmd, retcode) + if not keepends: + out = out.rstrip('\n\r') + return out + + +def read_git_lines(args, keepends=False, **kw): + """Return the lines output by Git command. + + Return as single lines, with newlines stripped off.""" + + return read_git_output(args, keepends=True, **kw).splitlines(keepends) + + +def git_rev_list_ish(cmd, spec, args=None, **kw): + """Common functionality for invoking a 'git rev-list'-like command. + + Parameters: + * cmd is the Git command to run, e.g., 'rev-list' or 'log'. + * spec is a list of revision arguments to pass to the named + command. If None, this function returns an empty list. + * args is a list of extra arguments passed to the named command. + * All other keyword arguments (if any) are passed to the + underlying read_git_lines() function. + + Return the output of the Git command in the form of a list, one + entry per output line. + """ + if spec is None: + return [] + if args is None: + args = [] + args = [cmd, '--stdin'] + args + spec_stdin = ''.join(s + '\n' for s in spec) + return read_git_lines(args, input=spec_stdin, **kw) + + +def git_rev_list(spec, **kw): + """Run 'git rev-list' with the given list of revision arguments. + + See git_rev_list_ish() for parameter and return value + documentation. + """ + return git_rev_list_ish('rev-list', spec, **kw) + + +def git_log(spec, **kw): + """Run 'git log' with the given list of revision arguments. + + See git_rev_list_ish() for parameter and return value + documentation. + """ + return git_rev_list_ish('log', spec, **kw) + + +def header_encode(text, header_name=None): + """Encode and line-wrap the value of an email header field.""" + + # Convert to unicode, if required. + if not isinstance(text, unicode): + text = unicode(text, 'utf-8') + + if is_ascii(text): + charset = 'ascii' + else: + charset = 'utf-8' + + return Header(text, header_name=header_name, charset=Charset(charset)).encode() + + +def addr_header_encode(text, header_name=None): + """Encode and line-wrap the value of an email header field containing + email addresses.""" + + # Convert to unicode, if required. + if not isinstance(text, unicode): + text = unicode(text, 'utf-8') + + text = ', '.join( + formataddr((header_encode(name), emailaddr)) + for name, emailaddr in getaddresses([text]) + ) + + if is_ascii(text): + charset = 'ascii' + else: + charset = 'utf-8' + + return Header(text, header_name=header_name, charset=Charset(charset)).encode() + + +class Config(object): + def __init__(self, section, git_config=None): + """Represent a section of the git configuration. + + If git_config is specified, it is passed to "git config" in + the GIT_CONFIG environment variable, meaning that "git config" + will read the specified path rather than the Git default + config paths.""" + + self.section = section + if git_config: + self.env = os.environ.copy() + self.env['GIT_CONFIG'] = git_config + else: + self.env = None + + @staticmethod + def _split(s): + """Split NUL-terminated values.""" + + words = s.split('\0') + assert words[-1] == '' + return words[:-1] + + @staticmethod + def add_config_parameters(c): + """Add configuration parameters to Git. + + c is either an str or a list of str, each element being of the + form 'var=val' or 'var', with the same syntax and meaning as + the argument of 'git -c var=val'. + """ + if isinstance(c, str): + c = (c,) + parameters = os.environ.get('GIT_CONFIG_PARAMETERS', '') + if parameters: + parameters += ' ' + # git expects GIT_CONFIG_PARAMETERS to be of the form + # "'name1=value1' 'name2=value2' 'name3=value3'" + # including everything inside the double quotes (but not the double + # quotes themselves). Spacing is critical. Also, if a value contains + # a literal single quote that quote must be represented using the + # four character sequence: '\'' + parameters += ' '.join("'" + x.replace("'", "'\\''") + "'" for x in c) + os.environ['GIT_CONFIG_PARAMETERS'] = parameters + + def get(self, name, default=None): + try: + values = self._split(read_git_output( + ['config', '--get', '--null', '%s.%s' % (self.section, name)], + env=self.env, keepends=True, + )) + assert len(values) == 1 + return values[0] + except CommandError: + return default + + def get_bool(self, name, default=None): + try: + value = read_git_output( + ['config', '--get', '--bool', '%s.%s' % (self.section, name)], + env=self.env, + ) + except CommandError: + return default + return value == 'true' + + def get_all(self, name, default=None): + """Read a (possibly multivalued) setting from the configuration. + + Return the result as a list of values, or default if the name + is unset.""" + + try: + return self._split(read_git_output( + ['config', '--get-all', '--null', '%s.%s' % (self.section, name)], + env=self.env, keepends=True, + )) + except CommandError: + t, e, traceback = sys.exc_info() + if e.retcode == 1: + # "the section or key is invalid"; i.e., there is no + # value for the specified key. + return default + else: + raise + + def set(self, name, value): + read_git_output( + ['config', '%s.%s' % (self.section, name), value], + env=self.env, + ) + + def add(self, name, value): + read_git_output( + ['config', '--add', '%s.%s' % (self.section, name), value], + env=self.env, + ) + + def __contains__(self, name): + return self.get_all(name, default=None) is not None + + # We don't use this method anymore internally, but keep it here in + # case somebody is calling it from their own code: + def has_key(self, name): + return name in self + + def unset_all(self, name): + try: + read_git_output( + ['config', '--unset-all', '%s.%s' % (self.section, name)], + env=self.env, + ) + except CommandError: + t, e, traceback = sys.exc_info() + if e.retcode == 5: + # The name doesn't exist, which is what we wanted anyway... + pass + else: + raise + + def set_recipients(self, name, value): + self.unset_all(name) + for pair in getaddresses([value]): + self.add(name, formataddr(pair)) + + +def generate_summaries(*log_args): + """Generate a brief summary for each revision requested. + + log_args are strings that will be passed directly to "git log" as + revision selectors. Iterate over (sha1_short, subject) for each + commit specified by log_args (subject is the first line of the + commit message as a string without EOLs).""" + + cmd = [ + 'log', '--abbrev', '--format=%h %s', + ] + list(log_args) + ['--'] + for line in read_git_lines(cmd): + yield tuple(line.split(' ', 1)) + + +def limit_lines(lines, max_lines): + for (index, line) in enumerate(lines): + if index < max_lines: + yield line + + if index >= max_lines: + yield '... %d lines suppressed ...\n' % (index + 1 - max_lines,) + + +def limit_linelength(lines, max_linelength): + for line in lines: + # Don't forget that lines always include a trailing newline. + if len(line) > max_linelength + 1: + line = line[:max_linelength - 7] + ' [...]\n' + yield line + + +class CommitSet(object): + """A (constant) set of object names. + + The set should be initialized with full SHA1 object names. The + __contains__() method returns True iff its argument is an + abbreviation of any the names in the set.""" + + def __init__(self, names): + self._names = sorted(names) + + def __len__(self): + return len(self._names) + + def __contains__(self, sha1_abbrev): + """Return True iff this set contains sha1_abbrev (which might be abbreviated).""" + + i = bisect.bisect_left(self._names, sha1_abbrev) + return i < len(self) and self._names[i].startswith(sha1_abbrev) + + +class GitObject(object): + def __init__(self, sha1, type=None): + if sha1 == ZEROS: + self.sha1 = self.type = self.commit_sha1 = None + else: + self.sha1 = sha1 + self.type = type or read_git_output(['cat-file', '-t', self.sha1]) + + if self.type == 'commit': + self.commit_sha1 = self.sha1 + elif self.type == 'tag': + try: + self.commit_sha1 = read_git_output( + ['rev-parse', '--verify', '%s^0' % (self.sha1,)] + ) + except CommandError: + # Cannot deref tag to determine commit_sha1 + self.commit_sha1 = None + else: + self.commit_sha1 = None + + self.short = read_git_output(['rev-parse', '--short', sha1]) + + def get_summary(self): + """Return (sha1_short, subject) for this commit.""" + + if not self.sha1: + raise ValueError('Empty commit has no summary') + + return next(iter(generate_summaries('--no-walk', self.sha1))) + + def __eq__(self, other): + return isinstance(other, GitObject) and self.sha1 == other.sha1 + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash(self.sha1) + + def __nonzero__(self): + return bool(self.sha1) + + def __bool__(self): + """Python 2 backward compatibility""" + return self.__nonzero__() + + def __str__(self): + return self.sha1 or ZEROS + + +class Change(object): + """A Change that has been made to the Git repository. + + Abstract class from which both Revisions and ReferenceChanges are + derived. A Change knows how to generate a notification email + describing itself.""" + + def __init__(self, environment): + self.environment = environment + self._values = None + self._contains_html_diff = False + + def _contains_diff(self): + # We do contain a diff, should it be rendered in HTML? + if self.environment.commit_email_format == "html": + self._contains_html_diff = True + + def _compute_values(self): + """Return a dictionary {keyword: expansion} for this Change. + + Derived classes overload this method to add more entries to + the return value. This method is used internally by + get_values(). The return value should always be a new + dictionary.""" + + values = self.environment.get_values() + fromaddr = self.environment.get_fromaddr(change=self) + if fromaddr is not None: + values['fromaddr'] = fromaddr + values['multimail_version'] = get_version() + return values + + # Aliases usable in template strings. Tuple of pairs (destination, + # source). + VALUES_ALIAS = ( + ("id", "newrev"), + ) + + def get_values(self, **extra_values): + """Return a dictionary {keyword: expansion} for this Change. + + Return a dictionary mapping keywords to the values that they + should be expanded to for this Change (used when interpolating + template strings). If any keyword arguments are supplied, add + those to the return value as well. The return value is always + a new dictionary.""" + + if self._values is None: + self._values = self._compute_values() + + values = self._values.copy() + if extra_values: + values.update(extra_values) + + for alias, val in self.VALUES_ALIAS: + values[alias] = values[val] + return values + + def expand(self, template, **extra_values): + """Expand template. + + Expand the template (which should be a string) using string + interpolation of the values for this Change. If any keyword + arguments are provided, also include those in the keywords + available for interpolation.""" + + return template % self.get_values(**extra_values) + + def expand_lines(self, template, html_escape_val=False, **extra_values): + """Break template into lines and expand each line.""" + + values = self.get_values(**extra_values) + if html_escape_val: + for k in values: + if is_string(values[k]): + values[k] = html_escape(values[k]) + for line in template.splitlines(True): + yield line % values + + def expand_header_lines(self, template, **extra_values): + """Break template into lines and expand each line as an RFC 2822 header. + + Encode values and split up lines that are too long. Silently + skip lines that contain references to unknown variables.""" + + values = self.get_values(**extra_values) + if self._contains_html_diff: + self._content_type = 'html' + else: + self._content_type = 'plain' + values['contenttype'] = self._content_type + + for line in template.splitlines(): + (name, value) = line.split(': ', 1) + + try: + value = value % values + except KeyError: + t, e, traceback = sys.exc_info() + if DEBUG: + self.environment.log_warning( + 'Warning: unknown variable %r in the following line; line skipped:\n' + ' %s\n' + % (e.args[0], line,) + ) + else: + if name.lower() in ADDR_HEADERS: + value = addr_header_encode(value, name) + else: + value = header_encode(value, name) + for splitline in ('%s: %s\n' % (name, value)).splitlines(True): + yield splitline + + def generate_email_header(self): + """Generate the RFC 2822 email headers for this Change, a line at a time. + + The output should not include the trailing blank line.""" + + raise NotImplementedError() + + def generate_browse_link(self, base_url): + """Generate a link to an online repository browser.""" + return iter(()) + + def generate_email_intro(self, html_escape_val=False): + """Generate the email intro for this Change, a line at a time. + + The output will be used as the standard boilerplate at the top + of the email body.""" + + raise NotImplementedError() + + def generate_email_body(self, push): + """Generate the main part of the email body, a line at a time. + + The text in the body might be truncated after a specified + number of lines (see multimailhook.emailmaxlines).""" + + raise NotImplementedError() + + def generate_email_footer(self, html_escape_val): + """Generate the footer of the email, a line at a time. + + The footer is always included, irrespective of + multimailhook.emailmaxlines.""" + + raise NotImplementedError() + + def _wrap_for_html(self, lines): + """Wrap the lines in HTML <pre> tag when using HTML format. + + Escape special HTML characters and add <pre> and </pre> tags around + the given lines if we should be generating HTML as indicated by + self._contains_html_diff being set to true. + """ + if self._contains_html_diff: + yield "<pre style='margin:0'>\n" + + for line in lines: + yield html_escape(line) + + yield '</pre>\n' + else: + for line in lines: + yield line + + def generate_email(self, push, body_filter=None, extra_header_values={}): + """Generate an email describing this change. + + Iterate over the lines (including the header lines) of an + email describing this change. If body_filter is not None, + then use it to filter the lines that are intended for the + email body. + + The extra_header_values field is received as a dict and not as + **kwargs, to allow passing other keyword arguments in the + future (e.g. passing extra values to generate_email_intro()""" + + for line in self.generate_email_header(**extra_header_values): + yield line + yield '\n' + html_escape_val = (self.environment.html_in_intro and + self._contains_html_diff) + intro = self.generate_email_intro(html_escape_val) + if not self.environment.html_in_intro: + intro = self._wrap_for_html(intro) + for line in intro: + yield line + + if self.environment.commitBrowseURL: + for line in self.generate_browse_link(self.environment.commitBrowseURL): + yield line + + body = self.generate_email_body(push) + if body_filter is not None: + body = body_filter(body) + + diff_started = False + if self._contains_html_diff: + # "white-space: pre" is the default, but we need to + # specify it again in case the message is viewed in a + # webmail which wraps it in an element setting white-space + # to something else (Zimbra does this and sets + # white-space: pre-line). + yield '<pre style="white-space: pre; background: #F8F8F8">' + for line in body: + if self._contains_html_diff: + # This is very, very naive. It would be much better to really + # parse the diff, i.e. look at how many lines do we have in + # the hunk headers instead of blindly highlighting everything + # that looks like it might be part of a diff. + bgcolor = '' + fgcolor = '' + if line.startswith('--- a/'): + diff_started = True + bgcolor = 'e0e0ff' + elif line.startswith('diff ') or line.startswith('index '): + diff_started = True + fgcolor = '808080' + elif diff_started: + if line.startswith('+++ '): + bgcolor = 'e0e0ff' + elif line.startswith('@@'): + bgcolor = 'e0e0e0' + elif line.startswith('+'): + bgcolor = 'e0ffe0' + elif line.startswith('-'): + bgcolor = 'ffe0e0' + elif line.startswith('commit '): + fgcolor = '808000' + elif line.startswith(' '): + fgcolor = '404040' + + # Chop the trailing LF, we don't want it inside <pre>. + line = html_escape(line[:-1]) + + if bgcolor or fgcolor: + style = 'display:block; white-space:pre;' + if bgcolor: + style += 'background:#' + bgcolor + ';' + if fgcolor: + style += 'color:#' + fgcolor + ';' + # Use a <span style='display:block> to color the + # whole line. The newline must be inside the span + # to display properly both in Firefox and in + # text-based browser. + line = "<span style='%s'>%s\n</span>" % (style, line) + else: + line = line + '\n' + + yield line + if self._contains_html_diff: + yield '</pre>' + html_escape_val = (self.environment.html_in_footer and + self._contains_html_diff) + footer = self.generate_email_footer(html_escape_val) + if not self.environment.html_in_footer: + footer = self._wrap_for_html(footer) + for line in footer: + yield line + + def get_specific_fromaddr(self): + """For kinds of Changes which specify it, return the kind-specific + From address to use.""" + return None + + +class Revision(Change): + """A Change consisting of a single git commit.""" + + CC_RE = re.compile(r'^\s*C[Cc]:\s*(?P<to>[^#]+@[^\s#]*)\s*(#.*)?$') + + def __init__(self, reference_change, rev, num, tot): + Change.__init__(self, reference_change.environment) + self.reference_change = reference_change + self.rev = rev + self.change_type = self.reference_change.change_type + self.refname = self.reference_change.refname + self.num = num + self.tot = tot + self.author = read_git_output(['log', '--no-walk', '--format=%aN <%aE>', self.rev.sha1]) + self.recipients = self.environment.get_revision_recipients(self) + + # -s is short for --no-patch, but -s works on older git's (e.g. 1.7) + self.parents = read_git_lines(['show', '-s', '--format=%P', + self.rev.sha1])[0].split() + + self.cc_recipients = '' + if self.environment.get_scancommitforcc(): + self.cc_recipients = ', '.join(to.strip() for to in self._cc_recipients()) + if self.cc_recipients: + self.environment.log_msg( + 'Add %s to CC for %s' % (self.cc_recipients, self.rev.sha1)) + + def _cc_recipients(self): + cc_recipients = [] + message = read_git_output(['log', '--no-walk', '--format=%b', self.rev.sha1]) + lines = message.strip().split('\n') + for line in lines: + m = re.match(self.CC_RE, line) + if m: + cc_recipients.append(m.group('to')) + + return cc_recipients + + def _compute_values(self): + values = Change._compute_values(self) + + oneline = read_git_output( + ['log', '--format=%s', '--no-walk', self.rev.sha1] + ) + + max_subject_length = self.environment.get_max_subject_length() + if max_subject_length > 0 and len(oneline) > max_subject_length: + oneline = oneline[:max_subject_length - 6] + ' [...]' + + values['rev'] = self.rev.sha1 + values['parents'] = ' '.join(self.parents) + values['rev_short'] = self.rev.short + values['change_type'] = self.change_type + values['refname'] = self.refname + values['newrev'] = self.rev.sha1 + values['short_refname'] = self.reference_change.short_refname + values['refname_type'] = self.reference_change.refname_type + values['reply_to_msgid'] = self.reference_change.msgid + values['thread_index'] = self.reference_change.thread_index + values['num'] = self.num + values['tot'] = self.tot + values['recipients'] = self.recipients + if self.cc_recipients: + values['cc_recipients'] = self.cc_recipients + values['oneline'] = oneline + values['author'] = self.author + + reply_to = self.environment.get_reply_to_commit(self) + if reply_to: + values['reply_to'] = reply_to + + return values + + def generate_email_header(self, **extra_values): + for line in self.expand_header_lines( + REVISION_HEADER_TEMPLATE, **extra_values + ): + yield line + + def generate_browse_link(self, base_url): + if '%(' not in base_url: + base_url += '%(id)s' + url = "".join(self.expand_lines(base_url)) + if self._content_type == 'html': + for line in self.expand_lines(LINK_HTML_TEMPLATE, + html_escape_val=True, + browse_url=url): + yield line + elif self._content_type == 'plain': + for line in self.expand_lines(LINK_TEXT_TEMPLATE, + html_escape_val=False, + browse_url=url): + yield line + else: + raise NotImplementedError("Content-type %s unsupported. Please report it as a bug.") + + def generate_email_intro(self, html_escape_val=False): + for line in self.expand_lines(REVISION_INTRO_TEMPLATE, + html_escape_val=html_escape_val): + yield line + + def generate_email_body(self, push): + """Show this revision.""" + + for line in read_git_lines( + ['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1], + keepends=True, + errors='replace'): + if line.startswith('Date: ') and self.environment.date_substitute: + yield self.environment.date_substitute + line[len('Date: '):] + else: + yield line + + def generate_email_footer(self, html_escape_val): + return self.expand_lines(REVISION_FOOTER_TEMPLATE, + html_escape_val=html_escape_val) + + def generate_email(self, push, body_filter=None, extra_header_values={}): + self._contains_diff() + return Change.generate_email(self, push, body_filter, extra_header_values) + + def get_specific_fromaddr(self): + return self.environment.from_commit + + +class ReferenceChange(Change): + """A Change to a Git reference. + + An abstract class representing a create, update, or delete of a + Git reference. Derived classes handle specific types of reference + (e.g., tags vs. branches). These classes generate the main + reference change email summarizing the reference change and + whether it caused any any commits to be added or removed. + + ReferenceChange objects are usually created using the static + create() method, which has the logic to decide which derived class + to instantiate.""" + + REF_RE = re.compile(r'^refs\/(?P<area>[^\/]+)\/(?P<shortname>.*)$') + + @staticmethod + def create(environment, oldrev, newrev, refname): + """Return a ReferenceChange object representing the change. + + Return an object that represents the type of change that is being + made. oldrev and newrev should be SHA1s or ZEROS.""" + + old = GitObject(oldrev) + new = GitObject(newrev) + rev = new or old + + # The revision type tells us what type the commit is, combined with + # the location of the ref we can decide between + # - working branch + # - tracking branch + # - unannotated tag + # - annotated tag + m = ReferenceChange.REF_RE.match(refname) + if m: + area = m.group('area') + short_refname = m.group('shortname') + else: + area = '' + short_refname = refname + + if rev.type == 'tag': + # Annotated tag: + klass = AnnotatedTagChange + elif rev.type == 'commit': + if area == 'tags': + # Non-annotated tag: + klass = NonAnnotatedTagChange + elif area == 'heads': + # Branch: + klass = BranchChange + elif area == 'remotes': + # Tracking branch: + environment.log_warning( + '*** Push-update of tracking branch %r\n' + '*** - incomplete email generated.' + % (refname,) + ) + klass = OtherReferenceChange + else: + # Some other reference namespace: + environment.log_warning( + '*** Push-update of strange reference %r\n' + '*** - incomplete email generated.' + % (refname,) + ) + klass = OtherReferenceChange + else: + # Anything else (is there anything else?) + environment.log_warning( + '*** Unknown type of update to %r (%s)\n' + '*** - incomplete email generated.' + % (refname, rev.type,) + ) + klass = OtherReferenceChange + + return klass( + environment, + refname=refname, short_refname=short_refname, + old=old, new=new, rev=rev, + ) + + @staticmethod + def make_thread_index(): + """Return a string appropriate for the Thread-Index header, + needed by MS Outlook to get threading right. + + The format is (base64-encoded): + - 1 byte must be 1 + - 5 bytes encode a date (hardcoded here) + - 16 bytes for a globally unique identifier + + FIXME: Unfortunately, even with the Thread-Index field, MS + Outlook doesn't seem to do the threading reliably (see + https://github.com/git-multimail/git-multimail/pull/194). + """ + thread_index = b'\x01\x00\x00\x12\x34\x56' + uuid.uuid4().bytes + return base64.standard_b64encode(thread_index).decode('ascii') + + def __init__(self, environment, refname, short_refname, old, new, rev): + Change.__init__(self, environment) + self.change_type = { + (False, True): 'create', + (True, True): 'update', + (True, False): 'delete', + }[bool(old), bool(new)] + self.refname = refname + self.short_refname = short_refname + self.old = old + self.new = new + self.rev = rev + self.msgid = make_msgid() + self.thread_index = self.make_thread_index() + self.diffopts = environment.diffopts + self.graphopts = environment.graphopts + self.logopts = environment.logopts + self.commitlogopts = environment.commitlogopts + self.showgraph = environment.refchange_showgraph + self.showlog = environment.refchange_showlog + + self.header_template = REFCHANGE_HEADER_TEMPLATE + self.intro_template = REFCHANGE_INTRO_TEMPLATE + self.footer_template = FOOTER_TEMPLATE + + def _compute_values(self): + values = Change._compute_values(self) + + values['change_type'] = self.change_type + values['refname_type'] = self.refname_type + values['refname'] = self.refname + values['short_refname'] = self.short_refname + values['msgid'] = self.msgid + values['thread_index'] = self.thread_index + values['recipients'] = self.recipients + values['oldrev'] = str(self.old) + values['oldrev_short'] = self.old.short + values['newrev'] = str(self.new) + values['newrev_short'] = self.new.short + + if self.old: + values['oldrev_type'] = self.old.type + if self.new: + values['newrev_type'] = self.new.type + + reply_to = self.environment.get_reply_to_refchange(self) + if reply_to: + values['reply_to'] = reply_to + + return values + + def send_single_combined_email(self, known_added_sha1s): + """Determine if a combined refchange/revision email should be sent + + If there is only a single new (non-merge) commit added by a + change, it is useful to combine the ReferenceChange and + Revision emails into one. In such a case, return the single + revision; otherwise, return None. + + This method is overridden in BranchChange.""" + + return None + + def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}): + """Generate an email describing this change AND specified revision. + + Iterate over the lines (including the header lines) of an + email describing this change. If body_filter is not None, + then use it to filter the lines that are intended for the + email body. + + The extra_header_values field is received as a dict and not as + **kwargs, to allow passing other keyword arguments in the + future (e.g. passing extra values to generate_email_intro() + + This method is overridden in BranchChange.""" + + raise NotImplementedError + + def get_subject(self): + template = { + 'create': REF_CREATED_SUBJECT_TEMPLATE, + 'update': REF_UPDATED_SUBJECT_TEMPLATE, + 'delete': REF_DELETED_SUBJECT_TEMPLATE, + }[self.change_type] + return self.expand(template) + + def generate_email_header(self, **extra_values): + if 'subject' not in extra_values: + extra_values['subject'] = self.get_subject() + + for line in self.expand_header_lines( + self.header_template, **extra_values + ): + yield line + + def generate_email_intro(self, html_escape_val=False): + for line in self.expand_lines(self.intro_template, + html_escape_val=html_escape_val): + yield line + + def generate_email_body(self, push): + """Call the appropriate body-generation routine. + + Call one of generate_create_summary() / + generate_update_summary() / generate_delete_summary().""" + + change_summary = { + 'create': self.generate_create_summary, + 'delete': self.generate_delete_summary, + 'update': self.generate_update_summary, + }[self.change_type](push) + for line in change_summary: + yield line + + for line in self.generate_revision_change_summary(push): + yield line + + def generate_email_footer(self, html_escape_val): + return self.expand_lines(self.footer_template, + html_escape_val=html_escape_val) + + def generate_revision_change_graph(self, push): + if self.showgraph: + args = ['--graph'] + self.graphopts + for newold in ('new', 'old'): + has_newold = False + spec = push.get_commits_spec(newold, self) + for line in git_log(spec, args=args, keepends=True): + if not has_newold: + has_newold = True + yield '\n' + yield 'Graph of %s commits:\n\n' % ( + {'new': 'new', 'old': 'discarded'}[newold],) + yield ' ' + line + if has_newold: + yield '\n' + + def generate_revision_change_log(self, new_commits_list): + if self.showlog: + yield '\n' + yield 'Detailed log of new commits:\n\n' + for line in read_git_lines( + ['log', '--no-walk'] + + self.logopts + + new_commits_list + + ['--'], + keepends=True, + ): + yield line + + def generate_new_revision_summary(self, tot, new_commits_list, push): + for line in self.expand_lines(NEW_REVISIONS_TEMPLATE, tot=tot): + yield line + for line in self.generate_revision_change_graph(push): + yield line + for line in self.generate_revision_change_log(new_commits_list): + yield line + + def generate_revision_change_summary(self, push): + """Generate a summary of the revisions added/removed by this change.""" + + if self.new.commit_sha1 and not self.old.commit_sha1: + # A new reference was created. List the new revisions + # brought by the new reference (i.e., those revisions that + # were not in the repository before this reference + # change). + sha1s = list(push.get_new_commits(self)) + sha1s.reverse() + tot = len(sha1s) + new_revisions = [ + Revision(self, GitObject(sha1), num=i + 1, tot=tot) + for (i, sha1) in enumerate(sha1s) + ] + + if new_revisions: + yield self.expand('This %(refname_type)s includes the following new commits:\n') + yield '\n' + for r in new_revisions: + (sha1, subject) = r.rev.get_summary() + yield r.expand( + BRIEF_SUMMARY_TEMPLATE, action='new', text=subject, + ) + yield '\n' + for line in self.generate_new_revision_summary( + tot, [r.rev.sha1 for r in new_revisions], push): + yield line + else: + for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE): + yield line + + elif self.new.commit_sha1 and self.old.commit_sha1: + # A reference was changed to point at a different commit. + # List the revisions that were removed and/or added *from + # that reference* by this reference change, along with a + # diff between the trees for its old and new values. + + # List of the revisions that were added to the branch by + # this update. Note this list can include revisions that + # have already had notification emails; we want such + # revisions in the summary even though we will not send + # new notification emails for them. + adds = list(generate_summaries( + '--topo-order', '--reverse', '%s..%s' + % (self.old.commit_sha1, self.new.commit_sha1,) + )) + + # List of the revisions that were removed from the branch + # by this update. This will be empty except for + # non-fast-forward updates. + discards = list(generate_summaries( + '%s..%s' % (self.new.commit_sha1, self.old.commit_sha1,) + )) + + if adds: + new_commits_list = push.get_new_commits(self) + else: + new_commits_list = [] + new_commits = CommitSet(new_commits_list) + + if discards: + discarded_commits = CommitSet(push.get_discarded_commits(self)) + else: + discarded_commits = CommitSet([]) + + if discards and adds: + for (sha1, subject) in discards: + if sha1 in discarded_commits: + action = 'discard' + else: + action = 'omit' + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action=action, + rev_short=sha1, text=subject, + ) + for (sha1, subject) in adds: + if sha1 in new_commits: + action = 'new' + else: + action = 'add' + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action=action, + rev_short=sha1, text=subject, + ) + yield '\n' + for line in self.expand_lines(NON_FF_TEMPLATE): + yield line + + elif discards: + for (sha1, subject) in discards: + if sha1 in discarded_commits: + action = 'discard' + else: + action = 'omit' + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action=action, + rev_short=sha1, text=subject, + ) + yield '\n' + for line in self.expand_lines(REWIND_ONLY_TEMPLATE): + yield line + + elif adds: + (sha1, subject) = self.old.get_summary() + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action='from', + rev_short=sha1, text=subject, + ) + for (sha1, subject) in adds: + if sha1 in new_commits: + action = 'new' + else: + action = 'add' + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action=action, + rev_short=sha1, text=subject, + ) + + yield '\n' + + if new_commits: + for line in self.generate_new_revision_summary( + len(new_commits), new_commits_list, push): + yield line + else: + for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE): + yield line + for line in self.generate_revision_change_graph(push): + yield line + + # The diffstat is shown from the old revision to the new + # revision. This is to show the truth of what happened in + # this change. There's no point showing the stat from the + # base to the new revision because the base is effectively a + # random revision at this point - the user will be interested + # in what this revision changed - including the undoing of + # previous revisions in the case of non-fast-forward updates. + yield '\n' + yield 'Summary of changes:\n' + for line in read_git_lines( + ['diff-tree'] + + self.diffopts + + ['%s..%s' % (self.old.commit_sha1, self.new.commit_sha1,)], + keepends=True, + ): + yield line + + elif self.old.commit_sha1 and not self.new.commit_sha1: + # A reference was deleted. List the revisions that were + # removed from the repository by this reference change. + + sha1s = list(push.get_discarded_commits(self)) + tot = len(sha1s) + discarded_revisions = [ + Revision(self, GitObject(sha1), num=i + 1, tot=tot) + for (i, sha1) in enumerate(sha1s) + ] + + if discarded_revisions: + for line in self.expand_lines(DISCARDED_REVISIONS_TEMPLATE): + yield line + yield '\n' + for r in discarded_revisions: + (sha1, subject) = r.rev.get_summary() + yield r.expand( + BRIEF_SUMMARY_TEMPLATE, action='discard', text=subject, + ) + for line in self.generate_revision_change_graph(push): + yield line + else: + for line in self.expand_lines(NO_DISCARDED_REVISIONS_TEMPLATE): + yield line + + elif not self.old.commit_sha1 and not self.new.commit_sha1: + for line in self.expand_lines(NON_COMMIT_UPDATE_TEMPLATE): + yield line + + def generate_create_summary(self, push): + """Called for the creation of a reference.""" + + # This is a new reference and so oldrev is not valid + (sha1, subject) = self.new.get_summary() + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action='at', + rev_short=sha1, text=subject, + ) + yield '\n' + + def generate_update_summary(self, push): + """Called for the change of a pre-existing branch.""" + + return iter([]) + + def generate_delete_summary(self, push): + """Called for the deletion of any type of reference.""" + + (sha1, subject) = self.old.get_summary() + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action='was', + rev_short=sha1, text=subject, + ) + yield '\n' + + def get_specific_fromaddr(self): + return self.environment.from_refchange + + +class BranchChange(ReferenceChange): + refname_type = 'branch' + + def __init__(self, environment, refname, short_refname, old, new, rev): + ReferenceChange.__init__( + self, environment, + refname=refname, short_refname=short_refname, + old=old, new=new, rev=rev, + ) + self.recipients = environment.get_refchange_recipients(self) + self._single_revision = None + + def send_single_combined_email(self, known_added_sha1s): + if not self.environment.combine_when_single_commit: + return None + + # In the sadly-all-too-frequent usecase of people pushing only + # one of their commits at a time to a repository, users feel + # the reference change summary emails are noise rather than + # important signal. This is because, in this particular + # usecase, there is a reference change summary email for each + # new commit, and all these summaries do is point out that + # there is one new commit (which can readily be inferred by + # the existence of the individual revision email that is also + # sent). In such cases, our users prefer there to be a combined + # reference change summary/new revision email. + # + # So, if the change is an update and it doesn't discard any + # commits, and it adds exactly one non-merge commit (gerrit + # forces a workflow where every commit is individually merged + # and the git-multimail hook fired off for just this one + # change), then we send a combined refchange/revision email. + try: + # If this change is a reference update that doesn't discard + # any commits... + if self.change_type != 'update': + return None + + if read_git_lines( + ['merge-base', self.old.sha1, self.new.sha1] + ) != [self.old.sha1]: + return None + + # Check if this update introduced exactly one non-merge + # commit: + + def split_line(line): + """Split line into (sha1, [parent,...]).""" + + words = line.split() + return (words[0], words[1:]) + + # Get the new commits introduced by the push as a list of + # (sha1, [parent,...]) + new_commits = [ + split_line(line) + for line in read_git_lines( + [ + 'log', '-3', '--format=%H %P', + '%s..%s' % (self.old.sha1, self.new.sha1), + ] + ) + ] + + if not new_commits: + return None + + # If the newest commit is a merge, save it for a later check + # but otherwise ignore it + merge = None + tot = len(new_commits) + if len(new_commits[0][1]) > 1: + merge = new_commits[0][0] + del new_commits[0] + + # Our primary check: we can't combine if more than one commit + # is introduced. We also currently only combine if the new + # commit is a non-merge commit, though it may make sense to + # combine if it is a merge as well. + if not ( + len(new_commits) == 1 and + len(new_commits[0][1]) == 1 and + new_commits[0][0] in known_added_sha1s + ): + return None + + # We do not want to combine revision and refchange emails if + # those go to separate locations. + rev = Revision(self, GitObject(new_commits[0][0]), 1, tot) + if rev.recipients != self.recipients: + return None + + # We ignored the newest commit if it was just a merge of the one + # commit being introduced. But we don't want to ignore that + # merge commit it it involved conflict resolutions. Check that. + if merge and merge != read_git_output(['diff-tree', '--cc', merge]): + return None + + # We can combine the refchange and one new revision emails + # into one. Return the Revision that a combined email should + # be sent about. + return rev + except CommandError: + # Cannot determine number of commits in old..new or new..old; + # don't combine reference/revision emails: + return None + + def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}): + values = revision.get_values() + if extra_header_values: + values.update(extra_header_values) + if 'subject' not in extra_header_values: + values['subject'] = self.expand(COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE, **values) + + self._single_revision = revision + self._contains_diff() + self.header_template = COMBINED_HEADER_TEMPLATE + self.intro_template = COMBINED_INTRO_TEMPLATE + self.footer_template = COMBINED_FOOTER_TEMPLATE + + def revision_gen_link(base_url): + # revision is used only to generate the body, and + # _content_type is set while generating headers. Get it + # from the BranchChange object. + revision._content_type = self._content_type + return revision.generate_browse_link(base_url) + self.generate_browse_link = revision_gen_link + for line in self.generate_email(push, body_filter, values): + yield line + + def generate_email_body(self, push): + '''Call the appropriate body generation routine. + + If this is a combined refchange/revision email, the special logic + for handling this combined email comes from this function. For + other cases, we just use the normal handling.''' + + # If self._single_revision isn't set; don't override + if not self._single_revision: + for line in super(BranchChange, self).generate_email_body(push): + yield line + return + + # This is a combined refchange/revision email; we first provide + # some info from the refchange portion, and then call the revision + # generate_email_body function to handle the revision portion. + adds = list(generate_summaries( + '--topo-order', '--reverse', '%s..%s' + % (self.old.commit_sha1, self.new.commit_sha1,) + )) + + yield self.expand("The following commit(s) were added to %(refname)s by this push:\n") + for (sha1, subject) in adds: + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action='new', + rev_short=sha1, text=subject, + ) + + yield self._single_revision.rev.short + " is described below\n" + yield '\n' + + for line in self._single_revision.generate_email_body(push): + yield line + + +class AnnotatedTagChange(ReferenceChange): + refname_type = 'annotated tag' + + def __init__(self, environment, refname, short_refname, old, new, rev): + ReferenceChange.__init__( + self, environment, + refname=refname, short_refname=short_refname, + old=old, new=new, rev=rev, + ) + self.recipients = environment.get_announce_recipients(self) + self.show_shortlog = environment.announce_show_shortlog + + ANNOTATED_TAG_FORMAT = ( + '%(*objectname)\n' + '%(*objecttype)\n' + '%(taggername)\n' + '%(taggerdate)' + ) + + def describe_tag(self, push): + """Describe the new value of an annotated tag.""" + + # Use git for-each-ref to pull out the individual fields from + # the tag + [tagobject, tagtype, tagger, tagged] = read_git_lines( + ['for-each-ref', '--format=%s' % (self.ANNOTATED_TAG_FORMAT,), self.refname], + ) + + yield self.expand( + BRIEF_SUMMARY_TEMPLATE, action='tagging', + rev_short=tagobject, text='(%s)' % (tagtype,), + ) + if tagtype == 'commit': + # If the tagged object is a commit, then we assume this is a + # release, and so we calculate which tag this tag is + # replacing + try: + prevtag = read_git_output(['describe', '--abbrev=0', '%s^' % (self.new,)]) + except CommandError: + prevtag = None + if prevtag: + yield ' replaces %s\n' % (prevtag,) + else: + prevtag = None + yield ' length %s bytes\n' % (read_git_output(['cat-file', '-s', tagobject]),) + + yield ' by %s\n' % (tagger,) + yield ' on %s\n' % (tagged,) + yield '\n' + + # Show the content of the tag message; this might contain a + # change log or release notes so is worth displaying. + yield LOGBEGIN + contents = list(read_git_lines(['cat-file', 'tag', self.new.sha1], keepends=True)) + contents = contents[contents.index('\n') + 1:] + if contents and contents[-1][-1:] != '\n': + contents.append('\n') + for line in contents: + yield line + + if self.show_shortlog and tagtype == 'commit': + # Only commit tags make sense to have rev-list operations + # performed on them + yield '\n' + if prevtag: + # Show changes since the previous release + revlist = read_git_output( + ['rev-list', '--pretty=short', '%s..%s' % (prevtag, self.new,)], + keepends=True, + ) + else: + # No previous tag, show all the changes since time + # began + revlist = read_git_output( + ['rev-list', '--pretty=short', '%s' % (self.new,)], + keepends=True, + ) + for line in read_git_lines(['shortlog'], input=revlist, keepends=True): + yield line + + yield LOGEND + yield '\n' + + def generate_create_summary(self, push): + """Called for the creation of an annotated tag.""" + + for line in self.expand_lines(TAG_CREATED_TEMPLATE): + yield line + + for line in self.describe_tag(push): + yield line + + def generate_update_summary(self, push): + """Called for the update of an annotated tag. + + This is probably a rare event and may not even be allowed.""" + + for line in self.expand_lines(TAG_UPDATED_TEMPLATE): + yield line + + for line in self.describe_tag(push): + yield line + + def generate_delete_summary(self, push): + """Called when a non-annotated reference is updated.""" + + for line in self.expand_lines(TAG_DELETED_TEMPLATE): + yield line + + yield self.expand(' tag was %(oldrev_short)s\n') + yield '\n' + + +class NonAnnotatedTagChange(ReferenceChange): + refname_type = 'tag' + + def __init__(self, environment, refname, short_refname, old, new, rev): + ReferenceChange.__init__( + self, environment, + refname=refname, short_refname=short_refname, + old=old, new=new, rev=rev, + ) + self.recipients = environment.get_refchange_recipients(self) + + def generate_create_summary(self, push): + """Called for the creation of an annotated tag.""" + + for line in self.expand_lines(TAG_CREATED_TEMPLATE): + yield line + + def generate_update_summary(self, push): + """Called when a non-annotated reference is updated.""" + + for line in self.expand_lines(TAG_UPDATED_TEMPLATE): + yield line + + def generate_delete_summary(self, push): + """Called when a non-annotated reference is updated.""" + + for line in self.expand_lines(TAG_DELETED_TEMPLATE): + yield line + + for line in ReferenceChange.generate_delete_summary(self, push): + yield line + + +class OtherReferenceChange(ReferenceChange): + refname_type = 'reference' + + def __init__(self, environment, refname, short_refname, old, new, rev): + # We use the full refname as short_refname, because otherwise + # the full name of the reference would not be obvious from the + # text of the email. + ReferenceChange.__init__( + self, environment, + refname=refname, short_refname=refname, + old=old, new=new, rev=rev, + ) + self.recipients = environment.get_refchange_recipients(self) + + +class Mailer(object): + """An object that can send emails.""" + + def __init__(self, environment): + self.environment = environment + + def close(self): + pass + + def send(self, lines, to_addrs): + """Send an email consisting of lines. + + lines must be an iterable over the lines constituting the + header and body of the email. to_addrs is a list of recipient + addresses (can be needed even if lines already contains a + "To:" field). It can be either a string (comma-separated list + of email addresses) or a Python list of individual email + addresses. + + """ + + raise NotImplementedError() + + +class SendMailer(Mailer): + """Send emails using 'sendmail -oi -t'.""" + + SENDMAIL_CANDIDATES = [ + '/usr/sbin/sendmail', + '/usr/lib/sendmail', + ] + + @staticmethod + def find_sendmail(): + for path in SendMailer.SENDMAIL_CANDIDATES: + if os.access(path, os.X_OK): + return path + else: + raise ConfigurationException( + 'No sendmail executable found. ' + 'Try setting multimailhook.sendmailCommand.' + ) + + def __init__(self, environment, command=None, envelopesender=None): + """Construct a SendMailer instance. + + command should be the command and arguments used to invoke + sendmail, as a list of strings. If an envelopesender is + provided, it will also be passed to the command, via '-f + envelopesender'.""" + super(SendMailer, self).__init__(environment) + if command: + self.command = command[:] + else: + self.command = [self.find_sendmail(), '-oi', '-t'] + + if envelopesender: + self.command.extend(['-f', envelopesender]) + + def send(self, lines, to_addrs): + try: + p = subprocess.Popen(self.command, stdin=subprocess.PIPE) + except OSError: + self.environment.get_logger().error( + '*** Cannot execute command: %s\n' % ' '.join(self.command) + + '*** %s\n' % sys.exc_info()[1] + + '*** Try setting multimailhook.mailer to "smtp"\n' + + '*** to send emails without using the sendmail command.\n' + ) + sys.exit(1) + try: + lines = (str_to_bytes(line) for line in lines) + p.stdin.writelines(lines) + except Exception: + self.environment.get_logger().error( + '*** Error while generating commit email\n' + '*** - mail sending aborted.\n' + ) + if hasattr(p, 'terminate'): + # subprocess.terminate() is not available in Python 2.4 + p.terminate() + else: + import signal + os.kill(p.pid, signal.SIGTERM) + raise + else: + p.stdin.close() + retcode = p.wait() + if retcode: + raise CommandError(self.command, retcode) + + +class SMTPMailer(Mailer): + """Send emails using Python's smtplib.""" + + def __init__(self, environment, + envelopesender, smtpserver, + smtpservertimeout=10.0, smtpserverdebuglevel=0, + smtpencryption='none', + smtpuser='', smtppass='', + smtpcacerts='' + ): + super(SMTPMailer, self).__init__(environment) + if not envelopesender: + self.environment.get_logger().error( + 'fatal: git_multimail: cannot use SMTPMailer without a sender address.\n' + 'please set either multimailhook.envelopeSender or user.email\n' + ) + sys.exit(1) + if smtpencryption == 'ssl' and not (smtpuser and smtppass): + raise ConfigurationException( + 'Cannot use SMTPMailer with security option ssl ' + 'without options username and password.' + ) + self.envelopesender = envelopesender + self.smtpserver = smtpserver + self.smtpservertimeout = smtpservertimeout + self.smtpserverdebuglevel = smtpserverdebuglevel + self.security = smtpencryption + self.username = smtpuser + self.password = smtppass + self.smtpcacerts = smtpcacerts + self.loggedin = False + try: + def call(klass, server, timeout): + try: + return klass(server, timeout=timeout) + except TypeError: + # Old Python versions do not have timeout= argument. + return klass(server) + if self.security == 'none': + self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) + elif self.security == 'ssl': + if self.smtpcacerts: + raise smtplib.SMTPException( + "Checking certificate is not supported for ssl, prefer starttls" + ) + self.smtp = call(smtplib.SMTP_SSL, self.smtpserver, timeout=self.smtpservertimeout) + elif self.security == 'tls': + if 'ssl' not in sys.modules: + self.environment.get_logger().error( + '*** Your Python version does not have the ssl library installed\n' + '*** smtpEncryption=tls is not available.\n' + '*** Either upgrade Python to 2.6 or later\n' + ' or use git_multimail.py version 1.2.\n') + if ':' not in self.smtpserver: + self.smtpserver += ':587' # default port for TLS + self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout) + # start: ehlo + starttls + # equivalent to + # self.smtp.ehlo() + # self.smtp.starttls() + # with access to the ssl layer + self.smtp.ehlo() + if not self.smtp.has_extn("starttls"): + raise smtplib.SMTPException("STARTTLS extension not supported by server") + resp, reply = self.smtp.docmd("STARTTLS") + if resp != 220: + raise smtplib.SMTPException("Wrong answer to the STARTTLS command") + if self.smtpcacerts: + self.smtp.sock = ssl.wrap_socket( + self.smtp.sock, + ca_certs=self.smtpcacerts, + cert_reqs=ssl.CERT_REQUIRED + ) + else: + self.smtp.sock = ssl.wrap_socket( + self.smtp.sock, + cert_reqs=ssl.CERT_NONE + ) + self.environment.get_logger().error( + '*** Warning, the server certificate is not verified (smtp) ***\n' + '*** set the option smtpCACerts ***\n' + ) + if not hasattr(self.smtp.sock, "read"): + # using httplib.FakeSocket with Python 2.5.x or earlier + self.smtp.sock.read = self.smtp.sock.recv + self.smtp.file = self.smtp.sock.makefile('rb') + self.smtp.helo_resp = None + self.smtp.ehlo_resp = None + self.smtp.esmtp_features = {} + self.smtp.does_esmtp = 0 + # end: ehlo + starttls + self.smtp.ehlo() + else: + sys.stdout.write('*** Error: Control reached an invalid option. ***') + sys.exit(1) + if self.smtpserverdebuglevel > 0: + sys.stdout.write( + "*** Setting debug on for SMTP server connection (%s) ***\n" + % self.smtpserverdebuglevel) + self.smtp.set_debuglevel(self.smtpserverdebuglevel) + except Exception: + self.environment.get_logger().error( + '*** Error establishing SMTP connection to %s ***\n' + '*** %s\n' + % (self.smtpserver, sys.exc_info()[1])) + sys.exit(1) + + def close(self): + if hasattr(self, 'smtp'): + self.smtp.quit() + del self.smtp + + def __del__(self): + self.close() + + def send(self, lines, to_addrs): + try: + if self.username or self.password: + if not self.loggedin: + self.smtp.login(self.username, self.password) + self.loggedin = True + msg = ''.join(lines) + # turn comma-separated list into Python list if needed. + if is_string(to_addrs): + to_addrs = [email for (name, email) in getaddresses([to_addrs])] + self.smtp.sendmail(self.envelopesender, to_addrs, msg.encode('utf8')) + except socket.timeout: + self.environment.get_logger().error( + '*** Error sending email ***\n' + '*** SMTP server timed out (timeout is %s)\n' + % self.smtpservertimeout) + except smtplib.SMTPResponseException: + err = sys.exc_info()[1] + self.environment.get_logger().error( + '*** Error sending email ***\n' + '*** Error %d: %s\n' + % (err.smtp_code, bytes_to_str(err.smtp_error))) + try: + smtp = self.smtp + # delete the field before quit() so that in case of + # error, self.smtp is deleted anyway. + del self.smtp + smtp.quit() + except: + self.environment.get_logger().error( + '*** Error closing the SMTP connection ***\n' + '*** Exiting anyway ... ***\n' + '*** %s\n' % sys.exc_info()[1]) + sys.exit(1) + + +class OutputMailer(Mailer): + """Write emails to an output stream, bracketed by lines of '=' characters. + + This is intended for debugging purposes.""" + + SEPARATOR = '=' * 75 + '\n' + + def __init__(self, f, environment=None): + super(OutputMailer, self).__init__(environment=environment) + self.f = f + + def send(self, lines, to_addrs): + write_str(self.f, self.SEPARATOR) + for line in lines: + write_str(self.f, line) + write_str(self.f, self.SEPARATOR) + + +def get_git_dir(): + """Determine GIT_DIR. + + Determine GIT_DIR either from the GIT_DIR environment variable or + from the working directory, using Git's usual rules.""" + + try: + return read_git_output(['rev-parse', '--git-dir']) + except CommandError: + sys.stderr.write('fatal: git_multimail: not in a git directory\n') + sys.exit(1) + + +class Environment(object): + """Describes the environment in which the push is occurring. + + An Environment object encapsulates information about the local + environment. For example, it knows how to determine: + + * the name of the repository to which the push occurred + + * what user did the push + + * what users want to be informed about various types of changes. + + An Environment object is expected to have the following methods: + + get_repo_shortname() + + Return a short name for the repository, for display + purposes. + + get_repo_path() + + Return the absolute path to the Git repository. + + get_emailprefix() + + Return a string that will be prefixed to every email's + subject. + + get_pusher() + + Return the username of the person who pushed the changes. + This value is used in the email body to indicate who + pushed the change. + + get_pusher_email() (may return None) + + Return the email address of the person who pushed the + changes. The value should be a single RFC 2822 email + address as a string; e.g., "Joe User <user@example.com>" + if available, otherwise "user@example.com". If set, the + value is used as the Reply-To address for refchange + emails. If it is impossible to determine the pusher's + email, this attribute should be set to None (in which case + no Reply-To header will be output). + + get_sender() + + Return the address to be used as the 'From' email address + in the email envelope. + + get_fromaddr(change=None) + + Return the 'From' email address used in the email 'From:' + headers. If the change is known when this function is + called, it is passed in as the 'change' parameter. (May + be a full RFC 2822 email address like 'Joe User + <user@example.com>'.) + + get_administrator() + + Return the name and/or email of the repository + administrator. This value is used in the footer as the + person to whom requests to be removed from the + notification list should be sent. Ideally, it should + include a valid email address. + + get_reply_to_refchange() + get_reply_to_commit() + + Return the address to use in the email "Reply-To" header, + as a string. These can be an RFC 2822 email address, or + None to omit the "Reply-To" header. + get_reply_to_refchange() is used for refchange emails; + get_reply_to_commit() is used for individual commit + emails. + + get_ref_filter_regex() + + Return a tuple -- a compiled regex, and a boolean indicating + whether the regex picks refs to include (if False, the regex + matches on refs to exclude). + + get_default_ref_ignore_regex() + + Return a regex that should be ignored for both what emails + to send and when computing what commits are considered new + to the repository. Default is "^refs/notes/". + + get_max_subject_length() + + Return an int giving the maximal length for the subject + (git log --oneline). + + They should also define the following attributes: + + announce_show_shortlog (bool) + + True iff announce emails should include a shortlog. + + commit_email_format (string) + + If "html", generate commit emails in HTML instead of plain text + used by default. + + html_in_intro (bool) + html_in_footer (bool) + + When generating HTML emails, the introduction (respectively, + the footer) will be HTML-escaped iff html_in_intro (respectively, + the footer) is true. When false, only the values used to expand + the template are escaped. + + refchange_showgraph (bool) + + True iff refchanges emails should include a detailed graph. + + refchange_showlog (bool) + + True iff refchanges emails should include a detailed log. + + diffopts (list of strings) + + The options that should be passed to 'git diff' for the + summary email. The value should be a list of strings + representing words to be passed to the command. + + graphopts (list of strings) + + Analogous to diffopts, but contains options passed to + 'git log --graph' when generating the detailed graph for + a set of commits (see refchange_showgraph) + + logopts (list of strings) + + Analogous to diffopts, but contains options passed to + 'git log' when generating the detailed log for a set of + commits (see refchange_showlog) + + commitlogopts (list of strings) + + The options that should be passed to 'git log' for each + commit mail. The value should be a list of strings + representing words to be passed to the command. + + date_substitute (string) + + String to be used in substitution for 'Date:' at start of + line in the output of 'git log'. + + quiet (bool) + On success do not write to stderr + + stdout (bool) + Write email to stdout rather than emailing. Useful for debugging + + combine_when_single_commit (bool) + + True if a combined email should be produced when a single + new commit is pushed to a branch, False otherwise. + + from_refchange, from_commit (strings) + + Addresses to use for the From: field for refchange emails + and commit emails respectively. Set from + multimailhook.fromRefchange and multimailhook.fromCommit + by ConfigEnvironmentMixin. + + log_file, error_log_file, debug_log_file (string) + + Name of a file to which logs should be sent. + + verbose (int) + + How verbose the system should be. + - 0 (default): show info, errors, ... + - 1 : show basic debug info + """ + + REPO_NAME_RE = re.compile(r'^(?P<name>.+?)(?:\.git)$') + + def __init__(self, osenv=None): + self.osenv = osenv or os.environ + self.announce_show_shortlog = False + self.commit_email_format = "text" + self.html_in_intro = False + self.html_in_footer = False + self.commitBrowseURL = None + self.maxcommitemails = 500 + self.excludemergerevisions = False + self.diffopts = ['--stat', '--summary', '--find-copies-harder'] + self.graphopts = ['--oneline', '--decorate'] + self.logopts = [] + self.refchange_showgraph = False + self.refchange_showlog = False + self.commitlogopts = ['-C', '--stat', '-p', '--cc'] + self.date_substitute = 'AuthorDate: ' + self.quiet = False + self.stdout = False + self.combine_when_single_commit = True + self.logger = None + + self.COMPUTED_KEYS = [ + 'administrator', + 'charset', + 'emailprefix', + 'pusher', + 'pusher_email', + 'repo_path', + 'repo_shortname', + 'sender', + ] + + self._values = None + + def get_logger(self): + """Get (possibly creates) the logger associated to this environment.""" + if self.logger is None: + self.logger = Logger(self) + return self.logger + + def get_repo_shortname(self): + """Use the last part of the repo path, with ".git" stripped off if present.""" + + basename = os.path.basename(os.path.abspath(self.get_repo_path())) + m = self.REPO_NAME_RE.match(basename) + if m: + return m.group('name') + else: + return basename + + def get_pusher(self): + raise NotImplementedError() + + def get_pusher_email(self): + return None + + def get_fromaddr(self, change=None): + config = Config('user') + fromname = config.get('name', default='') + fromemail = config.get('email', default='') + if fromemail: + return formataddr([fromname, fromemail]) + return self.get_sender() + + def get_administrator(self): + return 'the administrator of this repository' + + def get_emailprefix(self): + return '' + + def get_repo_path(self): + if read_git_output(['rev-parse', '--is-bare-repository']) == 'true': + path = get_git_dir() + else: + path = read_git_output(['rev-parse', '--show-toplevel']) + return os.path.abspath(path) + + def get_charset(self): + return CHARSET + + def get_values(self): + """Return a dictionary {keyword: expansion} for this Environment. + + This method is called by Change._compute_values(). The keys + in the returned dictionary are available to be used in any of + the templates. The dictionary is created by calling + self.get_NAME() for each of the attributes named in + COMPUTED_KEYS and recording those that do not return None. + The return value is always a new dictionary.""" + + if self._values is None: + values = {'': ''} # %()s expands to the empty string. + + for key in self.COMPUTED_KEYS: + value = getattr(self, 'get_%s' % (key,))() + if value is not None: + values[key] = value + + self._values = values + + return self._values.copy() + + def get_refchange_recipients(self, refchange): + """Return the recipients for notifications about refchange. + + Return the list of email addresses to which notifications + about the specified ReferenceChange should be sent.""" + + raise NotImplementedError() + + def get_announce_recipients(self, annotated_tag_change): + """Return the recipients for notifications about annotated_tag_change. + + Return the list of email addresses to which notifications + about the specified AnnotatedTagChange should be sent.""" + + raise NotImplementedError() + + def get_reply_to_refchange(self, refchange): + return self.get_pusher_email() + + def get_revision_recipients(self, revision): + """Return the recipients for messages about revision. + + Return the list of email addresses to which notifications + about the specified Revision should be sent. This method + could be overridden, for example, to take into account the + contents of the revision when deciding whom to notify about + it. For example, there could be a scheme for users to express + interest in particular files or subdirectories, and only + receive notification emails for revisions that affecting those + files.""" + + raise NotImplementedError() + + def get_reply_to_commit(self, revision): + return revision.author + + def get_default_ref_ignore_regex(self): + # The commit messages of git notes are essentially meaningless + # and "filenames" in git notes commits are an implementation + # detail that might surprise users at first. As such, we + # would need a completely different method for handling emails + # of git notes in order for them to be of benefit for users, + # which we simply do not have right now. + return "^refs/notes/" + + def get_max_subject_length(self): + """Return the maximal subject line (git log --oneline) length. + Longer subject lines will be truncated.""" + raise NotImplementedError() + + def filter_body(self, lines): + """Filter the lines intended for an email body. + + lines is an iterable over the lines that would go into the + email body. Filter it (e.g., limit the number of lines, the + line length, character set, etc.), returning another iterable. + See FilterLinesEnvironmentMixin and MaxlinesEnvironmentMixin + for classes implementing this functionality.""" + + return lines + + def log_msg(self, msg): + """Write the string msg on a log file or on stderr. + + Sends the text to stderr by default, override to change the behavior.""" + self.get_logger().info(msg) + + def log_warning(self, msg): + """Write the string msg on a log file or on stderr. + + Sends the text to stderr by default, override to change the behavior.""" + self.get_logger().warning(msg) + + def log_error(self, msg): + """Write the string msg on a log file or on stderr. + + Sends the text to stderr by default, override to change the behavior.""" + self.get_logger().error(msg) + + def check(self): + pass + + +class ConfigEnvironmentMixin(Environment): + """A mixin that sets self.config to its constructor's config argument. + + This class's constructor consumes the "config" argument. + + Mixins that need to inspect the config should inherit from this + class (1) to make sure that "config" is still in the constructor + arguments with its own constructor runs and/or (2) to be sure that + self.config is set after construction.""" + + def __init__(self, config, **kw): + super(ConfigEnvironmentMixin, self).__init__(**kw) + self.config = config + + +class ConfigOptionsEnvironmentMixin(ConfigEnvironmentMixin): + """An Environment that reads most of its information from "git config".""" + + @staticmethod + def forbid_field_values(name, value, forbidden): + for forbidden_val in forbidden: + if value is not None and value.lower() == forbidden_val: + raise ConfigurationException( + '"%s" is not an allowed setting for %s' % (value, name) + ) + + def __init__(self, config, **kw): + super(ConfigOptionsEnvironmentMixin, self).__init__( + config=config, **kw + ) + + for var, cfg in ( + ('announce_show_shortlog', 'announceshortlog'), + ('refchange_showgraph', 'refchangeShowGraph'), + ('refchange_showlog', 'refchangeshowlog'), + ('quiet', 'quiet'), + ('stdout', 'stdout'), + ): + val = config.get_bool(cfg) + if val is not None: + setattr(self, var, val) + + commit_email_format = config.get('commitEmailFormat') + if commit_email_format is not None: + if commit_email_format != "html" and commit_email_format != "text": + self.log_warning( + '*** Unknown value for multimailhook.commitEmailFormat: %s\n' % + commit_email_format + + '*** Expected either "text" or "html". Ignoring.\n' + ) + else: + self.commit_email_format = commit_email_format + + html_in_intro = config.get_bool('htmlInIntro') + if html_in_intro is not None: + self.html_in_intro = html_in_intro + + html_in_footer = config.get_bool('htmlInFooter') + if html_in_footer is not None: + self.html_in_footer = html_in_footer + + self.commitBrowseURL = config.get('commitBrowseURL') + + self.excludemergerevisions = config.get('excludeMergeRevisions') + + maxcommitemails = config.get('maxcommitemails') + if maxcommitemails is not None: + try: + self.maxcommitemails = int(maxcommitemails) + except ValueError: + self.log_warning( + '*** Malformed value for multimailhook.maxCommitEmails: %s\n' + % maxcommitemails + + '*** Expected a number. Ignoring.\n' + ) + + diffopts = config.get('diffopts') + if diffopts is not None: + self.diffopts = shlex.split(diffopts) + + graphopts = config.get('graphOpts') + if graphopts is not None: + self.graphopts = shlex.split(graphopts) + + logopts = config.get('logopts') + if logopts is not None: + self.logopts = shlex.split(logopts) + + commitlogopts = config.get('commitlogopts') + if commitlogopts is not None: + self.commitlogopts = shlex.split(commitlogopts) + + date_substitute = config.get('dateSubstitute') + if date_substitute == 'none': + self.date_substitute = None + elif date_substitute is not None: + self.date_substitute = date_substitute + + reply_to = config.get('replyTo') + self.__reply_to_refchange = config.get('replyToRefchange', default=reply_to) + self.forbid_field_values('replyToRefchange', + self.__reply_to_refchange, + ['author']) + self.__reply_to_commit = config.get('replyToCommit', default=reply_to) + + self.from_refchange = config.get('fromRefchange') + self.forbid_field_values('fromRefchange', + self.from_refchange, + ['author', 'none']) + self.from_commit = config.get('fromCommit') + self.forbid_field_values('fromCommit', + self.from_commit, + ['none']) + + combine = config.get_bool('combineWhenSingleCommit') + if combine is not None: + self.combine_when_single_commit = combine + + self.log_file = config.get('logFile', default=None) + self.error_log_file = config.get('errorLogFile', default=None) + self.debug_log_file = config.get('debugLogFile', default=None) + if config.get_bool('Verbose', default=False): + self.verbose = 1 + else: + self.verbose = 0 + + def get_administrator(self): + return ( + self.config.get('administrator') or + self.get_sender() or + super(ConfigOptionsEnvironmentMixin, self).get_administrator() + ) + + def get_repo_shortname(self): + return ( + self.config.get('reponame') or + super(ConfigOptionsEnvironmentMixin, self).get_repo_shortname() + ) + + def get_emailprefix(self): + emailprefix = self.config.get('emailprefix') + if emailprefix is not None: + emailprefix = emailprefix.strip() + if emailprefix: + emailprefix += ' ' + else: + emailprefix = '[%(repo_shortname)s] ' + short_name = self.get_repo_shortname() + try: + return emailprefix % {'repo_shortname': short_name} + except: + self.get_logger().error( + '*** Invalid multimailhook.emailPrefix: %s\n' % emailprefix + + '*** %s\n' % sys.exc_info()[1] + + "*** Only the '%(repo_shortname)s' placeholder is allowed\n" + ) + raise ConfigurationException( + '"%s" is not an allowed setting for emailPrefix' % emailprefix + ) + + def get_sender(self): + return self.config.get('envelopesender') + + def process_addr(self, addr, change): + if addr.lower() == 'author': + if hasattr(change, 'author'): + return change.author + else: + return None + elif addr.lower() == 'pusher': + return self.get_pusher_email() + elif addr.lower() == 'none': + return None + else: + return addr + + def get_fromaddr(self, change=None): + fromaddr = self.config.get('from') + if change: + specific_fromaddr = change.get_specific_fromaddr() + if specific_fromaddr: + fromaddr = specific_fromaddr + if fromaddr: + fromaddr = self.process_addr(fromaddr, change) + if fromaddr: + return fromaddr + return super(ConfigOptionsEnvironmentMixin, self).get_fromaddr(change) + + def get_reply_to_refchange(self, refchange): + if self.__reply_to_refchange is None: + return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_refchange(refchange) + else: + return self.process_addr(self.__reply_to_refchange, refchange) + + def get_reply_to_commit(self, revision): + if self.__reply_to_commit is None: + return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_commit(revision) + else: + return self.process_addr(self.__reply_to_commit, revision) + + def get_scancommitforcc(self): + return self.config.get('scancommitforcc') + + +class FilterLinesEnvironmentMixin(Environment): + """Handle encoding and maximum line length of body lines. + + email_max_line_length (int or None) + + The maximum length of any single line in the email body. + Longer lines are truncated at that length with ' [...]' + appended. + + strict_utf8 (bool) + + If this field is set to True, then the email body text is + expected to be UTF-8. Any invalid characters are + converted to U+FFFD, the Unicode replacement character + (encoded as UTF-8, of course). + + """ + + def __init__(self, strict_utf8=True, + email_max_line_length=500, max_subject_length=500, + **kw): + super(FilterLinesEnvironmentMixin, self).__init__(**kw) + self.__strict_utf8 = strict_utf8 + self.__email_max_line_length = email_max_line_length + self.__max_subject_length = max_subject_length + + def filter_body(self, lines): + lines = super(FilterLinesEnvironmentMixin, self).filter_body(lines) + if self.__strict_utf8: + if not PYTHON3: + lines = (line.decode(ENCODING, 'replace') for line in lines) + # Limit the line length in Unicode-space to avoid + # splitting characters: + if self.__email_max_line_length > 0: + lines = limit_linelength(lines, self.__email_max_line_length) + if not PYTHON3: + lines = (line.encode(ENCODING, 'replace') for line in lines) + elif self.__email_max_line_length: + lines = limit_linelength(lines, self.__email_max_line_length) + + return lines + + def get_max_subject_length(self): + return self.__max_subject_length + + +class ConfigFilterLinesEnvironmentMixin( + ConfigEnvironmentMixin, + FilterLinesEnvironmentMixin, + ): + """Handle encoding and maximum line length based on config.""" + + def __init__(self, config, **kw): + strict_utf8 = config.get_bool('emailstrictutf8', default=None) + if strict_utf8 is not None: + kw['strict_utf8'] = strict_utf8 + + email_max_line_length = config.get('emailmaxlinelength') + if email_max_line_length is not None: + kw['email_max_line_length'] = int(email_max_line_length) + + max_subject_length = config.get('subjectMaxLength', default=email_max_line_length) + if max_subject_length is not None: + kw['max_subject_length'] = int(max_subject_length) + + super(ConfigFilterLinesEnvironmentMixin, self).__init__( + config=config, **kw + ) + + +class MaxlinesEnvironmentMixin(Environment): + """Limit the email body to a specified number of lines.""" + + def __init__(self, emailmaxlines, **kw): + super(MaxlinesEnvironmentMixin, self).__init__(**kw) + self.__emailmaxlines = emailmaxlines + + def filter_body(self, lines): + lines = super(MaxlinesEnvironmentMixin, self).filter_body(lines) + if self.__emailmaxlines > 0: + lines = limit_lines(lines, self.__emailmaxlines) + return lines + + +class ConfigMaxlinesEnvironmentMixin( + ConfigEnvironmentMixin, + MaxlinesEnvironmentMixin, + ): + """Limit the email body to the number of lines specified in config.""" + + def __init__(self, config, **kw): + emailmaxlines = int(config.get('emailmaxlines', default='0')) + super(ConfigMaxlinesEnvironmentMixin, self).__init__( + config=config, + emailmaxlines=emailmaxlines, + **kw + ) + + +class FQDNEnvironmentMixin(Environment): + """A mixin that sets the host's FQDN to its constructor argument.""" + + def __init__(self, fqdn, **kw): + super(FQDNEnvironmentMixin, self).__init__(**kw) + self.COMPUTED_KEYS += ['fqdn'] + self.__fqdn = fqdn + + def get_fqdn(self): + """Return the fully-qualified domain name for this host. + + Return None if it is unavailable or unwanted.""" + + return self.__fqdn + + +class ConfigFQDNEnvironmentMixin( + ConfigEnvironmentMixin, + FQDNEnvironmentMixin, + ): + """Read the FQDN from the config.""" + + def __init__(self, config, **kw): + fqdn = config.get('fqdn') + super(ConfigFQDNEnvironmentMixin, self).__init__( + config=config, + fqdn=fqdn, + **kw + ) + + +class ComputeFQDNEnvironmentMixin(FQDNEnvironmentMixin): + """Get the FQDN by calling socket.getfqdn().""" + + def __init__(self, **kw): + super(ComputeFQDNEnvironmentMixin, self).__init__( + fqdn=self.get_fqdn(), + **kw + ) + + def get_fqdn(self): + fqdn = socket.getfqdn() + # Sometimes, socket.getfqdn() returns localhost or + # localhost.localhost, which isn't very helpful. In this case, + # fall-back to socket.gethostname() which may return an actual + # hostname. + if fqdn == 'localhost' or fqdn == 'localhost.localdomain': + fqdn = socket.gethostname() + return fqdn + + +class PusherDomainEnvironmentMixin(ConfigEnvironmentMixin): + """Deduce pusher_email from pusher by appending an emaildomain.""" + + def __init__(self, **kw): + super(PusherDomainEnvironmentMixin, self).__init__(**kw) + self.__emaildomain = self.config.get('emaildomain') + + def get_pusher_email(self): + if self.__emaildomain: + # Derive the pusher's full email address in the default way: + return '%s@%s' % (self.get_pusher(), self.__emaildomain) + else: + return super(PusherDomainEnvironmentMixin, self).get_pusher_email() + + +class StaticRecipientsEnvironmentMixin(Environment): + """Set recipients statically based on constructor parameters.""" + + def __init__( + self, + refchange_recipients, announce_recipients, revision_recipients, scancommitforcc, + **kw + ): + super(StaticRecipientsEnvironmentMixin, self).__init__(**kw) + + # The recipients for various types of notification emails, as + # RFC 2822 email addresses separated by commas (or the empty + # string if no recipients are configured). Although there is + # a mechanism to choose the recipient lists based on on the + # actual *contents* of the change being reported, we only + # choose based on the *type* of the change. Therefore we can + # compute them once and for all: + self.__refchange_recipients = refchange_recipients + self.__announce_recipients = announce_recipients + self.__revision_recipients = revision_recipients + + def check(self): + if not (self.get_refchange_recipients(None) or + self.get_announce_recipients(None) or + self.get_revision_recipients(None) or + self.get_scancommitforcc()): + raise ConfigurationException('No email recipients configured!') + super(StaticRecipientsEnvironmentMixin, self).check() + + def get_refchange_recipients(self, refchange): + if self.__refchange_recipients is None: + return super(StaticRecipientsEnvironmentMixin, + self).get_refchange_recipients(refchange) + return self.__refchange_recipients + + def get_announce_recipients(self, annotated_tag_change): + if self.__announce_recipients is None: + return super(StaticRecipientsEnvironmentMixin, + self).get_refchange_recipients(annotated_tag_change) + return self.__announce_recipients + + def get_revision_recipients(self, revision): + if self.__revision_recipients is None: + return super(StaticRecipientsEnvironmentMixin, + self).get_refchange_recipients(revision) + return self.__revision_recipients + + +class CLIRecipientsEnvironmentMixin(Environment): + """Mixin storing recipients information coming from the + command-line.""" + + def __init__(self, cli_recipients=None, **kw): + super(CLIRecipientsEnvironmentMixin, self).__init__(**kw) + self.__cli_recipients = cli_recipients + + def get_refchange_recipients(self, refchange): + if self.__cli_recipients is None: + return super(CLIRecipientsEnvironmentMixin, + self).get_refchange_recipients(refchange) + return self.__cli_recipients + + def get_announce_recipients(self, annotated_tag_change): + if self.__cli_recipients is None: + return super(CLIRecipientsEnvironmentMixin, + self).get_announce_recipients(annotated_tag_change) + return self.__cli_recipients + + def get_revision_recipients(self, revision): + if self.__cli_recipients is None: + return super(CLIRecipientsEnvironmentMixin, + self).get_revision_recipients(revision) + return self.__cli_recipients + + +class ConfigRecipientsEnvironmentMixin( + ConfigEnvironmentMixin, + StaticRecipientsEnvironmentMixin + ): + """Determine recipients statically based on config.""" + + def __init__(self, config, **kw): + super(ConfigRecipientsEnvironmentMixin, self).__init__( + config=config, + refchange_recipients=self._get_recipients( + config, 'refchangelist', 'mailinglist', + ), + announce_recipients=self._get_recipients( + config, 'announcelist', 'refchangelist', 'mailinglist', + ), + revision_recipients=self._get_recipients( + config, 'commitlist', 'mailinglist', + ), + scancommitforcc=config.get('scancommitforcc'), + **kw + ) + + def _get_recipients(self, config, *names): + """Return the recipients for a particular type of message. + + Return the list of email addresses to which a particular type + of notification email should be sent, by looking at the config + value for "multimailhook.$name" for each of names. Use the + value from the first name that is configured. The return + value is a (possibly empty) string containing RFC 2822 email + addresses separated by commas. If no configuration could be + found, raise a ConfigurationException.""" + + for name in names: + lines = config.get_all(name) + if lines is not None: + lines = [line.strip() for line in lines] + # Single "none" is a special value equivalence to empty string. + if lines == ['none']: + lines = [''] + return ', '.join(lines) + else: + return '' + + +class StaticRefFilterEnvironmentMixin(Environment): + """Set branch filter statically based on constructor parameters.""" + + def __init__(self, ref_filter_incl_regex, ref_filter_excl_regex, + ref_filter_do_send_regex, ref_filter_dont_send_regex, + **kw): + super(StaticRefFilterEnvironmentMixin, self).__init__(**kw) + + if ref_filter_incl_regex and ref_filter_excl_regex: + raise ConfigurationException( + "Cannot specify both a ref inclusion and exclusion regex.") + self.__is_inclusion_filter = bool(ref_filter_incl_regex) + default_exclude = self.get_default_ref_ignore_regex() + if ref_filter_incl_regex: + ref_filter_regex = ref_filter_incl_regex + elif ref_filter_excl_regex: + ref_filter_regex = ref_filter_excl_regex + '|' + default_exclude + else: + ref_filter_regex = default_exclude + try: + self.__compiled_regex = re.compile(ref_filter_regex) + except Exception: + raise ConfigurationException( + 'Invalid Ref Filter Regex "%s": %s' % (ref_filter_regex, sys.exc_info()[1])) + + if ref_filter_do_send_regex and ref_filter_dont_send_regex: + raise ConfigurationException( + "Cannot specify both a ref doSend and dontSend regex.") + self.__is_do_send_filter = bool(ref_filter_do_send_regex) + if ref_filter_do_send_regex: + ref_filter_send_regex = ref_filter_do_send_regex + elif ref_filter_dont_send_regex: + ref_filter_send_regex = ref_filter_dont_send_regex + else: + ref_filter_send_regex = '.*' + self.__is_do_send_filter = True + try: + self.__send_compiled_regex = re.compile(ref_filter_send_regex) + except Exception: + raise ConfigurationException( + 'Invalid Ref Filter Regex "%s": %s' % + (ref_filter_send_regex, sys.exc_info()[1])) + + def get_ref_filter_regex(self, send_filter=False): + if send_filter: + return self.__send_compiled_regex, self.__is_do_send_filter + else: + return self.__compiled_regex, self.__is_inclusion_filter + + +class ConfigRefFilterEnvironmentMixin( + ConfigEnvironmentMixin, + StaticRefFilterEnvironmentMixin + ): + """Determine branch filtering statically based on config.""" + + def _get_regex(self, config, key): + """Get a list of whitespace-separated regex. The refFilter* config + variables are multivalued (hence the use of get_all), and we + allow each entry to be a whitespace-separated list (hence the + split on each line). The whole thing is glued into a single regex.""" + values = config.get_all(key) + if values is None: + return values + items = [] + for line in values: + for i in line.split(): + items.append(i) + if items == []: + return None + return '|'.join(items) + + def __init__(self, config, **kw): + super(ConfigRefFilterEnvironmentMixin, self).__init__( + config=config, + ref_filter_incl_regex=self._get_regex(config, 'refFilterInclusionRegex'), + ref_filter_excl_regex=self._get_regex(config, 'refFilterExclusionRegex'), + ref_filter_do_send_regex=self._get_regex(config, 'refFilterDoSendRegex'), + ref_filter_dont_send_regex=self._get_regex(config, 'refFilterDontSendRegex'), + **kw + ) + + +class ProjectdescEnvironmentMixin(Environment): + """Make a "projectdesc" value available for templates. + + By default, it is set to the first line of $GIT_DIR/description + (if that file is present and appears to be set meaningfully).""" + + def __init__(self, **kw): + super(ProjectdescEnvironmentMixin, self).__init__(**kw) + self.COMPUTED_KEYS += ['projectdesc'] + + def get_projectdesc(self): + """Return a one-line description of the project.""" + + git_dir = get_git_dir() + try: + projectdesc = open(os.path.join(git_dir, 'description')).readline().strip() + if projectdesc and not projectdesc.startswith('Unnamed repository'): + return projectdesc + except IOError: + pass + + return 'UNNAMED PROJECT' + + +class GenericEnvironmentMixin(Environment): + def get_pusher(self): + return self.osenv.get('USER', self.osenv.get('USERNAME', 'unknown user')) + + +class GitoliteEnvironmentHighPrecMixin(Environment): + def get_pusher(self): + return self.osenv.get('GL_USER', 'unknown user') + + +class GitoliteEnvironmentLowPrecMixin( + ConfigEnvironmentMixin, + Environment): + + def get_repo_shortname(self): + # The gitolite environment variable $GL_REPO is a pretty good + # repo_shortname (though it's probably not as good as a value + # the user might have explicitly put in his config). + return ( + self.osenv.get('GL_REPO', None) or + super(GitoliteEnvironmentLowPrecMixin, self).get_repo_shortname() + ) + + @staticmethod + def _compile_regex(re_template): + return ( + re.compile(re_template % x) + for x in ( + r'BEGIN\s+USER\s+EMAILS', + r'([^\s]+)\s+(.*)', + r'END\s+USER\s+EMAILS', + )) + + def get_fromaddr(self, change=None): + GL_USER = self.osenv.get('GL_USER') + if GL_USER is not None: + # Find the path to gitolite.conf. Note that gitolite v3 + # did away with the GL_ADMINDIR and GL_CONF environment + # variables (they are now hard-coded). + GL_ADMINDIR = self.osenv.get( + 'GL_ADMINDIR', + os.path.expanduser(os.path.join('~', '.gitolite'))) + GL_CONF = self.osenv.get( + 'GL_CONF', + os.path.join(GL_ADMINDIR, 'conf', 'gitolite.conf')) + + mailaddress_map = self.config.get('MailaddressMap') + # If relative, consider relative to GL_CONF: + if mailaddress_map: + mailaddress_map = os.path.join(os.path.dirname(GL_CONF), + mailaddress_map) + if os.path.isfile(mailaddress_map): + f = open(mailaddress_map, 'rU') + try: + # Leading '#' is optional + re_begin, re_user, re_end = self._compile_regex( + r'^(?:\s*#)?\s*%s\s*$') + for l in f: + l = l.rstrip('\n') + if re_begin.match(l) or re_end.match(l): + continue # Ignore these lines + m = re_user.match(l) + if m: + if m.group(1) == GL_USER: + return m.group(2) + else: + continue # Not this user, but not an error + raise ConfigurationException( + "Syntax error in mail address map.\n" + "Check file {}.\n" + "Line: {}".format(mailaddress_map, l)) + + finally: + f.close() + + if os.path.isfile(GL_CONF): + f = open(GL_CONF, 'rU') + try: + in_user_emails_section = False + re_begin, re_user, re_end = self._compile_regex( + r'^\s*#\s*%s\s*$') + for l in f: + l = l.rstrip('\n') + if not in_user_emails_section: + if re_begin.match(l): + in_user_emails_section = True + continue + if re_end.match(l): + break + m = re_user.match(l) + if m and m.group(1) == GL_USER: + return m.group(2) + finally: + f.close() + return super(GitoliteEnvironmentLowPrecMixin, self).get_fromaddr(change) + + +class IncrementalDateTime(object): + """Simple wrapper to give incremental date/times. + + Each call will result in a date/time a second later than the + previous call. This can be used to falsify email headers, to + increase the likelihood that email clients sort the emails + correctly.""" + + def __init__(self): + self.time = time.time() + self.next = self.__next__ # Python 2 backward compatibility + + def __next__(self): + formatted = formatdate(self.time, True) + self.time += 1 + return formatted + + +class StashEnvironmentHighPrecMixin(Environment): + def __init__(self, user=None, repo=None, **kw): + super(StashEnvironmentHighPrecMixin, + self).__init__(user=user, repo=repo, **kw) + self.__user = user + self.__repo = repo + + def get_pusher(self): + return re.match(r'(.*?)\s*<', self.__user).group(1) + + def get_pusher_email(self): + return self.__user + + +class StashEnvironmentLowPrecMixin(Environment): + def __init__(self, user=None, repo=None, **kw): + super(StashEnvironmentLowPrecMixin, self).__init__(**kw) + self.__repo = repo + self.__user = user + + def get_repo_shortname(self): + return self.__repo + + def get_fromaddr(self, change=None): + return self.__user + + +class GerritEnvironmentHighPrecMixin(Environment): + def __init__(self, project=None, submitter=None, update_method=None, **kw): + super(GerritEnvironmentHighPrecMixin, + self).__init__(submitter=submitter, project=project, **kw) + self.__project = project + self.__submitter = submitter + self.__update_method = update_method + "Make an 'update_method' value available for templates." + self.COMPUTED_KEYS += ['update_method'] + + def get_pusher(self): + if self.__submitter: + if self.__submitter.find('<') != -1: + # Submitter has a configured email, we transformed + # __submitter into an RFC 2822 string already. + return re.match(r'(.*?)\s*<', self.__submitter).group(1) + else: + # Submitter has no configured email, it's just his name. + return self.__submitter + else: + # If we arrive here, this means someone pushed "Submit" from + # the gerrit web UI for the CR (or used one of the programmatic + # APIs to do the same, such as gerrit review) and the + # merge/push was done by the Gerrit user. It was technically + # triggered by someone else, but sadly we have no way of + # determining who that someone else is at this point. + return 'Gerrit' # 'unknown user'? + + def get_pusher_email(self): + if self.__submitter: + return self.__submitter + else: + return super(GerritEnvironmentHighPrecMixin, self).get_pusher_email() + + def get_default_ref_ignore_regex(self): + default = super(GerritEnvironmentHighPrecMixin, self).get_default_ref_ignore_regex() + return default + '|^refs/changes/|^refs/cache-automerge/|^refs/meta/' + + def get_revision_recipients(self, revision): + # Merge commits created by Gerrit when users hit "Submit this patchset" + # in the Web UI (or do equivalently with REST APIs or the gerrit review + # command) are not something users want to see an individual email for. + # Filter them out. + committer = read_git_output(['log', '--no-walk', '--format=%cN', + revision.rev.sha1]) + if committer == 'Gerrit Code Review': + return [] + else: + return super(GerritEnvironmentHighPrecMixin, self).get_revision_recipients(revision) + + def get_update_method(self): + return self.__update_method + + +class GerritEnvironmentLowPrecMixin(Environment): + def __init__(self, project=None, submitter=None, **kw): + super(GerritEnvironmentLowPrecMixin, self).__init__(**kw) + self.__project = project + self.__submitter = submitter + + def get_repo_shortname(self): + return self.__project + + def get_fromaddr(self, change=None): + if self.__submitter and self.__submitter.find('<') != -1: + return self.__submitter + else: + return super(GerritEnvironmentLowPrecMixin, self).get_fromaddr(change) + + +class GiteaEnvironmentHighPrecMixin(Environment): + def get_pusher(self): + return self.osenv.get('GITEA_PUSHER_NAME', 'unknown user') + + def get_pusher_email(self): + return self.osenv.get('GITEA_PUSHER_EMAIL') + + +class GiteaEnvironmentLowPrecMixin(Environment): + def get_repo_shortname(self): + return self.osenv.get('GITEA_REPO_NAME', 'unknown repository') + + def get_fromaddr(self, change=None): + # GITEA_PUSHER_NAME doesn't include the full name, just the user name + # at Gitea level, so it doesn't seem useful to use it and there + # doesn't seem to be any simple way to get it from Gitea neither. + return self.osenv.get('GITEA_PUSHER_EMAIL') + + +class Push(object): + """Represent an entire push (i.e., a group of ReferenceChanges). + + It is easy to figure out what commits were added to a *branch* by + a Reference change: + + git rev-list change.old..change.new + + or removed from a *branch*: + + git rev-list change.new..change.old + + But it is not quite so trivial to determine which entirely new + commits were added to the *repository* by a push and which old + commits were discarded by a push. A big part of the job of this + class is to figure out these things, and to make sure that new + commits are only detailed once even if they were added to multiple + references. + + The first step is to determine the "other" references--those + unaffected by the current push. They are computed by listing all + references then removing any affected by this push. The results + are stored in Push._other_ref_sha1s. + + The commits contained in the repository before this push were + + git rev-list other1 other2 other3 ... change1.old change2.old ... + + Where "changeN.old" is the old value of one of the references + affected by this push. + + The commits contained in the repository after this push are + + git rev-list other1 other2 other3 ... change1.new change2.new ... + + The commits added by this push are the difference between these + two sets, which can be written + + git rev-list \ + ^other1 ^other2 ... \ + ^change1.old ^change2.old ... \ + change1.new change2.new ... + + The commits removed by this push can be computed by + + git rev-list \ + ^other1 ^other2 ... \ + ^change1.new ^change2.new ... \ + change1.old change2.old ... + + The last point is that it is possible that other pushes are + occurring simultaneously to this one, so reference values can + change at any time. It is impossible to eliminate all race + conditions, but we reduce the window of time during which problems + can occur by translating reference names to SHA1s as soon as + possible and working with SHA1s thereafter (because SHA1s are + immutable).""" + + # A map {(changeclass, changetype): integer} specifying the order + # that reference changes will be processed if multiple reference + # changes are included in a single push. The order is significant + # mostly because new commit notifications are threaded together + # with the first reference change that includes the commit. The + # following order thus causes commits to be grouped with branch + # changes (as opposed to tag changes) if possible. + SORT_ORDER = dict( + (value, i) for (i, value) in enumerate([ + (BranchChange, 'update'), + (BranchChange, 'create'), + (AnnotatedTagChange, 'update'), + (AnnotatedTagChange, 'create'), + (NonAnnotatedTagChange, 'update'), + (NonAnnotatedTagChange, 'create'), + (BranchChange, 'delete'), + (AnnotatedTagChange, 'delete'), + (NonAnnotatedTagChange, 'delete'), + (OtherReferenceChange, 'update'), + (OtherReferenceChange, 'create'), + (OtherReferenceChange, 'delete'), + ]) + ) + + def __init__(self, environment, changes, ignore_other_refs=False): + self.changes = sorted(changes, key=self._sort_key) + self.__other_ref_sha1s = None + self.__cached_commits_spec = {} + self.environment = environment + + if ignore_other_refs: + self.__other_ref_sha1s = set() + + @classmethod + def _sort_key(klass, change): + return (klass.SORT_ORDER[change.__class__, change.change_type], change.refname,) + + @property + def _other_ref_sha1s(self): + """The GitObjects referred to by references unaffected by this push. + """ + if self.__other_ref_sha1s is None: + # The refnames being changed by this push: + updated_refs = set( + change.refname + for change in self.changes + ) + + # The SHA-1s of commits referred to by all references in this + # repository *except* updated_refs: + sha1s = set() + fmt = ( + '%(objectname) %(objecttype) %(refname)\n' + '%(*objectname) %(*objecttype) %(refname)' + ) + ref_filter_regex, is_inclusion_filter = \ + self.environment.get_ref_filter_regex() + for line in read_git_lines( + ['for-each-ref', '--format=%s' % (fmt,)]): + (sha1, type, name) = line.split(' ', 2) + if (sha1 and type == 'commit' and + name not in updated_refs and + include_ref(name, ref_filter_regex, is_inclusion_filter)): + sha1s.add(sha1) + + self.__other_ref_sha1s = sha1s + + return self.__other_ref_sha1s + + def _get_commits_spec_incl(self, new_or_old, reference_change=None): + """Get new or old SHA-1 from one or each of the changed refs. + + Return a list of SHA-1 commit identifier strings suitable as + arguments to 'git rev-list' (or 'git log' or ...). The + returned identifiers are either the old or new values from one + or all of the changed references, depending on the values of + new_or_old and reference_change. + + new_or_old is either the string 'new' or the string 'old'. If + 'new', the returned SHA-1 identifiers are the new values from + each changed reference. If 'old', the SHA-1 identifiers are + the old values from each changed reference. + + If reference_change is specified and not None, only the new or + old reference from the specified reference is included in the + return value. + + This function returns None if there are no matching revisions + (e.g., because a branch was deleted and new_or_old is 'new'). + """ + + if not reference_change: + incl_spec = sorted( + getattr(change, new_or_old).sha1 + for change in self.changes + if getattr(change, new_or_old) + ) + if not incl_spec: + incl_spec = None + elif not getattr(reference_change, new_or_old).commit_sha1: + incl_spec = None + else: + incl_spec = [getattr(reference_change, new_or_old).commit_sha1] + return incl_spec + + def _get_commits_spec_excl(self, new_or_old): + """Get exclusion revisions for determining new or discarded commits. + + Return a list of strings suitable as arguments to 'git + rev-list' (or 'git log' or ...) that will exclude all + commits that, depending on the value of new_or_old, were + either previously in the repository (useful for determining + which commits are new to the repository) or currently in the + repository (useful for determining which commits were + discarded from the repository). + + new_or_old is either the string 'new' or the string 'old'. If + 'new', the commits to be excluded are those that were in the + repository before the push. If 'old', the commits to be + excluded are those that are currently in the repository. """ + + old_or_new = {'old': 'new', 'new': 'old'}[new_or_old] + excl_revs = self._other_ref_sha1s.union( + getattr(change, old_or_new).sha1 + for change in self.changes + if getattr(change, old_or_new).type in ['commit', 'tag'] + ) + return ['^' + sha1 for sha1 in sorted(excl_revs)] + + def get_commits_spec(self, new_or_old, reference_change=None): + """Get rev-list arguments for added or discarded commits. + + Return a list of strings suitable as arguments to 'git + rev-list' (or 'git log' or ...) that select those commits + that, depending on the value of new_or_old, are either new to + the repository or were discarded from the repository. + + new_or_old is either the string 'new' or the string 'old'. If + 'new', the returned list is used to select commits that are + new to the repository. If 'old', the returned value is used + to select the commits that have been discarded from the + repository. + + If reference_change is specified and not None, the new or + discarded commits are limited to those that are reachable from + the new or old value of the specified reference. + + This function returns None if there are no added (or discarded) + revisions. + """ + key = (new_or_old, reference_change) + if key not in self.__cached_commits_spec: + ret = self._get_commits_spec_incl(new_or_old, reference_change) + if ret is not None: + ret.extend(self._get_commits_spec_excl(new_or_old)) + self.__cached_commits_spec[key] = ret + return self.__cached_commits_spec[key] + + def get_new_commits(self, reference_change=None): + """Return a list of commits added by this push. + + Return a list of the object names of commits that were added + by the part of this push represented by reference_change. If + reference_change is None, then return a list of *all* commits + added by this push.""" + + spec = self.get_commits_spec('new', reference_change) + return git_rev_list(spec) + + def get_discarded_commits(self, reference_change): + """Return a list of commits discarded by this push. + + Return a list of the object names of commits that were + entirely discarded from the repository by the part of this + push represented by reference_change.""" + + spec = self.get_commits_spec('old', reference_change) + return git_rev_list(spec) + + def send_emails(self, mailer, body_filter=None): + """Use send all of the notification emails needed for this push. + + Use send all of the notification emails (including reference + change emails and commit emails) needed for this push. Send + the emails using mailer. If body_filter is not None, then use + it to filter the lines that are intended for the email + body.""" + + # The sha1s of commits that were introduced by this push. + # They will be removed from this set as they are processed, to + # guarantee that one (and only one) email is generated for + # each new commit. + unhandled_sha1s = set(self.get_new_commits()) + send_date = IncrementalDateTime() + for change in self.changes: + sha1s = [] + for sha1 in reversed(list(self.get_new_commits(change))): + if sha1 in unhandled_sha1s: + sha1s.append(sha1) + unhandled_sha1s.remove(sha1) + + # Check if we've got anyone to send to + if not change.recipients: + # mga: avoid unnecessary error messages when the summary + # email address is not configured (used for i18n mails). +# change.environment.log_warning( +# '*** no recipients configured so no email will be sent\n' +# '*** for %r update %s->%s' +# % (change.refname, change.old.sha1, change.new.sha1,) +# ) + pass + else: + if not change.environment.quiet: + change.environment.log_msg( + 'Sending notification emails to: %s' % (change.recipients,)) + extra_values = {'send_date': next(send_date)} + + rev = change.send_single_combined_email(sha1s) + if rev: + mailer.send( + change.generate_combined_email(self, rev, body_filter, extra_values), + rev.recipients, + ) + # This change is now fully handled; no need to handle + # individual revisions any further. + continue + else: + mailer.send( + change.generate_email(self, body_filter, extra_values), + change.recipients, + ) + + max_emails = change.environment.maxcommitemails + if max_emails and len(sha1s) > max_emails: + change.environment.log_warning( + '*** Too many new commits (%d), not sending commit emails.\n' % len(sha1s) + + '*** Try setting multimailhook.maxCommitEmails to a greater value\n' + + '*** Currently, multimailhook.maxCommitEmails=%d' % max_emails + ) + return + + for (num, sha1) in enumerate(sha1s): + rev = Revision(change, GitObject(sha1), num=num + 1, tot=len(sha1s)) + if len(rev.parents) > 1 and change.environment.excludemergerevisions: + # skipping a merge commit + continue + if not rev.recipients and rev.cc_recipients: + change.environment.log_msg('*** Replacing Cc: with To:') + rev.recipients = rev.cc_recipients + rev.cc_recipients = None + if rev.recipients: + extra_values = {'send_date': next(send_date)} + mailer.send( + rev.generate_email(self, body_filter, extra_values), + rev.recipients, + ) + + # Consistency check: + if unhandled_sha1s: + change.environment.log_error( + 'ERROR: No emails were sent for the following new commits:\n' + ' %s' + % ('\n '.join(sorted(unhandled_sha1s)),) + ) + + +def include_ref(refname, ref_filter_regex, is_inclusion_filter): + does_match = bool(ref_filter_regex.search(refname)) + if is_inclusion_filter: + return does_match + else: # exclusion filter -- we include the ref if the regex doesn't match + return not does_match + + +def run_as_post_receive_hook(environment, mailer): + environment.check() + send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True) + ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False) + changes = [] + while True: + line = read_line(sys.stdin) + if line == '': + break + (oldrev, newrev, refname) = line.strip().split(' ', 2) + environment.get_logger().debug( + "run_as_post_receive_hook: oldrev=%s, newrev=%s, refname=%s" % + (oldrev, newrev, refname)) + + if not include_ref(refname, ref_filter_regex, is_inclusion_filter): + continue + if not include_ref(refname, send_filter_regex, send_is_inclusion_filter): + continue + changes.append( + ReferenceChange.create(environment, oldrev, newrev, refname) + ) + if not changes: + mailer.close() + return + push = Push(environment, changes) + try: + push.send_emails(mailer, body_filter=environment.filter_body) + finally: + mailer.close() + + +def run_as_update_hook(environment, mailer, refname, oldrev, newrev, force_send=False): + environment.check() + send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True) + ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False) + if not include_ref(refname, ref_filter_regex, is_inclusion_filter): + return + if not include_ref(refname, send_filter_regex, send_is_inclusion_filter): + return + changes = [ + ReferenceChange.create( + environment, + read_git_output(['rev-parse', '--verify', oldrev]), + read_git_output(['rev-parse', '--verify', newrev]), + refname, + ), + ] + if not changes: + mailer.close() + return + push = Push(environment, changes, force_send) + try: + push.send_emails(mailer, body_filter=environment.filter_body) + finally: + mailer.close() + + +def check_ref_filter(environment): + send_filter_regex, send_is_inclusion = environment.get_ref_filter_regex(True) + ref_filter_regex, ref_is_inclusion = environment.get_ref_filter_regex(False) + + def inc_exc_lusion(b): + if b: + return 'inclusion' + else: + return 'exclusion' + + if send_filter_regex: + sys.stdout.write("DoSend/DontSend filter regex (" + + (inc_exc_lusion(send_is_inclusion)) + + '): ' + send_filter_regex.pattern + + '\n') + if send_filter_regex: + sys.stdout.write("Include/Exclude filter regex (" + + (inc_exc_lusion(ref_is_inclusion)) + + '): ' + ref_filter_regex.pattern + + '\n') + sys.stdout.write(os.linesep) + + sys.stdout.write( + "Refs marked as EXCLUDE are excluded by either refFilterInclusionRegex\n" + "or refFilterExclusionRegex. No emails will be sent for commits included\n" + "in these refs.\n" + "Refs marked as DONT-SEND are excluded by either refFilterDoSendRegex or\n" + "refFilterDontSendRegex, but not by either refFilterInclusionRegex or\n" + "refFilterExclusionRegex. Emails will be sent for commits included in these\n" + "refs only when the commit reaches a ref which isn't excluded.\n" + "Refs marked as DO-SEND are not excluded by any filter. Emails will\n" + "be sent normally for commits included in these refs.\n") + + sys.stdout.write(os.linesep) + + for refname in read_git_lines(['for-each-ref', '--format', '%(refname)']): + sys.stdout.write(refname) + if not include_ref(refname, ref_filter_regex, ref_is_inclusion): + sys.stdout.write(' EXCLUDE') + elif not include_ref(refname, send_filter_regex, send_is_inclusion): + sys.stdout.write(' DONT-SEND') + else: + sys.stdout.write(' DO-SEND') + + sys.stdout.write(os.linesep) + + +def show_env(environment, out): + out.write('Environment values:\n') + for (k, v) in sorted(environment.get_values().items()): + if k: # Don't show the {'' : ''} pair. + out.write(' %s : %r\n' % (k, v)) + out.write('\n') + # Flush to avoid interleaving with further log output + out.flush() + + +def check_setup(environment): + environment.check() + show_env(environment, sys.stdout) + sys.stdout.write("Now, checking that git-multimail's standard input " + "is properly set ..." + os.linesep) + sys.stdout.write("Please type some text and then press Return" + os.linesep) + stdin = sys.stdin.readline() + sys.stdout.write("You have just entered:" + os.linesep) + sys.stdout.write(stdin) + sys.stdout.write("git-multimail seems properly set up." + os.linesep) + + +def choose_mailer(config, environment): + mailer = config.get('mailer', default='sendmail') + + if mailer == 'smtp': + smtpserver = config.get('smtpserver', default='localhost') + smtpservertimeout = float(config.get('smtpservertimeout', default=10.0)) + smtpserverdebuglevel = int(config.get('smtpserverdebuglevel', default=0)) + smtpencryption = config.get('smtpencryption', default='none') + smtpuser = config.get('smtpuser', default='') + smtppass = config.get('smtppass', default='') + smtpcacerts = config.get('smtpcacerts', default='') + mailer = SMTPMailer( + environment, + envelopesender=(environment.get_sender() or environment.get_fromaddr()), + smtpserver=smtpserver, smtpservertimeout=smtpservertimeout, + smtpserverdebuglevel=smtpserverdebuglevel, + smtpencryption=smtpencryption, + smtpuser=smtpuser, + smtppass=smtppass, + smtpcacerts=smtpcacerts + ) + elif mailer == 'sendmail': + command = config.get('sendmailcommand') + if command: + command = shlex.split(command) + mailer = SendMailer(environment, + command=command, envelopesender=environment.get_sender()) + else: + environment.log_error( + 'fatal: multimailhook.mailer is set to an incorrect value: "%s"\n' % mailer + + 'please use one of "smtp" or "sendmail".' + ) + sys.exit(1) + return mailer + + +KNOWN_ENVIRONMENTS = { + 'generic': {'highprec': GenericEnvironmentMixin}, + 'gitolite': {'highprec': GitoliteEnvironmentHighPrecMixin, + 'lowprec': GitoliteEnvironmentLowPrecMixin}, + 'stash': {'highprec': StashEnvironmentHighPrecMixin, + 'lowprec': StashEnvironmentLowPrecMixin}, + 'gerrit': {'highprec': GerritEnvironmentHighPrecMixin, + 'lowprec': GerritEnvironmentLowPrecMixin}, + 'gitea': {'highprec': GiteaEnvironmentHighPrecMixin, + 'lowprec': GiteaEnvironmentLowPrecMixin}, + } + + +def choose_environment(config, osenv=None, env=None, recipients=None, + hook_info=None): + env_name = choose_environment_name(config, env, osenv) + environment_klass = build_environment_klass(env_name) + env = build_environment(environment_klass, env_name, config, + osenv, recipients, hook_info) + return env + + +def choose_environment_name(config, env, osenv): + if not osenv: + osenv = os.environ + + if not env: + env = config.get('environment') + + if not env: + if 'GL_USER' in osenv and 'GL_REPO' in osenv: + env = 'gitolite' + elif 'GITEA_PUSHER_NAME' in osenv and 'GITEA_REPO_NAME' in osenv: + env = 'gitea' + else: + env = 'generic' + return env + + +COMMON_ENVIRONMENT_MIXINS = [ + ConfigRecipientsEnvironmentMixin, + CLIRecipientsEnvironmentMixin, + ConfigRefFilterEnvironmentMixin, + ProjectdescEnvironmentMixin, + ConfigMaxlinesEnvironmentMixin, + ComputeFQDNEnvironmentMixin, + ConfigFilterLinesEnvironmentMixin, + PusherDomainEnvironmentMixin, + ConfigOptionsEnvironmentMixin, + ] + + +def build_environment_klass(env_name): + if 'class' in KNOWN_ENVIRONMENTS[env_name]: + return KNOWN_ENVIRONMENTS[env_name]['class'] + + environment_mixins = [] + known_env = KNOWN_ENVIRONMENTS[env_name] + if 'highprec' in known_env: + high_prec_mixin = known_env['highprec'] + environment_mixins.append(high_prec_mixin) + environment_mixins = environment_mixins + COMMON_ENVIRONMENT_MIXINS + if 'lowprec' in known_env: + low_prec_mixin = known_env['lowprec'] + environment_mixins.append(low_prec_mixin) + environment_mixins.append(Environment) + klass_name = env_name.capitalize() + 'Environment' + environment_klass = type( + klass_name, + tuple(environment_mixins), + {}, + ) + KNOWN_ENVIRONMENTS[env_name]['class'] = environment_klass + return environment_klass + + +GiteaEnvironment = build_environment_klass('gitea') +GerritEnvironment = build_environment_klass('gerrit') +StashEnvironment = build_environment_klass('stash') +GitoliteEnvironment = build_environment_klass('gitolite') +GenericEnvironment = build_environment_klass('generic') + + +def build_environment(environment_klass, env, config, + osenv, recipients, hook_info): + environment_kw = { + 'osenv': osenv, + 'config': config, + } + + if env == 'stash': + environment_kw['user'] = hook_info['stash_user'] + environment_kw['repo'] = hook_info['stash_repo'] + elif env == 'gerrit': + environment_kw['project'] = hook_info['project'] + environment_kw['submitter'] = hook_info['submitter'] + environment_kw['update_method'] = hook_info['update_method'] + + environment_kw['cli_recipients'] = recipients + + return environment_klass(**environment_kw) + + +def get_version(): + oldcwd = os.getcwd() + try: + try: + os.chdir(os.path.dirname(os.path.realpath(__file__))) + git_version = read_git_output(['describe', '--tags', 'HEAD']) + if git_version == __version__: + return git_version + else: + return '%s (%s)' % (__version__, git_version) + except: + pass + finally: + os.chdir(oldcwd) + return __version__ + + +def compute_gerrit_options(options, args, required_gerrit_options, + raw_refname): + if None in required_gerrit_options: + raise SystemExit("Error: Specify all of --oldrev, --newrev, --refname, " + "and --project; or none of them.") + + if options.environment not in (None, 'gerrit'): + raise SystemExit("Non-gerrit environments incompatible with --oldrev, " + "--newrev, --refname, and --project") + options.environment = 'gerrit' + + if args: + raise SystemExit("Error: Positional parameters not allowed with " + "--oldrev, --newrev, and --refname.") + + # Gerrit oddly omits 'refs/heads/' in the refname when calling + # ref-updated hook; put it back. + git_dir = get_git_dir() + if (not os.path.exists(os.path.join(git_dir, raw_refname)) and + os.path.exists(os.path.join(git_dir, 'refs', 'heads', + raw_refname))): + options.refname = 'refs/heads/' + options.refname + + # New revisions can appear in a gerrit repository either due to someone + # pushing directly (in which case options.submitter will be set), or they + # can press "Submit this patchset" in the web UI for some CR (in which + # case options.submitter will not be set and gerrit will not have provided + # us the information about who pressed the button). + # + # Note for the nit-picky: I'm lumping in REST API calls and the ssh + # gerrit review command in with "Submit this patchset" button, since they + # have the same effect. + if options.submitter: + update_method = 'pushed' + # The submitter argument is almost an RFC 2822 email address; change it + # from 'User Name (email@domain)' to 'User Name <email@domain>' so it is + options.submitter = options.submitter.replace('(', '<').replace(')', '>') + else: + update_method = 'submitted' + # Gerrit knew who submitted this patchset, but threw that information + # away when it invoked this hook. However, *IF* Gerrit created a + # merge to bring the patchset in (project 'Submit Type' is either + # "Always Merge", or is "Merge if Necessary" and happens to be + # necessary for this particular CR), then it will have the committer + # of that merge be 'Gerrit Code Review' and the author will be the + # person who requested the submission of the CR. Since this is fairly + # likely for most gerrit installations (of a reasonable size), it's + # worth the extra effort to try to determine the actual submitter. + rev_info = read_git_lines(['log', '--no-walk', '--merges', + '--format=%cN%n%aN <%aE>', options.newrev]) + if rev_info and rev_info[0] == 'Gerrit Code Review': + options.submitter = rev_info[1] + + # We pass back refname, oldrev, newrev as args because then the + # gerrit ref-updated hook is much like the git update hook + return (options, + [options.refname, options.oldrev, options.newrev], + {'project': options.project, 'submitter': options.submitter, + 'update_method': update_method}) + + +def check_hook_specific_args(options, args): + raw_refname = options.refname + # Convert each string option unicode for Python3. + if PYTHON3: + opts = ['environment', 'recipients', 'oldrev', 'newrev', 'refname', + 'project', 'submitter', 'stash_user', 'stash_repo'] + for opt in opts: + if not hasattr(options, opt): + continue + obj = getattr(options, opt) + if obj: + enc = obj.encode('utf-8', 'surrogateescape') + dec = enc.decode('utf-8', 'replace') + setattr(options, opt, dec) + + # First check for stash arguments + if (options.stash_user is None) != (options.stash_repo is None): + raise SystemExit("Error: Specify both of --stash-user and " + "--stash-repo or neither.") + if options.stash_user: + options.environment = 'stash' + return options, args, {'stash_user': options.stash_user, + 'stash_repo': options.stash_repo} + + # Finally, check for gerrit specific arguments + required_gerrit_options = (options.oldrev, options.newrev, options.refname, + options.project) + if required_gerrit_options != (None,) * 4: + return compute_gerrit_options(options, args, required_gerrit_options, + raw_refname) + + # No special options in use, just return what we started with + return options, args, {} + + +class Logger(object): + def parse_verbose(self, verbose): + if verbose > 0: + return logging.DEBUG + else: + return logging.INFO + + def create_log_file(self, environment, name, path, verbosity): + log_file = logging.getLogger(name) + file_handler = logging.FileHandler(path) + log_fmt = logging.Formatter("%(asctime)s [%(levelname)-5.5s] %(message)s") + file_handler.setFormatter(log_fmt) + log_file.addHandler(file_handler) + log_file.setLevel(verbosity) + return log_file + + def __init__(self, environment): + self.environment = environment + self.loggers = [] + stderr_log = logging.getLogger('git_multimail.stderr') + + class EncodedStderr(object): + def write(self, x): + write_str(sys.stderr, x) + + def flush(self): + sys.stderr.flush() + + stderr_handler = logging.StreamHandler(EncodedStderr()) + stderr_log.addHandler(stderr_handler) + stderr_log.setLevel(self.parse_verbose(environment.verbose)) + self.loggers.append(stderr_log) + + if environment.debug_log_file is not None: + debug_log_file = self.create_log_file( + environment, 'git_multimail.debug', environment.debug_log_file, logging.DEBUG) + self.loggers.append(debug_log_file) + + if environment.log_file is not None: + log_file = self.create_log_file( + environment, 'git_multimail.file', environment.log_file, logging.INFO) + self.loggers.append(log_file) + + if environment.error_log_file is not None: + error_log_file = self.create_log_file( + environment, 'git_multimail.error', environment.error_log_file, logging.ERROR) + self.loggers.append(error_log_file) + + def info(self, msg, *args, **kwargs): + for l in self.loggers: + l.info(msg, *args, **kwargs) + + def debug(self, msg, *args, **kwargs): + for l in self.loggers: + l.debug(msg, *args, **kwargs) + + def warning(self, msg, *args, **kwargs): + for l in self.loggers: + l.warning(msg, *args, **kwargs) + + def error(self, msg, *args, **kwargs): + for l in self.loggers: + l.error(msg, *args, **kwargs) + + +def main(args): + parser = optparse.OptionParser( + description=__doc__, + usage='%prog [OPTIONS]\n or: %prog [OPTIONS] REFNAME OLDREV NEWREV', + ) + + parser.add_option( + '--environment', '--env', action='store', type='choice', + choices=list(KNOWN_ENVIRONMENTS.keys()), default=None, + help=( + 'Choose type of environment is in use. Default is taken from ' + 'multimailhook.environment if set; otherwise "generic".' + ), + ) + parser.add_option( + '--stdout', action='store_true', default=False, + help='Output emails to stdout rather than sending them.', + ) + parser.add_option( + '--recipients', action='store', default=None, + help='Set list of email recipients for all types of emails.', + ) + parser.add_option( + '--show-env', action='store_true', default=False, + help=( + 'Write to stderr the values determined for the environment ' + '(intended for debugging purposes), then proceed normally.' + ), + ) + parser.add_option( + '--force-send', action='store_true', default=False, + help=( + 'Force sending refchange email when using as an update hook. ' + 'This is useful to work around the unreliable new commits ' + 'detection in this mode.' + ), + ) + parser.add_option( + '-c', metavar="<name>=<value>", action='append', + help=( + 'Pass a configuration parameter through to git. The value given ' + 'will override values from configuration files. See the -c option ' + 'of git(1) for more details. (Only works with git >= 1.7.3)' + ), + ) + parser.add_option( + '--version', '-v', action='store_true', default=False, + help=( + "Display git-multimail's version" + ), + ) + + parser.add_option( + '--python-version', action='store_true', default=False, + help=( + "Display the version of Python used by git-multimail" + ), + ) + + parser.add_option( + '--check-ref-filter', action='store_true', default=False, + help=( + 'List refs and show information on how git-multimail ' + 'will process them.' + ) + ) + + # The following options permit this script to be run as a gerrit + # ref-updated hook. See e.g. + # code.google.com/p/gerrit/source/browse/Documentation/config-hooks.txt + # We suppress help for these items, since these are specific to gerrit, + # and we don't want users directly using them any way other than how the + # gerrit ref-updated hook is called. + parser.add_option('--oldrev', action='store', help=optparse.SUPPRESS_HELP) + parser.add_option('--newrev', action='store', help=optparse.SUPPRESS_HELP) + parser.add_option('--refname', action='store', help=optparse.SUPPRESS_HELP) + parser.add_option('--project', action='store', help=optparse.SUPPRESS_HELP) + parser.add_option('--submitter', action='store', help=optparse.SUPPRESS_HELP) + + # The following allow this to be run as a stash asynchronous post-receive + # hook (almost identical to a git post-receive hook but triggered also for + # merges of pull requests from the UI). We suppress help for these items, + # since these are specific to stash. + parser.add_option('--stash-user', action='store', help=optparse.SUPPRESS_HELP) + parser.add_option('--stash-repo', action='store', help=optparse.SUPPRESS_HELP) + + (options, args) = parser.parse_args(args) + (options, args, hook_info) = check_hook_specific_args(options, args) + + if options.version: + sys.stdout.write('git-multimail version ' + get_version() + '\n') + return + + if options.python_version: + sys.stdout.write('Python version ' + sys.version + '\n') + return + + if options.c: + Config.add_config_parameters(options.c) + + config = Config('multimailhook') + + environment = None + try: + environment = choose_environment( + config, osenv=os.environ, + env=options.environment, + recipients=options.recipients, + hook_info=hook_info, + ) + + if options.show_env: + show_env(environment, sys.stderr) + + if options.stdout or environment.stdout: + mailer = OutputMailer(sys.stdout, environment) + else: + mailer = choose_mailer(config, environment) + + must_check_setup = os.environ.get('GIT_MULTIMAIL_CHECK_SETUP') + if must_check_setup == '': + must_check_setup = False + if options.check_ref_filter: + check_ref_filter(environment) + elif must_check_setup: + check_setup(environment) + # Dual mode: if arguments were specified on the command line, run + # like an update hook; otherwise, run as a post-receive hook. + elif args: + if len(args) != 3: + parser.error('Need zero or three non-option arguments') + (refname, oldrev, newrev) = args + environment.get_logger().debug( + "run_as_update_hook: refname=%s, oldrev=%s, newrev=%s, force_send=%s" % + (refname, oldrev, newrev, options.force_send)) + run_as_update_hook(environment, mailer, refname, oldrev, newrev, options.force_send) + else: + run_as_post_receive_hook(environment, mailer) + except ConfigurationException: + sys.exit(sys.exc_info()[1]) + except SystemExit: + raise + except Exception: + t, e, tb = sys.exc_info() + import traceback + sys.stderr.write('\n') # Avoid mixing message with previous output + msg = ( + 'Exception \'' + t.__name__ + + '\' raised. Please report this as a bug to\n' + 'https://github.com/git-multimail/git-multimail/issues\n' + 'with the information below:\n\n' + 'git-multimail version ' + get_version() + '\n' + 'Python version ' + sys.version + '\n' + + traceback.format_exc()) + try: + environment.get_logger().error(msg) + except: + sys.stderr.write(msg) + sys.exit(1) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/deployment/mgagit/manifests/init.pp b/deployment/mgagit/manifests/init.pp new file mode 100644 index 00000000..42753b03 --- /dev/null +++ b/deployment/mgagit/manifests/init.pp @@ -0,0 +1,170 @@ +class mgagit( + $git_dir = '/git', + $ldap_server = "ldap.${::domain}", + $binddn = 'uid=mgagit,ou=People,dc=mageia,dc=org', + $vhost = "projects.${::domain}", + $bindpw +){ + $git_login = 'git' + $git_homedir = "/var/lib/${git_login}" + $gitolite_dir = "${git_homedir}/.gitolite" + $gitolite_keydir = "${gitolite_dir}/keydir" + $gitolite_tmpldir = '/etc/mgagit/tmpl' + $gitolite_confdir = "${gitolite_dir}/conf" + $gitolite_hooksdir = "${gitolite_dir}/hooks" + $gitolite_commonhooksdir = "${gitolite_hooksdir}/common" + $gitolite_conf = "${gitolite_confdir}/gitolite.conf" + $gitoliterc = "${git_homedir}/.gitolite.rc" + $bindpwfile = '/etc/mgagit.secret' + $reposconf_dir = "${git_homedir}/repos-config" + $vhostdir = "${git_homedir}/www" + + package { ['mgagit', 'gitolite', 'python3-bugz']: + ensure => installed, + } + + group { $git_login: + ensure => present, + } + + user { $git_login: + ensure => present, + home => $git_homedir, + managehome => true, + gid => $git_login, + } + + file { '/etc/mgagit.conf': + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mgagit/mgagit.conf'), + require => Package['mgagit'], + } + + file { "${gitolite_commonhooksdir}/git_multimail.py": + ensure => present, + owner => $git_login, + group => $git_login, + mode => '0644', + source => 'puppet:///modules/mgagit/git_multimail.py', + require => File[$gitolite_commonhooksdir], + } + + file { "${gitolite_commonhooksdir}/post-receive": + ensure => present, + owner => $git_login, + group => $git_login, + mode => '0755', + content => template('mgagit/git-post-receive-hook'), + require => File[$gitolite_commonhooksdir], + } + + file { "${gitolite_commonhooksdir}/post-update": + ensure => present, + owner => $git_login, + group => $git_login, + mode => '0755', + content => template('mgagit/git-post-update-hook'), + require => File[$gitolite_commonhooksdir], + } + + file { $gitolite_tmpldir: + ensure => directory, + owner => root, + group => root, + mode => '0755', + } + + file { "${gitolite_tmpldir}/group.gl": + ensure => 'link', + target => '/usr/share/mgagit/tmpl/group.gl', + } + + file { "${gitolite_tmpldir}/repodef_repo.gl": + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mgagit/repodef_repo.gl'), + } + + mgagit::tmpl { 'artwork': + tmpldir => $gitolite_tmpldir, + ml => 'atelier', + } + + mgagit::tmpl { 'doc': + tmpldir => $gitolite_tmpldir, + ml => 'atelier', # NB This is wrong, we should have a doc-commits@ ML (and thus remove this line) + } + + mgagit::tmpl { 'infrastructure': + tmpldir => $gitolite_tmpldir, + group => 'sysadmin', + ml => 'sysadmin', + } + + mgagit::tmpl { 'org': + tmpldir => $gitolite_tmpldir, + group => 'board', + ml => 'board', + } + + mgagit::tmpl { 'qa': + tmpldir => $gitolite_tmpldir, + } + + mgagit::tmpl { 'soft': + tmpldir => $gitolite_tmpldir, + group => 'packagers-committers', + } + + mgagit::tmpl { 'web': + tmpldir => $gitolite_tmpldir, + ml => 'atelier', + } + + file { [$gitolite_dir, $gitolite_keydir, $gitolite_confdir, + $gitolite_hooksdir, $gitolite_commonhooksdir, + $reposconf_dir, $vhostdir]: + ensure => directory, + owner => $git_login, + group => $git_login, + mode => '0755', + } + + file { $gitoliterc: + ensure => present, + owner => $git_login, + group => $git_login, + mode => '0644', + content => template('mgagit/gitolite.rc'), + } + + file { $bindpwfile: + ensure => present, + owner => $git_login, + group => $git_login, + mode => '0600', + content => inline_template('<%= @bindpw %>'), + } + + file { $git_dir: + ensure => directory, + owner => $git_login, + group => $git_login, + mode => '0755', + } + + file { "${git_homedir}/repositories": + ensure => 'link', + target => $git_dir, + } + + apache::vhost::base { $vhost: + location => $vhostdir, + } +} +# vim: sw=2 diff --git a/deployment/mgagit/manifests/tmpl.pp b/deployment/mgagit/manifests/tmpl.pp new file mode 100644 index 00000000..ef188ed2 --- /dev/null +++ b/deployment/mgagit/manifests/tmpl.pp @@ -0,0 +1,9 @@ +define mgagit::tmpl($tmpldir, $group = $title, $ml = $title) { + file { "${tmpldir}/${title}_repo.gl": + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mgagit/group_owned_repo.gl'), + } +} diff --git a/deployment/mgagit/templates/git-post-receive-hook b/deployment/mgagit/templates/git-post-receive-hook new file mode 100755 index 00000000..68da3200 --- /dev/null +++ b/deployment/mgagit/templates/git-post-receive-hook @@ -0,0 +1,314 @@ +#!/usr/bin/python3 + +import configparser +import os +import re +import sys +import urllib.error +import urllib.parse +import urllib.request +import xmlrpc.client +from dataclasses import dataclass + +LIBDIR = '<%= @gitolite_commonhooksdir %>' +sys.path.insert(0, LIBDIR) + +import bugz.settings + +import git_multimail + +# When editing this list, remember to edit the same list in +# modules/cgit/templates/filter.commit-links.sh +BUG_REFS = { + 'Mageia': { 're': re.compile('mga#([0-9]+)'), 'replace': 'https://bugs.mageia.org/%s' }, + 'Red Hat': { 're': re.compile('rhbz#([0-9]+)'), 'replace': 'https://bugzilla.redhat.com/show_bug.cgi?id=%s' }, + 'Free Desktop': { 're': re.compile('fdo#([0-9]+)'), 'replace': 'https://bugs.freedesktop.org/show_bug.cgi?id=%s' }, + 'KDE': { 're': re.compile('(?:bko|kde)#([0-9]+)'), 'replace': 'https://bugs.kde.org/show_bug.cgi?id=%s' }, + 'GNOME': { 're': re.compile('(?:bgo|gnome)#([0-9]+)'), 'replace': 'https://bugzilla.gnome.org/show_bug.cgi?id=%s' }, + 'Launchpad': { 're': re.compile('lp#([0-9]+)'), 'replace': 'https://launchpad.net/bugs/%s' }, +} + +COMMIT_RE = re.compile('^commit ([a-f0-9]{40})') +COMMIT_REPLACE = 'https://gitweb.mageia.org/%s/commit/?id=%s' + +MAGEIA_BUGZILLA_URL = 'https://bugs.mageia.org/xmlrpc.cgi' +MAGEIA_BUGZILLA_PASSWORD_FILE = '.gitzilla-password' +MAGEIA_BUGZILLA_APIKEY_FILE = '.gitzilla-apikey' # this holds a Bugzilla API key +GITWEB_UPDATE_URL = 'http://gitweb.mageia.org:8000' + +# Bugzilla user +USER_LOGIN = 'bot' + +# Recipient of i18n notifications +I18N_MAIL = 'i18n-reports@ml.mageia.org' + +# Set to 1..3 for debug logging (WARNING: this will show passwords to git committers!) +DEBUG = 0 + +git_multimail.FOOTER_TEMPLATE = """\ + +-- \n\ +Mageia Git Monkeys. +""" +git_multimail.REVISION_FOOTER_TEMPLATE = git_multimail.FOOTER_TEMPLATE + +I18N_REVISION_HEADER_TEMPLATE = """\ +Date: %(send_date)s +To: %(recipients)s +Subject: %(emailprefix)s%(oneline)s +MIME-Version: 1.0 +Content-Type: text/plain; charset=%(charset)s +Content-Transfer-Encoding: 8bit +From: %(fromaddr)s +Reply-To: %(reply_to)s +In-Reply-To: %(reply_to_msgid)s +References: %(reply_to_msgid)s +X-Git-Host: %(fqdn)s +X-Git-Repo: %(repo_shortname)s +X-Git-Refname: %(refname)s +X-Git-Reftype: %(refname_type)s +X-Git-Rev: %(rev)s +Auto-Submitted: auto-generated +""" + + +REPO_NAME_RE = re.compile(r'^/git/(?P<name>.+?)(?:\.git)?$') + + +# Log a debug message when logging is enabled +def debug(s, *a): + if DEBUG > 0: + print(s % a) + + +def repo_shortname(): + basename = os.path.abspath(git_multimail.get_git_dir()) + m = REPO_NAME_RE.match(basename) + if m: + return m.group('name') + else: + return basename + + +# Override the Environment class to generate an appropriate short name which is +# used in git links and as an email prefix +class MageiaEnvironment(git_multimail.Environment): + def get_repo_shortname(self): + return repo_shortname() + + +git_multimail.Environment = MageiaEnvironment + + +# Override the Revision class to inject gitweb/cgit links and any referenced +# bug URLs +class MageiaLinksRevision(git_multimail.Revision): + def __init__(self, reference_change, rev, num, tot): + super().__init__(reference_change, rev, num, tot) + self.bz = None + + def bugzilla_init(self): + if not self.bz: + tokenfile = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_APIKEY_FILE) + token = None + try: + token = open(tokenfile, 'r').readline().rstrip() + except IOError: + # Assume username/password will be used instead + pass + + passwordfile = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_PASSWORD_FILE) + pword = None + try: + pword = open(passwordfile, 'r').readline().rstrip() + except IOError: + print('Error: no Bugzilla credentials available; trying anyway') + # There's no real point in continuing, but why not + + class ConfigSettings: + pass + + cfg = ConfigSettings() + cfg.connection = 'Mageia' + if token: + # If an API key is found, that will be used instead of user/password + cfg.key = token + cfg.user = USER_LOGIN + cfg.password = pword + cfg.base = MAGEIA_BUGZILLA_URL + cfg.debug = DEBUG + + cfile = configparser.ConfigParser() + cfile.add_section(cfg.connection) + self.bz = bugz.settings.Settings(cfg, cfile) + + def generate_email_body(self, push): + """Show this revision.""" + output = git_multimail.read_git_lines( + ['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1], + keepends=True, + ) + bugs = {} + commit = None + idx = 0 + # Modify the mail output on-the-fly to add links; this is sensitive to + # the mail format produced by git_multimail. Also, update Mageia + # Bugzilla if a bug reference is found. + for line in output: + idx += 1 + if line == "---\n": + if commit and COMMIT_REPLACE: + output.insert(idx, "\n") + output.insert(idx, " %s\n" % (COMMIT_REPLACE % (self.environment.get_repo_shortname(), commit))) + output.insert(idx, " Commit Link:\n") + idx += 3 + if bugs: + output.insert(idx, " Bug links:\n") + idx += 1 + for tracker, bugnos in bugs.items(): + output.insert(idx, " %s\n" % tracker) + idx += 1 + for bugno in bugnos: + output.insert(idx, " %s\n" % (BUG_REFS[tracker]['replace'] % bugno)) + idx += 1 + output.insert(idx, "\n") + idx += 1 + + # Attempt to modify Bugzilla + if "Mageia" in bugs: + try: + self.bugzilla_init() + + # Mask email address + comment = None + # Suppress the "Bug links:" section if only one bug + # is referenced + if len(bugs) == 1 and len(bugs['Mageia']) == 1: + comment = output[0:idx-4] + else: + comment = output[0:idx] + comment[1] = re.sub(r'^(Author: [^@]*)@.*(>)?', r'\1@...>', comment[1]) + comment = "".join(comment) + + params = {} + params['ids'] = bugs['Mageia'] + params['comment'] = { 'body': comment } + self.bz.call_bz(self.bz.bz.Bug.update, params) + print("Updated bugzilla bugs: %s" % ", ".join(bugs['Mageia'])) + except: + print("Unable to post to bugzilla bugs: %s :(" % ", ".join(bugs['Mageia'])) + print(sys.exc_info()[1]) + + break + + m = COMMIT_RE.search(line) + if m: + commit = m.group(1) + for tracker in BUG_REFS.keys(): + foundbugs = BUG_REFS[tracker]['re'].findall(line) + if foundbugs: + if tracker not in bugs: + bugs[tracker] = foundbugs + else: + bugs[tracker] = list(set(bugs[tracker] + foundbugs)) + + return output + + +# Override the Revision class to inject gitweb/cgit links and any referenced +# bug URLs +class MageiaI18NRevision(git_multimail.Revision): + """A Change consisting of a single git commit.""" + + def __init__(self, reference_change, rev, num, tot): + super().__init__(reference_change, rev, num, tot) + + # Don't send to any of the normal recipients + self.recipients = False + self.cc_recipients = '' + + i18n_folders = [] + # Check files and find i18n folders + for line in git_multimail.read_git_lines(['ls-tree', '-rd', self.rev.sha1]): + (modetypesha1, name) = line.split("\t", 1) + if name.endswith("/.tx"): + i18n_folders.append(os.path.dirname(name)) + + if i18n_folders: + self.output = git_multimail.read_git_lines( + ['log', '-C', '--stat', '-p', '--no-walk', self.rev.sha1, '--'] + i18n_folders, + keepends=True, + ) + if self.output: + # We have some output so let's send the mail... + self.recipients = I18N_MAIL + print(f'Sending i8n notification to {self.recipients}') + + + def generate_email_body(self, push): + """Show this revision.""" + + return self.output + + +def main(): + # Attempt to write a last-updated file for cgit cosmetics + git_dir = git_multimail.get_git_dir() + infowebdir = os.path.join(git_dir, 'info', 'web') + lastupdated = git_multimail.read_git_output( + ['for-each-ref', '--sort=-committerdate', "--format=%(committerdate:iso8601)", '--count=1', 'refs/heads'], + ) + try: + if not os.path.exists(infowebdir): + os.makedirs(infowebdir) + with open(os.path.join(infowebdir, 'last-modified'), 'w') as modfile: + modfile.write(lastupdated) + except Exception: + debug('Warning: could not update git last-modified date: %s', sys.exc_info()[1]) + + # Contact the on-the-pull service on the gitweb server with the updated repo + try: + req = urllib.request.Request(GITWEB_UPDATE_URL, (repo_shortname() + '.git').encode('utf-8')) + req.add_header('Content-Type', 'x-git/repo') + fp = urllib.request.urlopen(req, timeout=5) + fp.close() + except Exception: + debug('Warning: could not contact gitweb server: %s', sys.exc_info()[1]) + + config = git_multimail.Config('multimailhook') + + try: + environment = git_multimail.choose_environment( + config, osenv=os.environ, + ) + + mailer = git_multimail.choose_mailer(config, environment) + # For testing...send mail to stdout only + #mailer = git_multimail.OutputMailer(sys.stdout) + + changes = [] + for line in sys.stdin: + (oldrev, newrev, refname) = line.strip().split(' ', 2) + changes.append( + git_multimail.ReferenceChange.create(environment, oldrev, newrev, refname) + ) + push = git_multimail.Push(environment, changes) + + # First pass - regular commit mails + git_multimail.Revision = MageiaLinksRevision + push.send_emails(mailer, body_filter=environment.filter_body) + + # Second pass - i18n commit mails + git_multimail.REVISION_HEADER_TEMPLATE = I18N_REVISION_HEADER_TEMPLATE + git_multimail.Revision = MageiaI18NRevision + # Don't send the summary email, so nuke the change recipients + for change in push.changes: + change.recipients = False + push.send_emails(mailer, body_filter=environment.filter_body) + + except git_multimail.ConfigurationException as e: + sys.exit(str(e)) + + +if __name__ == '__main__': + main() diff --git a/deployment/mgagit/templates/git-post-update-hook b/deployment/mgagit/templates/git-post-update-hook new file mode 100644 index 00000000..a2550ad3 --- /dev/null +++ b/deployment/mgagit/templates/git-post-update-hook @@ -0,0 +1,12 @@ +#!/bin/bash + +if [ "${GL_REPO:0:28}" == "infrastructure/repositories/" ]; then + OK=no + (unset GIT_DIR && mgagit glconf && mgagit glrun) >/dev/null 2>&1 && OK=yes + if [ "$OK" == "yes" ]; then + echo + echo " *** Repository definitions updated" + echo + fi +fi +exit 0
\ No newline at end of file diff --git a/deployment/mgagit/templates/gitolite.rc b/deployment/mgagit/templates/gitolite.rc new file mode 100644 index 00000000..c4c925e6 --- /dev/null +++ b/deployment/mgagit/templates/gitolite.rc @@ -0,0 +1,161 @@ +# configuration variables for gitolite + +# This file is in perl syntax. But you do NOT need to know perl to edit it -- +# just mind the commas, use single quotes unless you know what you're doing, +# and make sure the brackets and braces stay matched up! + +# (Tip: perl allows a comma after the last item in a list also!) + +# HELP for commands can be had by running the command with "-h". + +# HELP for all the other FEATURES can be found in the documentation (look for +# "list of non-core programs shipped with gitolite" in the master index) or +# directly in the corresponding source file. + +%RC = ( + + # ------------------------------------------------------------------ + + # default umask gives you perms of '0700'; see the rc file docs for + # how/why you might change this + UMASK => 0022, + + # look for "git-config" in the documentation + GIT_CONFIG_KEYS => 'gitweb\.description gitweb\.owner multimailhook\.mailingList multimailhook\.emailDomain multimailhook\.envelopeSender', + + # comment out if you don't need all the extra detail in the logfile + LOG_EXTRA => 1, + + # roles. add more roles (like MANAGER, TESTER, ...) here. + # WARNING: if you make changes to this hash, you MUST run 'gitolite + # compile' afterward, and possibly also 'gitolite trigger POST_COMPILE' + ROLES => { + READERS => 1, + WRITERS => 1, + }, + + # ------------------------------------------------------------------ + + # rc variables used by various features + + # the 'info' command prints this as additional info, if it is set + # SITE_INFO => 'Please see http://blahblah/gitolite for more help', + + # the 'desc' command uses this + # WRITER_CAN_UPDATE_DESC => 1, + + # the CpuTime feature uses these + # display user, system, and elapsed times to user after each git operation + # DISPLAY_CPU_TIME => 1, + # display a warning if total CPU times (u, s, cu, cs) crosses this limit + # CPU_TIME_WARN_LIMIT => 0.1, + + # the Mirroring feature needs this + # HOSTNAME => "foo", + + # if you enabled 'Shell', you need this + # SHELL_USERS_LIST => "$ENV{HOME}/.gitolite.shell-users", + + # ------------------------------------------------------------------ + + # List of commands and features to enable + + ENABLE => [ + + # COMMANDS + + # These are the commands enabled by default + 'help', + 'desc', + 'info', + 'perms', + 'writable', + + # Uncomment or add new commands here. + # 'create', + # 'fork', + # 'mirror', + # 'sskm', + # 'D', + + # These FEATURES are enabled by default. + + # essential (unless you're using smart-http mode) + 'ssh-authkeys', + + # creates git-config entities from gitolite.conf file entries like 'config foo.bar = baz' + 'git-config', + + # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out + 'daemon', + + # creates projects.list file; if you don't use gitweb, comment this out + 'gitweb', + + # These FEATURES are disabled by default; uncomment to enable. If you + # need to add new ones, ask on the mailing list :-) + + # user-visible behaviour + + # prevent wild repos auto-create on fetch/clone + # 'no-create-on-read', + # no auto-create at all (don't forget to enable the 'create' command!) + # 'no-auto-create', + + # access a repo by another (possibly legacy) name + # 'Alias', + + # give some users direct shell access + # 'Shell', + + # set default roles from lines like 'option default.roles-1 = ...', etc. + # 'set-default-roles', + + # system admin stuff + + # enable mirroring (don't forget to set the HOSTNAME too!) + # 'Mirroring', + + # allow people to submit pub files with more than one key in them + # 'ssh-authkeys-split', + + # selective read control hack + # 'partial-copy', + + # manage local, gitolite-controlled, copies of read-only upstream repos + # 'upstream', + + # updates 'description' file instead of 'gitweb.description' config item + 'cgit', + + # performance, logging, monitoring... + + # be nice + # 'renice 10', + + # log CPU times (user, system, cumulative user, cumulative system) + # 'CpuTime', + + # syntactic_sugar for gitolite.conf and included files + + # allow backslash-escaped continuation lines in gitolite.conf + # 'continuation-lines', + + # create implicit user groups from directory names in keydir/ + # 'keysubdirs-as-groups', + + # allow simple line-oriented macros + # 'macros', + + ], + +); + +# ------------------------------------------------------------------------------ +# per perl rules, this should be the last line in such a file: +1; + +# Local variables: +# mode: perl +# End: +# vim: set syn=perl: diff --git a/deployment/mgagit/templates/group_owned_repo.gl b/deployment/mgagit/templates/group_owned_repo.gl new file mode 100644 index 00000000..14431d6c --- /dev/null +++ b/deployment/mgagit/templates/group_owned_repo.gl @@ -0,0 +1,36 @@ +[% SET maintainer = r.repos.$repo.maintainer %] +repo [% repo %] + RW+ master$ = [% maintainer %] + RW+ distro/ = [% maintainer %] + RW+ topic/ = [% maintainer %] + RW+ refs/tags/ = [% maintainer %] +[% IF r.repos.$repo.lockdown != 'yes' -%] + RW master$ = @mga-<%= @group %> + RW distro/ = @mga-<%= @group %> + RW+ topic/ = @mga-<%= @group %> + RW refs/tags/ = @mga-<%= @group %> + RW master$ = @mga-i18n-committers + RW distro/ = @mga-i18n-committers + RW topic/ = @mga-i18n-committers +[% END -%] + RW+ master$ = @mga-sysadmin + RW+ distro/ = @mga-sysadmin + RW+ topic/ = @mga-sysadmin + RW+ refs/tags/ = @mga-sysadmin + RW+ user/USER/ = @all + R = @all +[% IF r.repos.$repo.noemail -%] + config multimailhook.mailingList = "" +[% ELSE -%] +[% IF r.repos.$repo.mailingList -%] + config multimailhook.mailingList = "[% r.repos.$repo.mailingList %]" +[% ELSE -%] + config multimailhook.mailingList = "<%= @ml %>-commits@ml.mageia.org" +[% END -%] +[% END -%] + config multimailhook.emailDomain = "mageia.org" + config multimailhook.envelopeSender = "root@mageia.org" + config gitweb.description = "[% r.repos.$repo.description %]" +[% IF r.users.$maintainer -%] + config gitweb.owner = "[% r.users.$maintainer.cn.0 %] [[% maintainer %]]" +[% END -%] diff --git a/deployment/mgagit/templates/mgagit.conf b/deployment/mgagit/templates/mgagit.conf new file mode 100644 index 00000000..82b1d66a --- /dev/null +++ b/deployment/mgagit/templates/mgagit.conf @@ -0,0 +1,57 @@ +--- +use_ldap: yes +ldapserver: <%= @ldap_server %> +binddn: <%= @binddn %> +bindpwfile: <%= @bindpwfile %> +pubkey_dir: <%= @gitolite_keydir %> +tmpl_dir: <%= @gitolite_tmpldir %> +gitolite_config: <%= @gitolite_conf %> +run_gitolite: yes +repodef_dir: <%= @reposconf_dir %> +repos_config: + - prefix: infrastructure/repositories + gl_template: repodef_repo + repos: + - name: artwork + maintainer: '@mga-sysadmin' + description: Artwork repository definitions + - name: doc + maintainer: '@mga-sysadmin' + description: Documentation repository definitions + - name: infrastructure + maintainer: '@mga-sysadmin' + description: Infrastructure repository definitions + - name: org + maintainer: '@mga-sysadmin' + description: Organization repository definitions + - name: qa + maintainer: '@mga-sysadmin' + description: QA repository definitions + - name: software + maintainer: '@mga-sysadmin' + description: Software repository definitions + - name: web + maintainer: '@mga-sysadmin' + description: Website repository definitions + - prefix: artwork + gl_template: artwork_repo + git_url: file:///git/infrastructure/repositories/artwork.git + - prefix: doc + gl_template: doc_repo + git_url: file:///git/infrastructure/repositories/doc.git + - prefix: infrastructure + gl_template: infrastructure_repo + git_url: file:///git/infrastructure/repositories/infrastructure.git + - prefix: org + gl_template: org_repo + git_url: file:///git/infrastructure/repositories/org.git + - prefix: qa + gl_template: qa_repo + git_url: file:///git/infrastructure/repositories/qa.git + - prefix: software + gl_template: soft_repo + git_url: file:///git/infrastructure/repositories/software.git + - prefix: web + gl_template: web_repo + git_url: file:///git/infrastructure/repositories/web.git +www_dir: <%= @vhostdir %> diff --git a/deployment/mgagit/templates/repodef_repo.gl b/deployment/mgagit/templates/repodef_repo.gl new file mode 100644 index 00000000..12c946f5 --- /dev/null +++ b/deployment/mgagit/templates/repodef_repo.gl @@ -0,0 +1,8 @@ +repo [% repo %] + RW master$ = [% r.repos.$repo.maintainer %] + RW+ user/USER/ = @all + R = @all + config multimailhook.mailingList = "sysadmin-commits@ml.mageia.org" + config multimailhook.emailDomain = "mageia.org" + config multimailhook.envelopeSender = "root@mageia.org" + config gitweb.description = "[% r.repos.$repo.description %]" diff --git a/deployment/releasekey/manifests/init.pp b/deployment/releasekey/manifests/init.pp index 66f66b60..a3c99526 100644 --- a/deployment/releasekey/manifests/init.pp +++ b/deployment/releasekey/manifests/init.pp @@ -1,7 +1,7 @@ class releasekey { $sign_login = 'releasekey' - $sign_home_dir = "/var/lib/$sign_login" - $sign_keydir = "$sign_home_dir/keys" + $sign_home_dir = "/var/lib/${sign_login}" + $sign_keydir = "${sign_home_dir}/keys" group { $sign_login: } user { $sign_login: @@ -12,16 +12,16 @@ class releasekey { } gnupg::keys{ 'release': - email => "release@$::domain", + email => "release@${::domain}", #FIXME there should be a variable somewhere to change the name of the distribution key_name => 'Mageia Release', login => $sign_login, - batchdir => "$sign_home_dir/batches", + batchdir => "${sign_home_dir}/batches", keydir => $sign_keydir, require => User[$sign_login], } - mga-common::local_script { 'sign_checksums': + mga_common::local_script { 'sign_checksums': content => template('releasekey/sign_checksums'), } } diff --git a/deployment/releasekey/templates/sign_checksums b/deployment/releasekey/templates/sign_checksums index 762dde7b..5edf7e57 100644 --- a/deployment/releasekey/templates/sign_checksums +++ b/deployment/releasekey/templates/sign_checksums @@ -6,6 +6,6 @@ fi directory=$1 cd "$directory" -for chksum in *.md5 *.sha1; do - gpg --homedir "<%= sign_keydir %>" --yes --sign "$chksum" +for chksum in *.md5 *.sha3 *.sha512; do + gpg --homedir "<%= @sign_keydir %>" --yes --sign "$chksum" done diff --git a/deployment/reports/templates/socket.yaml b/deployment/reports/templates/socket.yaml index 075d7a9f..6b0a8b33 100644 --- a/deployment/reports/templates/socket.yaml +++ b/deployment/reports/templates/socket.yaml @@ -1,2 +1,2 @@ --- -socket_path: /var/lib/ii/<%= nick %>/<%= server %>/<%= channel %>/in +socket_path: /var/lib/ii/<%= @nick %>/<%= @server %>/<%= @channel %>/in diff --git a/deployment/repositories/manifests/git.pp b/deployment/repositories/manifests/git.pp deleted file mode 100644 index 46445647..00000000 --- a/deployment/repositories/manifests/git.pp +++ /dev/null @@ -1,11 +0,0 @@ -class repositories::git { - git::repository { '/git/forum': - description => "Reference code for forum.$::domain", - group => 'mga-forum-developers', - } - - git::repository { '/git/initscripts': - description => 'Source for initscripts package', - group => 'mga-packagers-committers', - } -} diff --git a/deployment/repositories/manifests/git_mirror.pp b/deployment/repositories/manifests/git_mirror.pp index 9d213441..7384b5a8 100644 --- a/deployment/repositories/manifests/git_mirror.pp +++ b/deployment/repositories/manifests/git_mirror.pp @@ -1,16 +1,16 @@ class repositories::git_mirror { - file { '/git': - ensure => directory, - } + #file { '/git': + # ensure => directory, + #} - git::mirror { '/git/forum/': - description => "Reference code for forum.$::domain", - source => "git://git.$::domain/forum/", - } + #git::mirror { '/git/forum/': + # description => "Reference code for forum.${::domain}", + # source => "git://git.${::domain}/forum/", + #} - git::mirror { '/git/initscripts/': - description => 'Reference code for Initscripts', - source => "git://git.$::domain/initscripts/", - } + #git::mirror { '/git/initscripts/': + # description => 'Reference code for Initscripts', + # source => "git://git.${::domain}/initscripts/", + #} } diff --git a/deployment/repositories/manifests/sparkleshare.pp b/deployment/repositories/manifests/sparkleshare.pp deleted file mode 100644 index 302e07c1..00000000 --- a/deployment/repositories/manifests/sparkleshare.pp +++ /dev/null @@ -1,11 +0,0 @@ -class repositories::sparkleshare { - $sp_dir = '/git/sparkleshare' - file { $sp_dir: - ensure => directory, - } - - git::repository { "$sp_dir/test": - description => 'Test sparkleshare repository', - group => 'mga-packagers-committers', - } -} diff --git a/deployment/repositories/manifests/subversion.pp b/deployment/repositories/manifests/subversion.pp index 56b6db6d..742efe67 100644 --- a/deployment/repositories/manifests/subversion.pp +++ b/deployment/repositories/manifests/subversion.pp @@ -1,15 +1,19 @@ class repositories::subversion { - Subversion::Repository { - cia_post => true, - cia_ignore_author => '^schedbot$', - } + # Be sure that any mailing list found in commit_mail here whitelists + # "subversion_noreply@ml.mageia.org" as a sender by adding it to + # sender_email in its sympa::list::X configuration in + # deployment/lists/manifests/init.pp subversion::repository { '/svn/adm/': group => 'mga-sysadmin', - commit_mail => ["sysadmin-commits@ml.$::domain"], + commit_mail => ["sysadmin-commits@ml.${::domain}"], syntax_check => ['check_puppet_templates','check_puppet'], - cia_module => 'sysadm', + } + + subversion::repository { '/svn/advisories': + group => 'mga-qa-committers', + commit_mail => ["qa-commits@ml.${::domain}"], } sudo::sudoers_config { 'puppet_update': @@ -22,55 +26,48 @@ class repositories::subversion { subversion::repository { '/svn/org/': group => 'mga-board', - commit_mail => ["board-commits@ml.$::domain"], - cia_post => true, - cia_module => 'org', + commit_mail => ["board-commits@ml.${::domain}"], } subversion::repository { '/svn/soft/': group => 'mga-packagers', - commit_mail => ["soft-commits@ml.$::domain"], + commit_mail => ["soft-commits@ml.${::domain}"], syntax_check => ['check_po'], - cia_module => 'soft', - i18n_mail => ["mageia-i18n@$::domain"], + i18n_mail => ["i18n-reports@ml.${::domain}"], } subversion::repository { '/svn/soft_publish/': group => 'mga-packagers', - commit_mail => ["soft-commits@ml.$::domain"], - cia_post => true, - cia_module => 'soft_publish', + commit_mail => ["soft-commits@ml.${::domain}"], } subversion::repository { '/svn/web/': group => 'mga-web', + commit_mail => ["atelier-commits@ml.${::domain}"], syntax_check => ['check_php'], - cia_module => 'web', } subversion::repository { '/svn/packages/': group => 'mga-packagers-committers', no_binary => true, - commit_mail => ["packages-commits@ml.$::domain"], - cia_module => 'packages', - } - - file { '/svn/binrepos/': - ensure => directory, - mode => '0700', + commit_mail => ["packages-commits@ml.${::domain}"], } - subversion::repository { '/svn/binrepos/cauldron/': - group => 'mga-packagers-committers', - cia_module => 'binrepos', - } - - file { '/svn/binrepos/updates/': - ensure => directory + subversion::repository { '/svn/test-irker/': + group => 'mga-packagers', + no_binary => true, + commit_mail => ["tmb@${::domain}"], + irker_conf => { + project => 'mageia', + repo => 'testrepo', + tinyifier => 'https://is.gd/create.php?format=simple&url=', + urlprefix => "https://svnweb.${::domain}/%(repo)?view=revision&revision=", + channels => '{irc://chat.freenode.net/commits, irc://chat.freenode.net/test-irker}', + }, } - subversion::repository { '/svn/binrepos/updates/1/': - group => 'mga-packagers-committers', - cia_module => 'binrepos_1', + subversion::repository { '/svn/treasurer/': + group => 'mga-treasurer', + commit_mail => ["treasurer-commits@ml.${::domain}"], } } diff --git a/deployment/repositories/manifests/svn_mirror.pp b/deployment/repositories/manifests/svn_mirror.pp index 570b3326..d71e896d 100644 --- a/deployment/repositories/manifests/svn_mirror.pp +++ b/deployment/repositories/manifests/svn_mirror.pp @@ -4,11 +4,13 @@ class repositories::svn_mirror { } subversion::mirror_repository { - '/svn/adm/': source => "svn://svn.$::domain/svn/adm/"; - '/svn/soft/': source => "svn://svn.$::domain/svn/soft/"; - '/svn/web/': source => "svn://svn.$::domain/svn/web/"; - '/svn/packages/': source => "svn://svn.$::domain/svn/packages/"; - '/svn/org/': source => "svn://svn.$::domain/svn/org/"; + '/svn/adm/': source => "svn://svn.${::domain}/svn/adm/"; + '/svn/advisories/':source => "svn://svn.${::domain}/svn/advisories/"; + '/svn/soft/': source => "svn://svn.${::domain}/svn/soft/"; + '/svn/web/': source => "svn://svn.${::domain}/svn/web/"; + '/svn/packages/': source => "svn://svn.${::domain}/svn/packages/"; + '/svn/org/': source => "svn://svn.${::domain}/svn/org/"; + '/svn/treasurer/': source => "svn://svn.${::domain}/svn/treasurer/"; } # no binrepos, too big to mirror diff --git a/deployment/repositories/templates/puppet_update.sudoers b/deployment/repositories/templates/puppet_update.sudoers index 154bc9c1..42235771 100644 --- a/deployment/repositories/templates/puppet_update.sudoers +++ b/deployment/repositories/templates/puppet_update.sudoers @@ -1,2 +1 @@ %mga-sysadmin ALL= NOPASSWD: /usr/bin/svn update -q --non-interactive --accept theirs-full /etc/puppet - diff --git a/deployment/shadow/files/login.defs b/deployment/shadow/files/login.defs deleted file mode 100644 index 4d966b60..00000000 --- a/deployment/shadow/files/login.defs +++ /dev/null @@ -1,193 +0,0 @@ -# *REQUIRED* -# Directory where mailboxes reside, _or_ name of file, relative to the -# home directory. If you _do_ define both, MAIL_DIR takes precedence. -# QMAIL_DIR is for Qmail -# -#QMAIL_DIR Maildir -MAIL_DIR /var/spool/mail -#MAIL_FILE .mail - -# Password aging controls: -# -# PASS_MAX_DAYS Maximum number of days a password may be used. -# PASS_MIN_DAYS Minimum number of days allowed between password changes. -# PASS_MIN_LEN Minimum acceptable password length. -# PASS_WARN_AGE Number of days warning given before a password expires. -# -PASS_MAX_DAYS 99999 -PASS_MIN_DAYS 0 -#PASS_MIN_LEN 5 -PASS_WARN_AGE 7 - -# -# Min/max values for automatic uid selection in useradd -# -UID_MIN 500 -UID_MAX 2000 - -# -# Min/max values for automatic gid selection in groupadd -# -GID_MIN 500 -GID_MAX 2000 - -# -# If defined, this command is run when removing a user. -# It should remove any at/cron/print jobs etc. owned by -# the user to be removed (passed as the first argument). -# -# USERDEL_CMD /usr/sbin/userdel_local - -# -# If useradd should create home directories for users by default -# On RH systems, we do. This option is ORed with the -m flag on -# useradd command line. -# -CREATE_HOME yes - -# -# The password hashing method and iteration count to use for group -# passwords that may be set with gpasswd(1). -# -CRYPT_PREFIX $2a$ -CRYPT_ROUNDS 8 - -# -# Whether to use tcb password shadowing scheme. Use 'yes' if using -# tcb and 'no' if using /etc/shadow -# -USE_TCB no - -# -# Whether newly created tcb-style shadow files should be readable by -# group "auth". -# -TCB_AUTH_GROUP yes - -# -# Whether useradd should create symlinks rather than directories under -# /etc/tcb for newly created accounts with UIDs over 1000. See tcb(5) -# for information on why this may be needed. -# -TCB_SYMLINKS no - -# -# Delay in seconds before being allowed another attempt after a login failure -# -FAIL_DELAY 3 - -# -# Enable display of unknown usernames when login failures are recorded. -# -LOG_UNKFAIL_ENAB no - -# -# Enable logging of successful logins -# -LOG_OK_LOGINS no - -# -# Enable "syslog" logging of su activity - in addition to sulog file logging. -# SYSLOG_SG_ENAB does the same for newgrp and sg. -# -SYSLOG_SU_ENAB yes -SYSLOG_SG_ENAB yes - -# -# If defined, either full pathname of a file containing device names or -# a ":" delimited list of device names. Root logins will be allowed only -# upon these devices. -# -CONSOLE /etc/securetty -#CONSOLE console:tty01:tty02:tty03:tty04 - -# -# If defined, the command name to display when running "su -". For -# example, if this is defined as "su" then a "ps" will display the -# command is "-su". If not defined, then "ps" would display the -# name of the shell actually being run, e.g. something like "-sh". -# -SU_NAME su - -# -# If defined, file which inhibits all the usual chatter during the login -# sequence. If a full pathname, then hushed mode will be enabled if the -# user's name or shell are found in the file. If not a full pathname, then -# hushed mode will be enabled if the file exists in the user's home directory. -# -HUSHLOGIN_FILE .hushlogin -#HUSHLOGIN_FILE /etc/hushlogins - -# -# *REQUIRED* The default PATH settings, for superuser and normal users. -# -# (they are minimal, add the rest in the shell startup files) -ENV_SUPATH PATH=/sbin:/bin:/usr/sbin:/usr/bin -ENV_PATH PATH=/bin:/usr/bin - -# -# Terminal permissions -# -# TTYGROUP Login tty will be assigned this group ownership. -# TTYPERM Login tty will be set to this permission. -# -# If you have a "write" program which is "setgid" to a special group -# which owns the terminals, define TTYGROUP to the group number and -# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign -# TTYPERM to either 622 or 600. -# -TTYGROUP tty -TTYPERM 0600 - -# -# Login configuration initializations: -# -# ERASECHAR Terminal ERASE character ('\010' = backspace). -# KILLCHAR Terminal KILL character ('\025' = CTRL/U). -# UMASK Default "umask" value. -# ULIMIT Default "ulimit" value. -# -# The ERASECHAR and KILLCHAR are used only on System V machines. -# The ULIMIT is used only if the system supports it. -# (now it works with setrlimit too; ulimit is in 512-byte units) -# -# Prefix these values with "0" to get octal, "0x" to get hexadecimal. -# -ERASECHAR 0177 -KILLCHAR 025 -UMASK 022 -#ULIMIT 2097152 - -# -# Max number of login retries if password is bad -# -LOGIN_RETRIES 5 - -# -# Max time in seconds for login -# -LOGIN_TIMEOUT 60 - -# -# Which fields may be changed by regular users using chfn - use -# any combination of letters "frwh" (full name, room number, work -# phone, home phone). If not defined, no changes are allowed. -# For backward compatibility, "yes" = "rwh" and "no" = "frwh". -# -CHFN_RESTRICT rwh - -# -# Should login be allowed if we can't cd to the home directory? -# Default in no. -# -DEFAULT_HOME yes - -# -# Enable setting of the umask group bits to be the same as owner bits -# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is -# the same as gid, and username is the same as the primary group name. -# -# This also enables userdel to remove user groups if no members exist. -# -USERGROUPS_ENAB yes - diff --git a/deployment/shadow/manifests/init.pp b/deployment/shadow/manifests/init.pp index 083f86ba..c24c36bf 100644 --- a/deployment/shadow/manifests/init.pp +++ b/deployment/shadow/manifests/init.pp @@ -1,8 +1,23 @@ class shadow { - file { '/etc/login.defs': + include stdlib + + $login_defs = '/etc/login.defs' + + file { $login_defs: owner => 'root', group => 'shadow', mode => '0640', - source => 'puppet:///modules/shadow/login.defs', + } + + file_line { 'uid_max': + path => $login_defs, + line => 'UID_MAX 2000', + match => '^UID_MAX\s+', + } + + file_line { 'gid_max': + path => $login_defs, + line => 'GID_MAX 2000', + match => '^GID_MAX\s+', } } diff --git a/deployment/softwarekey/manifests/init.pp b/deployment/softwarekey/manifests/init.pp index 41102b4e..b2c4bcb2 100644 --- a/deployment/softwarekey/manifests/init.pp +++ b/deployment/softwarekey/manifests/init.pp @@ -1,24 +1,23 @@ class softwarekey { $sign_login = 'softwarekey' - $sign_home_dir = "/var/lib/$sign_login" - $sign_keydir = "$sign_home_dir/keys" + $sign_home_dir = "/var/lib/${sign_login}" + $sign_keydir = "${sign_home_dir}/keys" group { $sign_login: } user { $sign_login: - comment => 'System user to sign Mageia Software', home => $sign_home_dir, gid => $sign_login, require => Group[$sign_login], } gnupg::keys{ 'software': - email => "software@$::domain", + email => "software@${::domain}", #FIXME there should be a variable somewhere to change the # name of the distribution key_name => 'Mageia Software', login => $sign_login, - batchdir => "$sign_home_dir/batches", + batchdir => "${sign_home_dir}/batches", keydir => $sign_keydir, require => User[$sign_login], } diff --git a/deployment/tld_redirections/manifests/init.pp b/deployment/tld_redirections/manifests/init.pp index 92215e86..18db541c 100644 --- a/deployment/tld_redirections/manifests/init.pp +++ b/deployment/tld_redirections/manifests/init.pp @@ -1,24 +1,24 @@ class tld_redirections { define domain { - dns::zone { "mageia.$name": } + dns::zone { "mageia.${name}": } } define redirection($managed_dns = false) { if ($managed_dns) { - @@tld_redirections::domain { $name: } + @@tld_redirections::domain { $name: } } - apache::vhost_redirect { "mageia.$name": - url => "http://www.mageia.org/?fromtld=$name" + apache::vhost_redirect { "mageia.${name}": + url => "https://www.${::domain}/?fromtld=${name}" } - apache::vhost_redirect { "www.mageia.$name": - url => "http://www.mageia.org/?fromtld=$name" + apache::vhost_redirect { "www.mageia.${name}": + url => "https://www.${::domain}/?fromtld=${name}" } } - # domaine owned by Florin Catalin Russen + # domain owned by Florin Catalin Russen redirection { "ro": } # domain owned by the association diff --git a/deployment/websites/manifests/archives.pp b/deployment/websites/manifests/archives.pp new file mode 100644 index 00000000..825e082b --- /dev/null +++ b/deployment/websites/manifests/archives.pp @@ -0,0 +1,20 @@ +class websites::archives { + include websites::base + $vhost = "archives.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" + $git_location = "git://git.${::domain}/web/archives" + + apache::vhost::base { $vhost: + location => $vhostdir, + } + + apache::vhost::base { "ssl_${vhost}": + vhost => $vhost, + use_ssl => true, + location => $vhostdir, + } + + git::snapshot { $vhostdir: + source => $git_location, + } +} diff --git a/deployment/websites/manifests/base.pp b/deployment/websites/manifests/base.pp index c45ca431..1c2dbc64 100644 --- a/deployment/websites/manifests/base.pp +++ b/deployment/websites/manifests/base.pp @@ -1,3 +1,9 @@ class websites::base { $webdatadir = '/var/www/vhosts' + file { $webdatadir: + ensure => directory, + mode => '0755', + owner => root, + group => root + } } diff --git a/deployment/websites/manifests/doc.pp b/deployment/websites/manifests/doc.pp index 63ba9d45..01474af2 100644 --- a/deployment/websites/manifests/doc.pp +++ b/deployment/websites/manifests/doc.pp @@ -1,20 +1,20 @@ class websites::doc { include websites::base - $vhost = "doc.$::domain" - $vhostdir = "$websites::base::webdatadir/$vhost" - $svn_location = "svn://svn.$::domain/svn/web/doc/" + $vhost = "doc.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" + $git_location = "git://git.${::domain}/web/doc" apache::vhost::base { $vhost: location => $vhostdir, } - apache::vhost::base { "ssl_$vhost": + apache::vhost::base { "ssl_${vhost}": vhost => $vhost, use_ssl => true, location => $vhostdir, } - subversion::snapshot { $vhostdir: - source => $svn_location, + git::snapshot { $vhostdir: + source => $git_location, } } diff --git a/deployment/websites/manifests/forum_proxy.pp b/deployment/websites/manifests/forum_proxy.pp index 06e9f433..bd8f1fc1 100644 --- a/deployment/websites/manifests/forum_proxy.pp +++ b/deployment/websites/manifests/forum_proxy.pp @@ -1,13 +1,13 @@ class websites::forum_proxy { - $web_domain = "forums.$::domain" + $web_domain = "forums.${::domain}" apache::vhost::reverse_proxy { $web_domain: - url => "http://$web_domain/", + url => "http://${web_domain}/", } - apache::vhost::reverse_proxy { "ssl_$web_domain": + apache::vhost::reverse_proxy { "ssl_${web_domain}": vhost => $web_domain, use_ssl => true, - url => "http://$web_domain/", + url => "http://${web_domain}/", } } diff --git a/deployment/websites/manifests/git.pp b/deployment/websites/manifests/git.pp new file mode 100644 index 00000000..e357dfb2 --- /dev/null +++ b/deployment/websites/manifests/git.pp @@ -0,0 +1,10 @@ +class websites::git { + apache::vhost_redirect { "git.${::domain}": + url => "https://gitweb.${::domain}/", + } + apache::vhost_redirect { "ssl_git.${::domain}": + use_ssl => true, + vhost => "git.${::domain}", + url => "https://gitweb.${::domain}/", + } +} diff --git a/deployment/websites/manifests/hugs.pp b/deployment/websites/manifests/hugs.pp index 49fe6ac7..95246464 100644 --- a/deployment/websites/manifests/hugs.pp +++ b/deployment/websites/manifests/hugs.pp @@ -1,15 +1,15 @@ class websites::hugs { include websites::base - $vhostdir = "$websites::base::webdatadir/hugs.$::domain" - $svn_location = "svn://svn.$::domain/svn/web/hugs/public/" + $vhostdir = "${websites::base::webdatadir}/hugs.${::domain}" + $git_location = "git://git.${::domain}/web/hugs" - apache::vhost::base { "hugs.$::domain": + apache::vhost::base { "hugs.${::domain}": location => $vhostdir, } - subversion::snapshot { $vhostdir: - source => $svn_location + git::snapshot { $vhostdir: + source => $git_location } package { 'php-exif': } diff --git a/deployment/websites/manifests/meetbot.pp b/deployment/websites/manifests/meetbot.pp new file mode 100644 index 00000000..04bbcf70 --- /dev/null +++ b/deployment/websites/manifests/meetbot.pp @@ -0,0 +1,14 @@ +# We should rather have a meetbot module used to deploy +# it, setup backups and this website +class websites::meetbot { + $vhost = "meetbot.${::domain}" + $vhostdir = "/home/irc_bots/meetings/" + + apache::vhost::other_app { "meetbot.${::domain}": + vhost_file => 'websites/vhost_meetbot.conf', + } + + file { $vhostdir: + ensure => directory, + } +} diff --git a/deployment/websites/manifests/nav.pp b/deployment/websites/manifests/nav.pp index 587abe0d..84323c26 100644 --- a/deployment/websites/manifests/nav.pp +++ b/deployment/websites/manifests/nav.pp @@ -1,20 +1,27 @@ class websites::nav { include websites::base - $vhost = "nav.$::domain" - $vhostdir = "$websites::base::webdatadir/$vhost" - $svn_location = "svn://svn.$::domain/svn/web/nav/" + $vhost = "nav.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" + $git_location = "git://git.${::domain}/web/nav" apache::vhost::base { $vhost: location => $vhostdir, } - apache::vhost::base { "ssl_$vhost": + apache::vhost::base { "ssl_${vhost}": vhost => $vhost, use_ssl => true, location => $vhostdir, } - subversion::snapshot { $vhostdir: - source => $svn_location, + git::snapshot { $vhostdir: + source => $git_location, + } + + file { "${vhostdir}/var/tmp/cache": + ensure => directory, + mode => '0660', + group => $apache::var::apache_group, + require => Git::Snapshot[$vhostdir], } } diff --git a/deployment/websites/manifests/perl.pp b/deployment/websites/manifests/perl.pp index 041bde63..2b4849fb 100644 --- a/deployment/websites/manifests/perl.pp +++ b/deployment/websites/manifests/perl.pp @@ -1,10 +1,10 @@ class websites::perl { include websites::base - $vhost = "perl.$::domain" - $vhostdir = "$websites::base::webdatadir/$vhost" + $vhost = "perl.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" $statsdir = "${vhostdir}/stats" - $login = 'pkgcpan' - $homedir = "/var/lib/$login" + $login = 'pkgcpan' + $homedir = "/var/lib/${login}" user { $login: managehome => true, @@ -26,29 +26,29 @@ class websites::perl { cron { 'update cpanpkg': hour => 23, - minute => 0, + minute => 0, require => Package['perl-Module-Packaged-Generator'], - command => "pkgcpan -q -f $vhostdir/cpan_Mageia.db -d Mageia && chmod 644 $vhostdir/cpan_Mageia.db", + command => "pkgcpan -q -f ${vhostdir}/cpan_Mageia.db -d Mageia && chmod 644 ${vhostdir}/cpan_Mageia.db", user => $login, } - file { "$vhostdir/cpan_Mageia.db": + file { "${vhostdir}/cpan_Mageia.db": owner => $login, group => $login, } file { $statsdir: - ensure => directory, - owner => $login, - group => $login, + ensure => directory, + owner => $login, + group => $login, } - # http://www.mageia.org/pipermail/mageia-sysadm/2012-March/004337.html + # https://www.mageia.org/pipermail/mageia-sysadm/2012-March/004337.html cron { 'update pkgcpan stats': - hour => 23, - minute => 30, - require => [ Package['magpie'], File[$statsdir] ], - command => "magpie webstatic -qq -d $statsdir", - user => $login, + hour => 23, + minute => 30, + require => [ Package['magpie'], File[$statsdir] ], + command => "magpie webstatic -qq -d ${statsdir}", + user => $login, } } diff --git a/deployment/websites/manifests/releases.pp b/deployment/websites/manifests/releases.pp index 1d52201c..2b25c8ec 100644 --- a/deployment/websites/manifests/releases.pp +++ b/deployment/websites/manifests/releases.pp @@ -1,22 +1,22 @@ class websites::releases { include websites::base - $vhost = "releases.$::domain" - $vhostdir = "$websites::base::webdatadir/$vhost" - $svn_location = "svn://svn.$::domain/svn/web/releases/" + $vhost = "releases.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" + $git_location = "git://git.${::domain}/web/releases" apache::vhost::base { $vhost: location => $vhostdir, options => [ 'FollowSymLinks' ], } - apache::vhost::base { "ssl_$vhost": + apache::vhost::base { "ssl_${vhost}": vhost => $vhost, use_ssl => true, location => $vhostdir, options => [ 'FollowSymLinks' ], } - subversion::snapshot { $vhostdir: - source => $svn_location, + git::snapshot { $vhostdir: + source => $git_location, } } diff --git a/deployment/websites/manifests/start.pp b/deployment/websites/manifests/start.pp index e4c383ce..9d5b77e5 100644 --- a/deployment/websites/manifests/start.pp +++ b/deployment/websites/manifests/start.pp @@ -1,6 +1,11 @@ class websites::start { include websites::base - apache::vhost_redirect { "start.$::domain": - url => "http://www.mageia.org/community/", + apache::vhost_redirect { "start.${::domain}": + url => "https://www.${::domain}/community/", + } + apache::vhost_redirect { "ssl_start.${::domain}": + use_ssl => true, + vhost => "start.${::domain}", + url => "https://www.${::domain}/community/", } } diff --git a/deployment/websites/manifests/static.pp b/deployment/websites/manifests/static.pp index 749f72b0..66711329 100644 --- a/deployment/websites/manifests/static.pp +++ b/deployment/websites/manifests/static.pp @@ -1,8 +1,8 @@ class websites::static { include websites::base - $vhostdir = "$websites::base::webdatadir/static.$::domain" + $vhostdir = "${websites::base::webdatadir}/static.${::domain}" - apache::vhost::other_app { "static.$::domain": + apache::vhost::other_app { "static.${::domain}": vhost_file => 'websites/vhost_static.conf', } @@ -10,7 +10,7 @@ class websites::static { ensure => directory, } - subversion::snapshot { "$vhostdir/g": - source => "svn://svn.$::domain/svn/web/www/trunk/g/", + git::snapshot { "${vhostdir}": + source => "git://git.${::domain}/web/www", } } diff --git a/deployment/websites/manifests/svn.pp b/deployment/websites/manifests/svn.pp index 650442dc..973c012d 100644 --- a/deployment/websites/manifests/svn.pp +++ b/deployment/websites/manifests/svn.pp @@ -1,5 +1,10 @@ class websites::svn { - apache::vhost_redirect { "svn.$::domain": - url => "http://svnweb.$::domain/", + apache::vhost_redirect { "svn.${::domain}": + url => "https://svnweb.${::domain}/", + } + apache::vhost_redirect { "ssl_svn.${::domain}": + use_ssl => true, + vhost => "svn.${::domain}", + url => "https://svnweb.${::domain}/", } } diff --git a/deployment/websites/manifests/www.pp b/deployment/websites/manifests/www.pp index 03498084..08c232f2 100644 --- a/deployment/websites/manifests/www.pp +++ b/deployment/websites/manifests/www.pp @@ -1,51 +1,64 @@ class websites::www { include websites::base - $vhost = "www.$::domain" - $vhostdir = "$websites::base::webdatadir/$vhost" - $svn_location = "svn://svn.$::domain/svn/web/www/trunk" + $vhost = "www.${::domain}" + $vhostdir = "${websites::base::webdatadir}/${vhost}" + $git_location = "git://git.${::domain}/web/www" + include apache::var include apache::mod::php - include apache::mod::geoip # for mailman reverse proxy, on ssl include apache::mod::proxy include apache::mod::ssl - subversion::snapshot { $vhostdir: - source => $svn_location, + git::snapshot { $vhostdir: + source => $git_location, } - file { "$vhostdir/var/tmp/cache": - ensure => directory, - group => $apache::base::apache_group, - mode => '0660', + file { [ "${vhostdir}/var", + "${vhostdir}/var/tmp", + "${vhostdir}/var/tmp/cache" ] : + ensure => directory, + group => $apache::var::apache_group, + mode => '0660', + require => Git::Snapshot[$vhostdir], + } + + file { [ "${vhostdir}/_nav", + "${vhostdir}/_nav/var", + "${vhostdir}/_nav/var/tmp", + "${vhostdir}/_nav/var/tmp/cache" ] : + ensure => directory, + group => $apache::var::apache_group, + mode => '0660', + require => Git::Snapshot[$vhostdir], } apache::vhost::base { $vhost: content => template('websites/vhost_www.conf', - 'websites/vhost_proxy_mailman.conf'), + 'websites/vhost_www_rewrite.conf'), location => $vhostdir, options => ['FollowSymLinks'], } - apache::vhost::base { "ssl_$vhost": + apache::vhost::base { "ssl_${vhost}": use_ssl => true, vhost => $vhost, content => template('websites/vhost_www.conf', - 'websites/vhost_proxy_mailman_ssl.conf'), + 'websites/vhost_www_rewrite.conf'), location => $vhostdir, options => ['FollowSymLinks'], } - apache::vhost_redirect { $::domain: - url => "http://www.$::domain/", + apache::vhost_redirect { "${::domain}": + url => "https://www.${::domain}/", } - apache::vhost_redirect { "ssl_$::domain": + apache::vhost_redirect { "ssl_${::domain}": use_ssl => true, - vhost => $::domain, - url => "https://www.$::domain/", + vhost => "${::domain}", + url => "https://www.${::domain}/", } - package { ['php-mbstring', 'php-mcrypt', 'php-gettext', 'php-geoip']: } + package { ['php-mbstring', 'php-mcrypt', 'php-gettext']: } } diff --git a/deployment/websites/templates/vhost_meetbot.conf b/deployment/websites/templates/vhost_meetbot.conf new file mode 100644 index 00000000..40a0f92a --- /dev/null +++ b/deployment/websites/templates/vhost_meetbot.conf @@ -0,0 +1,36 @@ +<VirtualHost *:80> + ServerAdmin sysadm@mageia.org + ServerName meetbot.<%= @domain %> + DocumentRoot <%= scope.lookupvar("websites::meetbot::vhostdir") %> + + CustomLog /var/log/httpd/access_meetbot_log combined + ErrorLog /var/log/httpd/error_meetbot_log + <Directory <%= scope.lookupvar("websites::meetbot::vhostdir") %>> + Allow from all + <IfModule mod_authz_core.c> + Require all granted + </IfModule> + Options +Indexes + IndexIgnore .htaccess *.bak *~ *.txt *.log.html + </Directory> +</VirtualHost> + +<VirtualHost *:443> + ServerAdmin sysadm@mageia.org + ServerName meetbot.<%= @domain %> + DocumentRoot <%= scope.lookupvar("websites::meetbot::vhostdir") %> + + CustomLog /var/log/httpd/access_meetbot_log combined + ErrorLog /var/log/httpd/error_meetbot_log + +<%= scope.function_template(["apache/vhost_ssl.conf"]) %> + + <Directory <%= scope.lookupvar("websites::meetbot::vhostdir") %>> + Allow from all + <IfModule mod_authz_core.c> + Require all granted + </IfModule> + Options +Indexes + IndexIgnore .htaccess *.bak *~ *.txt *.log.html + </Directory> +</VirtualHost> diff --git a/deployment/websites/templates/vhost_proxy_mailman.conf b/deployment/websites/templates/vhost_proxy_mailman.conf deleted file mode 100644 index ef447f9c..00000000 --- a/deployment/websites/templates/vhost_proxy_mailman.conf +++ /dev/null @@ -1,14 +0,0 @@ - -ProxyRequests Off -ProxyPreserveHost On - -<Proxy *> - Order deny,allow - Allow from all -</Proxy> - -<% for u in ['/mailman/','/pipermail/'] %> -ProxyPass <%= u %> http://ryu.zarb.org<%= u %> -ProxyPassReverse <%= u %> http://ryu.zarb.org<%= u %> - -<% end %> diff --git a/deployment/websites/templates/vhost_proxy_mailman_ssl.conf b/deployment/websites/templates/vhost_proxy_mailman_ssl.conf deleted file mode 100644 index e5fcfbe1..00000000 --- a/deployment/websites/templates/vhost_proxy_mailman_ssl.conf +++ /dev/null @@ -1,16 +0,0 @@ - -ProxyRequests Off -ProxyPreserveHost On - -<Proxy *> - Order deny,allow - Allow from all -</Proxy> - -SSLProxyEngine On - -<% for u in ['/mailman/','/pipermail/'] %> -ProxyPass <%= u %> https://ryu.zarb.org<%= u %> -ProxyPassReverse <%= u %> https://ryu.zarb.org<%= u %> - -<% end %> diff --git a/deployment/websites/templates/vhost_static.conf b/deployment/websites/templates/vhost_static.conf index 6521b469..fcadc425 100644 --- a/deployment/websites/templates/vhost_static.conf +++ b/deployment/websites/templates/vhost_static.conf @@ -1,7 +1,7 @@ <VirtualHost *:80> - ServerName static.<%= domain %> + ServerName static.<%= @domain %> - DocumentRoot <%= vhostdir %> + DocumentRoot <%= scope.lookupvar("websites::static::vhostdir") %> CustomLog /var/log/httpd/static_log combined ErrorLog /var/log/httpd/error_static_log @@ -19,10 +19,63 @@ AddOutputFilterByType DEFLATE application/json text/javascript application/javascript application/x-javascript <Location /> + Deny from all + </Location> + + <Location /g/> + Allow from all + </Location> + + <Directory <%= scope.lookupvar("websites::static::vhostdir") %>> + Order deny,allow + Deny from All + AllowOverride None + </Directory> + + <Directory <%= scope.lookupvar("websites::static::vhostdir") %>/g> + Order deny,allow + Allow from All + AllowOverride None + </Directory> +</VirtualHost> + +<VirtualHost *:443> + ServerName static.<%= @domain %> + + DocumentRoot <%= scope.lookupvar("websites::static::vhostdir") %> + CustomLog /var/log/httpd/static_log combined + ErrorLog /var/log/httpd/error_static_log + +<%= scope.function_template(["apache/vhost_ssl.conf"]) %> + + FileETag none + Header unset ETag + ExpiresActive On + ExpiresByType text/css "access plus 1 month" + ExpiresByType image/gif "access plus 2 months" + ExpiresByType image/png "access plus 2 months" + ExpiresByType image/jpeg "access plus 2 months" + ExpiresByType image/x-icon "access plus 2 months" + ExpiresByType application/x-javascript "access plus 1 month" + ExpiresByType text/javascript "access plus 1 month" + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css + AddOutputFilterByType DEFLATE application/json text/javascript application/javascript application/x-javascript + + <Location /> + Deny from all + </Location> + + <Location /g/> Allow from all </Location> - <Directory <%= vhostdir %>> + <Directory <%= scope.lookupvar("websites::static::vhostdir") %>> + Order deny,allow + Deny from All + AllowOverride None + </Directory> + + <Directory <%= scope.lookupvar("websites::static::vhostdir") %>/g> Order deny,allow Allow from All AllowOverride None diff --git a/deployment/websites/templates/vhost_www.conf b/deployment/websites/templates/vhost_www.conf index 9d00828d..399681be 100644 --- a/deployment/websites/templates/vhost_www.conf +++ b/deployment/websites/templates/vhost_www.conf @@ -1,13 +1,13 @@ Redirect /wiki https://wiki.mageia.org/# -# Everything under /g/ is static content to be served by a seconday host +# Everything under /g/ is static content to be served by a secondary host RewriteEngine On -RewriteRule ^g/(.+)$ http://static.mageia.org/g/$1 [R,L,QSA] - -# ProxyPreserveHost On is in another file -ProxyPass /old-wiki/ http://ryu.zarb.org/wiki -ProxyPassReverse /old-wiki/ http://ryu.zarb.org/wiki +RewriteRule ^g/(.+)$ https://static.mageia.org/g/$1 [R,L,QSA] ErrorDocument 404 /404.php php_value short_open_tag false + +# switch all to https +RewriteCond %{HTTPS} !=on +RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] diff --git a/deployment/websites/templates/vhost_www_rewrite.conf b/deployment/websites/templates/vhost_www_rewrite.conf new file mode 100644 index 00000000..c7bb2fd5 --- /dev/null +++ b/deployment/websites/templates/vhost_www_rewrite.conf @@ -0,0 +1,22 @@ +RewriteEngine On +RewriteRule ^/mailman/listinfo/mageia-annnounce https://ml.mageia.org/l/info/announce [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-artwork https://ml.mageia.org/l/info/atelier-discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-bugsquad https://ml.mageia.org/l/info/bugsquad-discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-dev https://ml.mageia.org/l/info/dev [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-discuss https://ml.mageia.org/l/info/discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-i18n https://ml.mageia.org/l/info/i18n-discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-marketing https://ml.mageia.org/l/info/atelier-discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-sysadm https://ml.mageia.org/l/info/sysadmin-discuss [R=301,L] +RewriteRule ^/mailman/listinfo/mageia-webteam https://ml.mageia.org/l/info/atelier-discuss [R=301,L] +RewriteRule ^/mailman https://ml.mageia.org/ [R=301,L] + +RewriteRule ^/pipermail/mageia-announce/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-announce/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-artwork/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-artwork/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-bugsquad/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-bugsquad/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-dev/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-dev/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-discuss/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-discuss/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-i18n/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-i18n/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-marketing/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-marketing/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-sysadm/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-sysadm/$1 [R=301,L] +RewriteRule ^/pipermail/mageia-webteam/?(.*)$ https://archives.mageia.org/zarb-ml/mageia-webteam/$1 [R=301,L] +RewriteRule ^/pipermail https://archives.mageia.org/zarb-ml/ [R=301,L] diff --git a/deployment/wikis/manifests/init.pp b/deployment/wikis/manifests/init.pp index 901c5953..c34b06d5 100644 --- a/deployment/wikis/manifests/init.pp +++ b/deployment/wikis/manifests/init.pp @@ -9,22 +9,22 @@ class wikis { vhost => false, } - subversion::snapshot { $wikis_templates: - source => "svn://svn.$::domain/svn/web/templates/mediawiki" + git::snapshot { $wikis_templates: + source => "git://git.${::domain}/web/templates/mediawiki" } - $wiki_languages = [ 'en','de' ] + $wiki_languages = [ 'en','de', 'fr' ] mediawiki::instance { $wiki_languages: title => 'Mageia wiki', wiki_settings => template('wikis/wiki_settings'), - skinsdir => "$wikis_templates/skins", + skinsdir => "${wikis_templates}/skins", } - apache::vhost::redirect_ssl { "wiki.$::domain": } + apache::vhost::redirect_ssl { "wiki.${::domain}": } - apache::vhost::base { "ssl_wiki.$::domain": + apache::vhost::base { "ssl_wiki.${::domain}": use_ssl => true, - vhost => "wiki.$::domain", + vhost => "wiki.${::domain}", content => template('wikis/wiki_vhost.conf'), } } diff --git a/deployment/wikis/templates/wiki_settings b/deployment/wikis/templates/wiki_settings index d2c1b199..ec6e647d 100644 --- a/deployment/wikis/templates/wiki_settings +++ b/deployment/wikis/templates/wiki_settings @@ -7,12 +7,13 @@ $wgGroupPermissions['*']['createpage'] = false; $wgGroupPermissions['*']['writeapi'] = false; $wgGroupPermissions['*']['createaccount'] = false; $wgGroupPermissions['user']['edit'] = true; +$wgGroupPermissions['*']['autocreateaccount'] = true; $wgScriptPath = "/mw-$wgLanguageCode"; $wgArticlePath = "/$wgLanguageCode/$1"; $wgUsePathInfo = true; $wgStylePath = "$wgScriptPath/skins"; -$wgStyleDirectory = '<%= wikis_templates %>/skins'; +$wgStyleDirectory = '<%= @wikis_templates %>/skins'; $wgLogo = ""; $wgDefaultSkin = 'vector'; $wgFavicon = '/mw-en/skins/cavendish/favicon.png'; @@ -31,3 +32,15 @@ $wgExtraNamespaces[NS_QA_PROCEDURE] = 'QA_procedure'; $wgExtraNamespaces[NS_QA_PROCEDURE_TALK] = 'QA_procedure_Talk'; $wgContentNamespaces[] = NS_QA_PROCEDURE; $wgNamespacesToBeSearchedDefault[NS_QA_PROCEDURE] = true; + +wfLoadExtension('Nuke'); +wfLoadExtension('SpamBlacklist'); +wfLoadExtension('TitleBlacklist'); +$wgTitleBlacklistSources = array( + array( + 'type' => 'localpage', + 'src' => 'MediaWiki:Titleblacklist' + ) +); + +# $wgReadOnly = 'This wiki is currently read-only'; diff --git a/deployment/wikis/templates/wiki_vhost.conf b/deployment/wikis/templates/wiki_vhost.conf index e8e4fd6d..4e1355bc 100644 --- a/deployment/wikis/templates/wiki_vhost.conf +++ b/deployment/wikis/templates/wiki_vhost.conf @@ -1,18 +1,19 @@ -<Directory <%= wikis_root %>> +<Directory <%= @wikis_root %>> Options +FollowSymLinks </Directory> RewriteEngine On RewriteRule ^/?$ /en/ [R] +Alias /robots.txt <%= @wikis_root %>/robots.txt + <%- for lang in wiki_languages -%> -<Directory <%= wikis_root %>/<%= lang %>/images> +<Directory <%= @wikis_root %>/<%= lang %>/images> SetHandler default-handler </Directory> -Alias /<%= lang %> <%= wikis_root %>/<%= lang %>/index.php -Alias /mw-<%= lang %> <%= wikis_root %>/<%= lang %> +Alias /<%= lang %> <%= @wikis_root %>/<%= lang %>/index.php +Alias /mw-<%= lang %> <%= @wikis_root %>/<%= lang %> <%- end -%> - diff --git a/external/.gitignore b/external/.gitignore new file mode 100644 index 00000000..f6289ea5 --- /dev/null +++ b/external/.gitignore @@ -0,0 +1 @@ +hiera diff --git a/external/concat/manifests/fragment.pp b/external/concat/manifests/fragment.pp index 890d43a4..ba546766 100644 --- a/external/concat/manifests/fragment.pp +++ b/external/concat/manifests/fragment.pp @@ -1,5 +1,5 @@ # Puts a file fragment into a directory previous setup using concat -# +# # OPTIONS: # - target The file that these fragments belong to # - content If present puts the content into the file @@ -31,17 +31,17 @@ define concat::fragment($target, $content='', $source='', $order=10, $ensure = " } } } - default: { File{ source => $source } } + default: { File{ source => $source } } } } default: { File{ content => $content } } } file{"${fragdir}/fragments/${order}_${safe_name}": + ensure => $ensure, mode => $mode, owner => $owner, group => $group, - ensure => $ensure, backup => $backup, alias => "concat_fragment_${name}", notify => Exec["concat_${target}"] diff --git a/external/concat/manifests/init.pp b/external/concat/manifests/init.pp index b94411c2..c2039349 100644 --- a/external/concat/manifests/init.pp +++ b/external/concat/manifests/init.pp @@ -1,13 +1,13 @@ # A system to construct files using fragments from other files or templates. # -# This requires at least puppet 0.25 to work correctly as we use some +# This requires at least puppet 0.25 to work correctly as we use some # enhancements in recursive directory management and regular expressions # to do the work here. # # USAGE: # The basic use case is as below: # -# concat{"/etc/named.conf": +# concat{"/etc/named.conf": # notify => Service["named"] # } # @@ -17,7 +17,7 @@ # content => template("named_conf_zone.erb") # } # -# # add a fragment not managed by puppet so local users +# # add a fragment not managed by puppet so local users # # can add content to managed file # concat::fragment{"foo.com_user_config": # target => "/etc/named.conf", @@ -25,7 +25,7 @@ # ensure => "/etc/named.conf.local" # } # -# This will use the template named_conf_zone.erb to build a single +# This will use the template named_conf_zone.erb to build a single # bit of config up and put it into the fragments dir. The file # will have an number prefix of 10, you can use the order option # to control that and thus control the order the final file gets built in. @@ -39,16 +39,16 @@ # There's some regular expression magic to figure out the puppet version but # if you're on an older 0.24 version just set $puppetversion = 24 # -# Before you can use any of the concat features you should include the +# Before you can use any of the concat features you should include the # class concat::setup somewhere on your node first. # # DETAIL: # We use a helper shell script called concatfragments.sh that gets placed -# in /usr/local/bin to do the concatenation. While this might seem more +# in /usr/local/bin to do the concatenation. While this might seem more # complex than some of the one-liner alternatives you might find on the net -# we do a lot of error checking and safety checks in the script to avoid +# we do a lot of error checking and safety checks in the script to avoid # problems that might be caused by complex escaping errors etc. -# +# # LICENSE: # Apache Version 2 # @@ -56,13 +56,13 @@ # http://github.com/ripienaar/puppet-concat/ # # CONTACT: -# R.I.Pienaar <rip@devco.net> +# R.I.Pienaar <rip@devco.net> # Volcane on freenode # @ripienaar on twitter # www.devco.net -# Sets up so that you can use fragments to build a final config file, +# Sets up so that you can use fragments to build a final config file, # # OPTIONS: # - mode The mode of the final file @@ -78,15 +78,15 @@ # - Creates fragment directories if it didn't exist already # - Executes the concatfragments.sh script to build the final file, this script will create # directory/fragments.concat. Execution happens only when: -# * The directory changes -# * fragments.concat != final destination, this means rebuilds will happen whenever +# * The directory changes +# * fragments.concat != final destination, this means rebuilds will happen whenever # someone changes or deletes the final file. Checking is done using /usr/bin/cmp. # * The Exec gets notified by something else - like the concat::fragment define # - Copies the file over to the final destination using a file resource # # ALIASES: # - The exec can notified using Exec["concat_/path/to/file"] or Exec["concat_/path/to/directory"] -# - The final file can be referened as File["/path/to/file"] or File["concat_/path/to/file"] +# - The final file can be referenced as File["/path/to/file"] or File["concat_/path/to/file"] define concat($mode = 0644, $owner = "root", $group = "root", $warn = "false", $force = "false", $backup = "puppet") { $safe_name = regsubst($name, '/', '_', 'G') $concatdir = $concat::setup::concatdir @@ -123,7 +123,7 @@ define concat($mode = 0644, $owner = "root", $group = "root", $warn = "false", $ file{$fragdir: ensure => directory; - "${fragdir}/fragments": + "${fragdir}/fragments": ensure => directory, recurse => true, purge => true, @@ -135,19 +135,19 @@ define concat($mode = 0644, $owner = "root", $group = "root", $warn = "false", $ }, notify => Exec["concat_${name}"]; - "${fragdir}/fragments.concat": + "${fragdir}/fragments.concat": ensure => present; - "${fragdir}/${concat_name}": + "${fragdir}/${concat_name}": ensure => present; - $name: + $name: + ensure => present, source => "${fragdir}/${concat_name}", owner => $owner, group => $group, checksum => md5, mode => $mode, - ensure => present, alias => "concat_${name}"; } diff --git a/external/concat/manifests/setup.pp b/external/concat/manifests/setup.pp index 9676fb66..68beb901 100644 --- a/external/concat/manifests/setup.pp +++ b/external/concat/manifests/setup.pp @@ -7,29 +7,29 @@ # $puppetversion should be either 24 or 25 to enable a 24 compatible # mode, in 24 mode you might see phantom notifies this is a side effect # of the method we use to clear the fragments directory. -# +# # The regular expression below will try to figure out your puppet version # but this code will only work in 0.24.8 and newer. # # It also copies out the concatfragments.sh file to /usr/local/bin class concat::setup { - $concatdir = "/var/lib/puppet/concat" + $concatdir = '/var/lib/puppet/concat' $majorversion = regsubst($puppetversion, '^[0-9]+[.]([0-9]+)[.][0-9]+$', '\1') - file{"/usr/local/bin/concatfragments.sh": + file{'/usr/local/bin/concatfragments.sh': owner => root, group => root, - mode => 755, + mode => '0755', source => $majorversion ? { 24 => "puppet:///concat/concatfragments.sh", default => "puppet:///modules/concat/concatfragments.sh" }; - $concatdir: + $concatdir: ensure => directory, owner => root, group => root, - mode => 755; + mode => '0755'; } } diff --git a/external/ssh/manifests/auth.pp b/external/ssh/manifests/auth.pp deleted file mode 100644 index 08570add..00000000 --- a/external/ssh/manifests/auth.pp +++ /dev/null @@ -1,336 +0,0 @@ -# =========
-# ssh::auth
-# =========
-#
-# The latest official release and documentation for ssh::auth can always
-# be found at http://reductivelabs.com/trac/puppet/wiki/Recipes/ModuleSSHAuth .
-#
-# Version: 0.3.2
-# Release date: 2009-12-29
-
-class ssh::auth {
-
-$keymaster_storage = "/var/lib/keys"
-
-Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" }
-Notify { withpath => false }
-
-
-##########################################################################
-
-
-# ssh::auth::key
-
-# Declare keys. The approach here is just to define a bunch of
-# virtual resources, representing key files on the keymaster, client,
-# and server. The virtual keys are then realized by
-# ssh::auth::{keymaster,client,server}, respectively. The reason for
-# doing things that way is that it makes ssh::auth::key into a "one
-# stop shop" where users can declare their keys with all of their
-# parameters, whether those parameters apply to the keymaster, server,
-# or client. The real work of creating, installing, and removing keys
-# is done in the private definitions called by the virtual resources:
-# ssh_auth_key_{master,server,client}.
-
-define key ($ensure = "present", $filename = "", $force = false, $group = "puppet", $home = "", $keytype = "rsa", $length = 2048, $maxdays = "", $mindate = "", $options = "", $user = "") {
-
- ssh_auth_key_namecheck { "${title}-title": parm => "title", value => $title }
-
- # apply defaults
- $_filename = $filename ? { "" => "id_${keytype}", default => $filename }
- $_length = $keytype ? { "rsa" => $length, "dsa" => 1024 }
- $_user = $user ? {
- "" => regsubst($title, '^([^@]*)@?.*$', '\1'),
- default => $user,
- }
- $_home = $home ? { "" => "/home/$_user", default => $home }
-
- ssh_auth_key_namecheck { "${title}-filename": parm => "filename", value => $_filename }
-
- @ssh_auth_key_master { $title:
- ensure => $ensure,
- force => $force,
- keytype => $keytype,
- length => $_length,
- maxdays => $maxdays,
- mindate => $mindate,
- }
- @ssh_auth_key_client { $title:
- ensure => $ensure,
- filename => $_filename,
- group => $group,
- home => $_home,
- user => $_user,
- }
- @ssh_auth_key_server { $title:
- ensure => $ensure,
- group => $group,
- home => $_home,
- options => $options,
- user => $_user,
- }
-}
-
-
-##########################################################################
-
-
-# ssh::auth::keymaster
-#
-# Keymaster host:
-# Create key storage; create, regenerate, and remove key pairs
-
-class keymaster {
-
- # Set up key storage
-
- file { $ssh::auth::keymaster_storage:
- ensure => directory,
- owner => puppet,
- group => puppet,
- mode => 644,
- }
-
- # Realize all virtual master keys
- Ssh_auth_key_master <| |>
-
-} # class keymaster
-
-
-##########################################################################
-
-
-# ssh::auth::client
-#
-# Install generated key pairs onto clients
-
-define client ($ensure = "", $filename = "", $group = "", $home = "", $user = "") {
-
- # Realize the virtual client keys.
- # Override the defaults set in ssh::auth::key, as needed.
- if $ensure { Ssh_auth_key_client <| title == $title |> { ensure => $ensure } }
- if $filename { Ssh_auth_key_client <| title == $title |> { filename => $filename } }
- if $group { Ssh_auth_key_client <| title == $title |> { group => $group } }
-
- if $user { Ssh_auth_key_client <| title == $title |> { user => $user, home => "/home/$user" } }
- if $home { Ssh_auth_key_client <| title == $title |> { home => $home } }
-
- realize Ssh_auth_key_client[$title]
-
-} # define client
-
-
-##########################################################################
-
-
-# ssh::auth::server
-#
-# Install public keys onto clients
-
-define server ($ensure = "", $group = "", $home = "", $options = "", $user = "") {
-
- # Realize the virtual server keys.
- # Override the defaults set in ssh::auth::key, as needed.
- if $ensure { Ssh_auth_key_server <| title == $title |> { ensure => $ensure } }
- if $group { Ssh_auth_key_server <| title == $title |> { group => $group } }
- if $options { Ssh_auth_key_server <| title == $title |> { options => $options } }
-
- if $user { Ssh_auth_key_server <| title == $title |> { user => $user, home => "/home/$user" } }
- if $home { Ssh_auth_key_server <| title == $title |> { home => $home } }
-
- realize Ssh_auth_key_server[$title]
-
-} # define server
-
-} # class ssh::auth
-
-
-##########################################################################
-
-
-# ssh_auth_key_master
-#
-# Create/regenerate/remove a key pair on the keymaster.
-# This definition is private, i.e. it is not intended to be called directly by users.
-# ssh::auth::key calls it to create virtual keys, which are realized in ssh::auth::keymaster.
-
-define ssh_auth_key_master ($ensure, $force, $keytype, $length, $maxdays, $mindate) {
-
- Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" }
- File {
- owner => puppet,
- group => puppet,
- mode => 600,
- }
-
- $keydir = "${ssh::auth::keymaster_storage}/${title}"
- $keyfile = "${keydir}/key"
-
- file {
- "$keydir":
- ensure => directory,
- mode => 644;
- "$keyfile":
- ensure => $ensure;
- "${keyfile}.pub":
- ensure => $ensure,
- mode => 644;
- }
-
- if $ensure == "present" {
-
- # Remove the existing key pair, if
- # * $force is true, or
- # * $maxdays or $mindate criteria aren't met, or
- # * $keytype or $length have changed
-
- $keycontent = file("${keyfile}.pub", "/dev/null")
- if $keycontent {
-
- if $force {
- $reason = "force=true"
- }
- if !$reason and $mindate and generate("/usr/bin/find", $keyfile, "!", "-newermt", "${mindate}") {
- $reason = "created before ${mindate}"
- }
- if !$reason and $maxdays and generate("/usr/bin/find", $keyfile, "-mtime", "+${maxdays}") {
- $reason = "older than ${maxdays} days"
- }
- if !$reason and $keycontent =~ /^ssh-... [^ ]+ (...) (\d+)$/ {
- if $keytype != $1 { $reason = "keytype changed: $1 -> $keytype" }
- else { if $length != $2 { $reason = "length changed: $2 -> $length" } }
- }
- if $reason {
- exec { "Revoke previous key ${title}: ${reason}":
- command => "rm $keyfile ${keyfile}.pub",
- before => Exec["Create key $title: $keytype, $length bits"],
- }
- }
- }
-
- # Create the key pair.
- # We "repurpose" the comment field in public keys on the keymaster to
- # store data about the key, i.e. $keytype and $length. This avoids
- # having to rerun ssh-keygen -l on every key at every run to determine
- # the key length.
- exec { "Create key $title: $keytype, $length bits":
- command => "ssh-keygen -t ${keytype} -b ${length} -f ${keyfile} -C \"${keytype} ${length}\" -N \"\"",
- user => "puppet",
- group => "puppet",
- creates => $keyfile,
- require => File[$keydir],
- before => File[$keyfile, "${keyfile}.pub"],
- }
-
- } # if $ensure == "present"
-
-} # define ssh_auth_key_master
-
-
-##########################################################################
-
-
-# ssh_auth_key_client
-#
-# Install a key pair into a user's account.
-# This definition is private, i.e. it is not intended to be called directly by users.
-
-define ssh_auth_key_client ($ensure, $filename, $group, $home, $user) {
-
- File {
- owner => $user,
- group => $group,
- mode => 600,
- require => [ User[$user], File[$home]],
- }
-
- $key_src_file = "${ssh::auth::keymaster_storage}/${title}/key" # on the keymaster
- $key_tgt_file = "${home}/.ssh/${filename}" # on the client
-
- $key_src_content_pub = file("${key_src_file}.pub", "/dev/null")
- if $ensure == "absent" or $key_src_content_pub =~ /^(ssh-...) ([^ ]+)/ {
- $keytype = $1
- $modulus = $2
- file {
- $key_tgt_file:
- ensure => $ensure,
- content => file($key_src_file, "/dev/null");
- "${key_tgt_file}.pub":
- ensure => $ensure,
- content => "$keytype $modulus $title\n",
- mode => 644;
- }
- } else {
- notify { "Private key file $key_src_file for key $title not found on keymaster; skipping ensure => present": }
- }
-
-} # define ssh_auth_key_client
-
-
-##########################################################################
-
-
-# ssh_auth_key_server
-#
-# Install a public key into a server user's authorized_keys(5) file.
-# This definition is private, i.e. it is not intended to be called directly by users.
-
-define ssh_auth_key_server ($ensure, $group, $home, $options, $user) {
-
- # on the keymaster:
- $key_src_dir = "${ssh::auth::keymaster_storage}/${title}"
- $key_src_file = "${key_src_dir}/key.pub"
- # on the server:
- $key_tgt_file = "${home}/.ssh/authorized_keys"
-
- File {
- owner => $user,
- group => $group,
- require => User[$user],
- mode => 600,
- }
- Ssh_authorized_key {
- user => $user,
- target => $key_tgt_file,
- }
-
- if $ensure == "absent" {
- ssh_authorized_key { $title: ensure => "absent" }
- }
- else {
- $key_src_content = file($key_src_file, "/dev/null")
- if ! $key_src_content {
- notify { "Public key file $key_src_file for key $title not found on keymaster; skipping ensure => present": }
- } else { if $ensure == "present" and $key_src_content !~ /^(ssh-...) ([^ ]*)/ {
- err("Can't parse public key file $key_src_file")
- notify { "Can't parse public key file $key_src_file for key $title on the keymaster: skipping ensure => $ensure": }
- } else {
- $keytype = $1
- $modulus = $2
- ssh_authorized_key { $title:
- ensure => "present",
- type => $keytype,
- key => $modulus,
- options => $options ? { "" => undef, default => $options },
- }
- }} # if ... else ... else
- } # if ... else
-
-} # define ssh_auth_key_server
-
-
-##########################################################################
-
-
-# ssh_auth_key_namecheck
-#
-# Check a name (e.g. key title or filename) for the allowed form
-
-define ssh_auth_key_namecheck ($parm, $value) {
- if $value !~ /^[A-Za-z0-9]/ {
- fail("ssh::auth::key: $parm '$value' not allowed: must begin with a letter or digit")
- }
- if $value !~ /^[A-Za-z0-9_.:@-]+$/ {
- fail("ssh::auth::key: $parm '$value' not allowed: may only contain the characters A-Za-z0-9_.:@-")
- }
-} # define namecheck
diff --git a/external/sshkeys/COPYING b/external/sshkeys/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/external/sshkeys/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/external/sshkeys/README.rst b/external/sshkeys/README.rst new file mode 100644 index 00000000..73b136d6 --- /dev/null +++ b/external/sshkeys/README.rst @@ -0,0 +1,73 @@ +sshkeys puppet module +===================== + +The sshkeys puppet module allow the creation and installation of ssh keys. + + +How it works +============ + +With the sshkeys module, you define a key that will be generated on the +puppet master. You define where this key should be installed, for the +client key pair, and for the authorized_keys. + +When the key has not been generated yet, you may need to run puppet +twice. The key will be generated on the first run, and installed on the +second run. + + +Usage +===== + +In order to tell which node will generate the keys, you need to include +the `sshkeys::keymaster` class on the puppet master node:: + + include sshkeys::keymaster + +Before installing the key, we need to create it. This is done with the +`create_key` resource, on the puppet master node. We can create the key +`key1`:: + + sshkeys::create_key{key1: } + +If we want to install the `key1` key pair for user `user1`, we can use +the `set_client_key_pair` resource:: + + sshkeys::set_client_key_pair{'key1-for-user1': + keyname => 'key1', + home => '/home/user1', + user => 'user1', + } + +The `key1` private and public keys should now be installed for user +`user1` on the node on which we created this resource. + +If we want to allow the key `key1` to connect to the `user2` account, +we use the `set_authorized_keys` resource:: + + sshkeys::set_authorized_keys{'key1-to-user2': + keyname => 'key1', + user => 'user2', + home => '/home/user2', + } + +Now, `user1` should have the `key1` key pair installed on his account, +and be able to login to the `user2` account. + + +License +======= + +This module is released under the GNU General Public License version 3: +http://www.gnu.org/licenses/gpl-3.0.txt + + +Authors +======= + +The sshkeys module is based on the ssh::auth module written by +Andrew E. Schulman <andrex at alumni dot utexas dot net>. + +The original ssh::auth module is available at this URL : +http://projects.puppetlabs.com/projects/1/wiki/Module_Ssh_Auth_Patterns + diff --git a/external/sshkeys/manifests/create_key.pp b/external/sshkeys/manifests/create_key.pp new file mode 100644 index 00000000..23a74e8c --- /dev/null +++ b/external/sshkeys/manifests/create_key.pp @@ -0,0 +1,29 @@ +define sshkeys::create_key ( + $ensure = "present", + $filename = "", + $force = false, + $keytype = "rsa", + $length = 2048, + $maxdays = "", + $mindate = "" +) { + sshkeys::namecheck { "${title}-title": parm => "title", value => $title } + + # apply defaults + $_filename = $filename ? { "" => "id_${keytype}", default => $filename } + $_length = $keytype ? { "rsa" => $length, "dsa" => 1024 } + + sshkeys::namecheck { "${title}-filename": + parm => "filename", + value => $_filename, + } + + @sshkeys::setup_key_master { $title: + ensure => $ensure, + force => $force, + keytype => $keytype, + length => $_length, + maxdays => $maxdays, + mindate => $mindate, + } +} diff --git a/external/sshkeys/manifests/init.pp b/external/sshkeys/manifests/init.pp new file mode 100644 index 00000000..4ab92bff --- /dev/null +++ b/external/sshkeys/manifests/init.pp @@ -0,0 +1,2 @@ +class sshkeys { +} diff --git a/external/sshkeys/manifests/keymaster.pp b/external/sshkeys/manifests/keymaster.pp new file mode 100644 index 00000000..3fc2a1fb --- /dev/null +++ b/external/sshkeys/manifests/keymaster.pp @@ -0,0 +1,13 @@ +# Keymaster host: +# Create key storage; create, regenerate, and remove key pairs +class sshkeys::keymaster { + include sshkeys::var + file { $sshkeys::var::keymaster_storage: + ensure => directory, + owner => puppet, + group => puppet, + mode => '0644', + } + # Realize all virtual master keys + Sshkeys::Setup_key_master <| |> +} diff --git a/external/sshkeys/manifests/namecheck.pp b/external/sshkeys/manifests/namecheck.pp new file mode 100644 index 00000000..52c6e51f --- /dev/null +++ b/external/sshkeys/manifests/namecheck.pp @@ -0,0 +1,12 @@ +# Check a name (e.g. key title or filename) for the allowed form +define sshkeys::namecheck ( + $parm, + $value +) { + if $value !~ /^[A-Za-z0-9]/ { + fail("sshkeys::key: ${parm} '${value}' not allowed: must begin with a letter or digit") + } + if $value !~ /^[A-Za-z0-9_.:@-]+$/ { + fail("sshkeys::key: ${parm} '${value}' not allowed: may only contain the characters A-Za-z0-9_.:@-") + } +} diff --git a/external/sshkeys/manifests/set_authorized_keys.pp b/external/sshkeys/manifests/set_authorized_keys.pp new file mode 100644 index 00000000..894f8069 --- /dev/null +++ b/external/sshkeys/manifests/set_authorized_keys.pp @@ -0,0 +1,58 @@ +# Install a public key into a server user's authorized_keys(5) file. +define sshkeys::set_authorized_keys ( + $keyname = '', + $ensure = 'present', + $group = '', + $home = '', + $options = '', + $user +) { + include sshkeys::var + $_keyname = $keyname ? { '' => $title, default => $keyname } + $_home = $home ? { "" => "/home/${user}", default => $home } + # on the keymaster: + $key_src_dir = "${sshkeys::var::keymaster_storage}/${_keyname}" + $key_src_file = "${key_src_dir}/key.pub" + # on the server: + $key_tgt_file = "${_home}/.ssh/authorized_keys" + + File { + owner => $user, + group => $group ? { "" => $user, default => $group }, + require => User[$user], + mode => '0600', + } + Ssh_authorized_key { + user => $user, + target => $key_tgt_file, + } + + if $ensure == "absent" { + ssh_authorized_key { $title: + ensure => "absent", + } + } else { + $key_src_content = file($key_src_file, "/dev/null") + if ! $key_src_content { + notify { + "Public key file ${key_src_file} for key ${_keyname} not found on keymaster; skipping ensure => present": + } + } else { + if $ensure == "present" and $key_src_content !~ /^(ssh-...) ([^ ]*)/ { + err("Can't parse public key file ${key_src_file}") + notify { + "Can't parse public key file ${key_src_file} for key ${_keyname} on the keymaster: skipping ensure => ${ensure}": + } + } else { + $keytype = $1 + $modulus = $2 + ssh_authorized_key { $title: + ensure => "present", + type => $keytype, + key => $modulus, + options => $options ? { "" => undef, default => $options }, + } + } + } + } +} diff --git a/external/sshkeys/manifests/set_client_key_pair.pp b/external/sshkeys/manifests/set_client_key_pair.pp new file mode 100644 index 00000000..27780eb4 --- /dev/null +++ b/external/sshkeys/manifests/set_client_key_pair.pp @@ -0,0 +1,39 @@ +# Install a key pair into a user's account. +define sshkeys::set_client_key_pair ( + $keyname = '', + $ensure = 'present', + $filename = 'id_rsa', + $group = '', + $home = '', + $user +) { + include sshkeys::var + File { + owner => $user, + group => $group ? { '' => $user, default => $group }, + mode => '0600', + require => [ User[$user], File[$home]], + } + + $_keyname = $keyname ? { '' => $title, default => $keyname } + $_home = $home ? { '' => "/home/${user}", default => $home } + $key_src_file = "${sshkeys::var::keymaster_storage}/${_keyname}/key" # on the keymaster + $key_tgt_file = "${_home}/.ssh/${filename}" # on the client + + $key_src_content_pub = file("${key_src_file}.pub", "/dev/null") + if $ensure == "absent" or $key_src_content_pub =~ /^(ssh-...) ([^ ]+)/ { + $keytype = $1 + $modulus = $2 + file { + $key_tgt_file: + ensure => $ensure, + content => file($key_src_file, "/dev/null"); + "${key_tgt_file}.pub": + ensure => $ensure, + content => "${keytype} ${modulus} ${title}\n", + mode => '0644'; + } + } else { + notify { "Private key file ${key_src_file} for key ${title} not found on keymaster; skipping ensure => present": } + } +} diff --git a/external/sshkeys/manifests/setup_key_master.pp b/external/sshkeys/manifests/setup_key_master.pp new file mode 100644 index 00000000..9dcd5f86 --- /dev/null +++ b/external/sshkeys/manifests/setup_key_master.pp @@ -0,0 +1,87 @@ +# Create/regenerate/remove a key pair on the keymaster. +# This definition is private, i.e. it is not intended to be called +# directly by users. sshkeys::create_key calls it to create virtual +# keys, which are realized in sshkeys::keymaster. +define sshkeys::setup_key_master ( + $ensure, + $force, + $keytype, + $length, + $maxdays, + $mindate +) { + include sshkeys::var + Exec { path => "/usr/bin:/usr/sbin:/bin:/sbin" } + File { + owner => puppet, + group => puppet, + mode => '0600', + } + + $keydir = "${sshkeys::var::keymaster_storage}/${title}" + $keyfile = "${keydir}/key" + + file { + "${keydir}": + ensure => directory, + mode => '0644'; + "${keyfile}": + ensure => $ensure; + "${keyfile}.pub": + ensure => $ensure, + mode => '0644'; + } + + if $ensure == "present" { + + # Remove the existing key pair, if + # * $force is true, or + # * $maxdays or $mindate criteria aren't met, or + # * $keytype or $length have changed + + $keycontent = file("${keyfile}.pub", "/dev/null") + if $keycontent { + + if $force { + $reason = "force=true" + } + if !$reason and $mindate and + generate("/usr/bin/find", $keyfile, "!", "-newermt", "${mindate}") { + $reason = "created before ${mindate}" + } + if !$reason and $maxdays and + generate("/usr/bin/find", $keyfile, "-mtime", "+${maxdays}") { + $reason = "older than ${maxdays} days" + } + if !$reason and $keycontent =~ /^ssh-... [^ ]+ (...) (\d+)$/ { + if $keytype != $1 { + $reason = "keytype changed: ${1} -> ${keytype}" + } else { + if $length != $2 { + $reason = "length changed: ${2} -> ${length}" + } + } + } + if $reason { + exec { "Revoke previous key ${title}: ${reason}": + command => "rm ${keyfile} ${keyfile}.pub", + before => Exec["Create key ${title}: ${keytype}, ${length} bits"], + } + } + } + + # Create the key pair. + # We "repurpose" the comment field in public keys on the keymaster to + # store data about the key, i.e. $keytype and $length. This avoids + # having to rerun ssh-keygen -l on every key at every run to determine + # the key length. + exec { "Create key ${title}: ${keytype}, ${length} bits": + command => "ssh-keygen -t ${keytype} -b ${length} -f ${keyfile} -C \"${keytype} ${length}\" -N \"\"", + user => "puppet", + group => "puppet", + creates => $keyfile, + require => File[$keydir], + before => File[$keyfile, "${keyfile}.pub"], + } + } +} diff --git a/external/sshkeys/manifests/var.pp b/external/sshkeys/manifests/var.pp new file mode 100644 index 00000000..13f6992e --- /dev/null +++ b/external/sshkeys/manifests/var.pp @@ -0,0 +1,4 @@ +class sshkeys::var( + $keymaster_storage = '/var/lib/puppet-sshkeys' +) { +} diff --git a/manifests/defaults.pp b/manifests/defaults.pp index c7b0dd85..85f3f31c 100644 --- a/manifests/defaults.pp +++ b/manifests/defaults.pp @@ -29,3 +29,7 @@ User { Service { ensure => running, } + +Service { + provider => systemd, +} diff --git a/manifests/extlookup.pp b/manifests/extlookup.pp index 554958ed..0837818b 100644 --- a/manifests/extlookup.pp +++ b/manifests/extlookup.pp @@ -1,4 +1,4 @@ -# see http://www.devco.net/archives/2009/08/31/complex_data_and_puppet.php +# see https://www.devco.net/archives/2009/08/31/complex_data_and_puppet.php $extlookup_datadir = '/etc/puppet/extdata' $extlookup_precedence = ['%{fqdn}', 'common'] diff --git a/manifests/nodes/alamut.pp b/manifests/nodes/alamut.pp deleted file mode 100644 index bfa0d6f2..00000000 --- a/manifests/nodes/alamut.pp +++ /dev/null @@ -1,103 +0,0 @@ -# web apps -node alamut { -# Location: IELO datacenter (marseille) -# -# TODO: -# - Review board -# - api -# - pastebin -# - LDAP slave -# - include common::default_mageia_server_no_smtp - include postgresql::server - postgresql::tagged { 'default': } - - timezone::timezone { 'Europe/Paris': } - - include catdap - include mga-mirrors - include epoll - include transifex - include bugzilla - include sympa::server - include postfix::server::primary - - # temporary, just the time the vm is running there - host { 'friteuse': - ensure => 'present', - ip => '192.168.122.131', - host_aliases => [ "friteuse.$domain", "forums.$domain" ], - } - - # to create all phpbb database on alamut - phpbb::databases { $fqdn: } - - apache::vhost::redirect_ssl { "forums.$domain": } - apache::vhost_redirect { "forum.$domain": - url => "https://forums.$domain/", - } - apache::vhost_redirect { "ssl_forum.$domain": - url => "https://forums.$domain/", - vhost => "forum.$domain", - use_ssl => true, - } - - # connect to ssl so the proxy do not shoke if trying to - # enforce ssl ( note that this has not been tested, maybe this - # is uneeded ) - apache::vhost::reverse_proxy { "ssl_forums.$domain": - url => "https://forums.$domain/", - vhost => "forums.$domain", - use_ssl => true, - } - - include tld_redirections - - include libvirtd::kvm - include lists - include dns::server - include repositories::svn_mirror - include viewvc - - # disabled until fixed - #Enable back to test. - include repositories::git_mirror - include gitweb - - include xymon::server - apache::vhost_simple { "xymon.$domain": - location => '/var/lib/xymon/www', - } - - youri-check::report_www { 'check': } - - youri-check::config {'config_cauldron': - version => 'cauldron', - } - youri-check::report { 'report_cauldron': - version => 'cauldron', - hour => '*', - minute => '24' - } - - youri-check::config {'config_1': - version => '1', - } - youri-check::report {'report_1': - version => '1', - hour => '*', - minute => '54' - } - - youri-check::config {'config_2': - version => '2', - } - youri-check::report {'report_2': - version => '2', - hour => '*', - minute => '9' - } - - include wikis - include websites::perl -} diff --git a/manifests/nodes/armlet1.pp b/manifests/nodes/armlet1.pp new file mode 100644 index 00000000..0d731f08 --- /dev/null +++ b/manifests/nodes/armlet1.pp @@ -0,0 +1,7 @@ +node armlet1 { +# Location: Scaleway (Iliad/Online datacenter) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/armlet2.pp b/manifests/nodes/armlet2.pp new file mode 100644 index 00000000..7566249f --- /dev/null +++ b/manifests/nodes/armlet2.pp @@ -0,0 +1,7 @@ +node armlet2 { +# Location: Scaleway (Iliad/Online datacenter) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/champagne.pp b/manifests/nodes/champagne.pp deleted file mode 100644 index cc575d2b..00000000 --- a/manifests/nodes/champagne.pp +++ /dev/null @@ -1,22 +0,0 @@ -node champagne { -# Location: gandi VM -# - include common::default_mageia_server - timezone::timezone { 'Europe/Paris': } - include blog::files_bots - include blog::files_backup - include planet - include websites::static - include websites::hugs - include websites::releases - include websites::www - include websites::nav - include websites::doc - include websites::start - include dashboard - include access_classes::web - include openssh::ssh_keys_from_ldap - - # temporary protection for CVE-2011-3192 - include apache::cve-2011-3192 -} diff --git a/manifests/nodes/valstar.pp b/manifests/nodes/duvel.pp index c79f65af..772e43dc 100644 --- a/manifests/nodes/valstar.pp +++ b/manifests/nodes/duvel.pp @@ -1,5 +1,4 @@ -# svn, big important server -node valstar { +node duvel { # Location: IELO datacenter (marseille) # # TODO: @@ -10,16 +9,17 @@ node valstar { timezone::timezone { 'Europe/Paris': } include main_mirror include openldap::master + include git::client include subversion::client include subversion::server include puppet::master - include reports::ii + #include reports::ii - include ssh::auth - include ssh::auth::keymaster + include sshkeys::keymaster include mga_buildsystem::mainnode include softwarekey include mgasoft + include spec-tree-reports include access_classes::committers include restrictshell::allow_git @@ -27,25 +27,30 @@ node valstar { include restrictshell::allow_pkgsubmit include restrictshell::allow_maintdb include restrictshell::allow_upload_bin - # disabled the ldap key here instead of disabling for the - # whole module ( see r698 ) - class { 'openssh::ssh_keys_from_ldap': - symlink_users => ['schedbot', 'iurt'] - } - - include mirror::mdv2010spring + include openssh::ssh_keys_from_ldap include repositories::subversion - include repositories::git - include repositories::sparkleshare + + # include irkerd include websites::svn + include websites::git - subversion::snapshot { '/etc/puppet': - source => 'svn://svn.mageia.org/svn/adm/puppet/' + class { 'mga-advisories': + vhost => "advisories.${::domain}", + } + + git::snapshot { '/etc/puppet': + source => "git://git.${::domain}/infrastructure/puppet/" } mirror_cleaner::orphans { 'cauldron': base => '/distrib/bootstrap/distrib/', } + + class { 'mgagit': + ldap_server => "ldap.${::domain}", + binddn => 'cn=mgagit-valstar,ou=System Accounts,dc=mageia,dc=org', + bindpw => extlookup('mgagit_ldap','x'), + } } diff --git a/manifests/nodes/ec2aa1.pp b/manifests/nodes/ec2aa1.pp new file mode 100644 index 00000000..f000db8a --- /dev/null +++ b/manifests/nodes/ec2aa1.pp @@ -0,0 +1,7 @@ +node ec2aa1 { +# Location: Amazon (eu-central-1a) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/ec2aa2.pp b/manifests/nodes/ec2aa2.pp new file mode 100644 index 00000000..a4e1e27f --- /dev/null +++ b/manifests/nodes/ec2aa2.pp @@ -0,0 +1,7 @@ +node ec2aa2 { +# Location: Amazon (eu-central-1b) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/ec2aa3.pp b/manifests/nodes/ec2aa3.pp new file mode 100644 index 00000000..763675d7 --- /dev/null +++ b/manifests/nodes/ec2aa3.pp @@ -0,0 +1,7 @@ +node ec2aa3 { +# Location: Amazon (eu-central-1b) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/ec2x1.pp b/manifests/nodes/ec2x1.pp new file mode 100644 index 00000000..4a0f5a0f --- /dev/null +++ b/manifests/nodes/ec2x1.pp @@ -0,0 +1,7 @@ +node ec2x1 { +# Location: Amazon (eu-central-1b) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/ec2x2.pp b/manifests/nodes/ec2x2.pp new file mode 100644 index 00000000..bf25cf8e --- /dev/null +++ b/manifests/nodes/ec2x2.pp @@ -0,0 +1,7 @@ +node ec2x2 { +# Location: Amazon (eu-central-1a) +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/ecosse.pp b/manifests/nodes/ecosse.pp index a106d0ed..c7fa95e5 100644 --- a/manifests/nodes/ecosse.pp +++ b/manifests/nodes/ecosse.pp @@ -2,6 +2,6 @@ node ecosse { # Location: IELO datacenter (marseille) # include common::default_mageia_server - include buildsystem::buildnode + include mga_buildsystem::buildnode timezone::timezone { 'Europe/Paris': } } diff --git a/manifests/nodes/fiona.pp b/manifests/nodes/fiona.pp index bb533586..2093001a 100644 --- a/manifests/nodes/fiona.pp +++ b/manifests/nodes/fiona.pp @@ -6,5 +6,5 @@ node fiona { # - install a backup system include common::default_mageia_server timezone::timezone { 'Europe/Paris': } - include backups::server +# include backups::server } diff --git a/manifests/nodes/friteuse.pp b/manifests/nodes/friteuse.pp index 9c0fdde1..b096021e 100644 --- a/manifests/nodes/friteuse.pp +++ b/manifests/nodes/friteuse.pp @@ -1,5 +1,5 @@ node friteuse { -# Location: VM hosted by nfrance (toulouse) +# Location: VM hosted on sucuk # include common::default_mageia_server timezone::timezone { 'Europe/Paris': } diff --git a/manifests/nodes/jonund.pp b/manifests/nodes/jonund.pp deleted file mode 100644 index ff448844..00000000 --- a/manifests/nodes/jonund.pp +++ /dev/null @@ -1,11 +0,0 @@ -# buildnode -node jonund { -# Location: IELO datacenter (marseille) -# - include common::default_mageia_server - include buildsystem::buildnode - include buildsystem::iurt20101 - timezone::timezone { 'Europe/Paris': } -# include shorewall -# include shorewall::default_firewall -} diff --git a/manifests/nodes/krampouezh.pp b/manifests/nodes/krampouezh.pp deleted file mode 100644 index 52fd93f5..00000000 --- a/manifests/nodes/krampouezh.pp +++ /dev/null @@ -1,27 +0,0 @@ -# gandi-vm -node krampouezh { -# Location: gandi VM -# -# - #include common::default_mageia_server - include common::default_mageia_server_no_smtp - include postfix::server::secondary - include blog::base - include blog::db_backup - include mysql::server - include dns::server - timezone::timezone { 'Europe/Paris': } - - openldap::slave_instance { '1': - rid => 1, - } - - # http server for meetbot logs - include apache::base - - # temporary protection for CVE-2011-3192 - include apache::cve-2011-3192 - -# Other services running on this server : -# - meetbot -} diff --git a/manifests/nodes/arm2.pp b/manifests/nodes/ncaa1.pp index 2cd94b71..b512939a 100644 --- a/manifests/nodes/arm2.pp +++ b/manifests/nodes/ncaa1.pp @@ -1,5 +1,7 @@ -node arm2 { -# Location: IELO datacenter (marseille) +node ncaa1 { +# Location: Netcup, Vienna +# include common::default_mageia_server + include mga_buildsystem::buildnode timezone::timezone { 'Europe/Paris': } } diff --git a/manifests/nodes/neru.pp b/manifests/nodes/neru.pp new file mode 100644 index 00000000..66958059 --- /dev/null +++ b/manifests/nodes/neru.pp @@ -0,0 +1,45 @@ +node neru { +# Location: Scaleway Paris +# + include common::default_mageia_server_no_smtp + timezone::timezone { 'Europe/Paris': } + include postfix::server::secondary + include blog::base + include blog::db_backup + include blog::files_bots + include blog::files_backup + include mysql::server + include dns::server + + include planet + include websites::archives + include websites::static + include websites::hugs + include websites::releases + include websites::www + include websites::doc + include websites::start + include websites::meetbot + include dashboard + include access_classes::web + include openssh::ssh_keys_from_ldap + + # temporary redirects for madb (2024-11) until it gets hosted on Mageia infra + apache::vhost_redirect { "madb.${::domain}": + url => "https://madb.mageialinux-online.org/", + } + apache::vhost_redirect { "ssl_madb.${::domain}": + use_ssl => true, + vhost => "madb.${::domain}", + url => "https://madb.mageialinux-online.org/", + } + + openldap::slave_instance { '1': + rid => 1, + } + + # http server for meetbot logs + include apache::base +} +# Other services running on this server : +# - meetbot diff --git a/manifests/nodes/arm1.pp b/manifests/nodes/ociaa1.pp index 6409f9b4..ce476665 100644 --- a/manifests/nodes/arm1.pp +++ b/manifests/nodes/ociaa1.pp @@ -1,5 +1,7 @@ -node arm1 { -# Location: IELO datacenter (marseille) +node ociaa1 { +# Location: ? +# include common::default_mageia_server + include mga_buildsystem::buildnode timezone::timezone { 'Europe/Paris': } } diff --git a/manifests/nodes/pktaa1.pp b/manifests/nodes/pktaa1.pp new file mode 100644 index 00000000..31f649c4 --- /dev/null +++ b/manifests/nodes/pktaa1.pp @@ -0,0 +1,7 @@ +node pktaa1 { +# Location: Equinix Metal / SV - SJC1 +# + include common::default_mageia_server + include mga_buildsystem::buildnode + timezone::timezone { 'Europe/Paris': } +} diff --git a/manifests/nodes/rabbit.pp b/manifests/nodes/rabbit.pp index 8906de0c..2436219b 100644 --- a/manifests/nodes/rabbit.pp +++ b/manifests/nodes/rabbit.pp @@ -1,14 +1,16 @@ node rabbit { -# Location: Server offered by Dedibox (paris) +# Location: IELO datacenter (marseille) # # - used to create isos ( and live, and so on ) # include common::default_mageia_server timezone::timezone { 'Europe/Paris': } include bcd::base - include bcd::web + #include bcd::web include bcd::rsync + include mga_buildsystem::buildnode include draklive + include git::svn include access_classes::iso_makers include openssh::ssh_keys_from_ldap # include mirror::mageia @@ -19,31 +21,12 @@ node rabbit { } youri-check::check {'check_cauldron': version => 'cauldron', - hour => '*', - minute => 4 - } - - youri-check::config {'config_1': - version => '1', - } - youri-check::check {'check_1': - version => '1', - hour => '*/2', + hour => '1-23/2', minute => 30 } - youri-check::config {'config_2': - version => '2', - } - - youri-check::check {'check_2': - version => '2', - hour => '*/2', - minute => 45 - } - # for testing iso quickly - include libvirtd::kvm - libvirtd::group_access { 'mga-iso_makers': } + # include libvirtd::kvm + # libvirtd::group_access { 'mga-iso_makers': } } diff --git a/manifests/nodes/sucuk.pp b/manifests/nodes/sucuk.pp index 9789fd97..e56fd113 100644 --- a/manifests/nodes/sucuk.pp +++ b/manifests/nodes/sucuk.pp @@ -1,9 +1,131 @@ # server for various task node sucuk { # Location: IELO datacenter (marseille) - include common::default_mageia_server + include common::default_mageia_server_no_smtp timezone::timezone { 'Europe/Paris': } include openssh::ssh_keys_from_ldap include access_classes::admin + + include postgresql::server + postgresql::tagged { 'default': } + + class {'epoll::var': + db_password => extlookup('epoll_pgsql','x'), + password => extlookup('epoll_password','x'), + } + + #include epoll + #include epoll::create_db + + include sympa::server + include postfix::server::primary + include lists + + include catdap + include mga-mirrors + + include wikis + include websites::perl + include websites::www + include websites::nav + + include bugzilla + + # gitweb + include repositories::git_mirror + include cgit + include gitmirror + + include repositories::svn_mirror + include viewvc + +# include mirrorbrain + + include dns::server + + include xymon::server + apache::vhost_simple { "xymon.${::domain}": + location => '/usr/share/xymon/www', + } + + class { 'mgapeople': + ldap_server => "ldap.${::domain}", + binddn => 'cn=mgapeople-alamut,ou=System Accounts,dc=mageia,dc=org', + bindpw => extlookup('mgapeople_ldap','x'), + vhost => "people.${::domain}", + vhostdir => "/var/www/vhosts/people.${::domain}", + maintdburl => "https://pkgsubmit.${::domain}/data/maintdb.txt", + } + + class { 'mga-treasurer': + vhost => "treasurer.${::domain}", + vhostdir => "/var/www/vhosts/treasurer.${::domain}", + } + + youri-check::report_www { 'check': } + + youri-check::createdb_user {'config_cauldron': + version => 'cauldron', + } + + youri-check::config {'config_cauldron': + version => 'cauldron', + } + youri-check::report { 'report_cauldron': + version => 'cauldron', + hour => '*/2', + minute => '0' + } + + youri-check::createdb_user {'config_9': + version => '9', + } + + youri-check::config {'config_9': + version => '9', + } + + youri-check::report {'report_9': + version => '9', + hour => '*/4', + minute => '56' + } + + include tld_redirections + + # temporary, just the time the vm is running there + host { 'friteuse': + ensure => 'present', + ip => '192.168.122.131', + host_aliases => [ "friteuse.${::domain}", "forums.${::domain}" ], + } + + # to create all phpbb database on sucuk + phpbb::databases { $fqdn: } + + apache::vhost::redirect_ssl { "forums.${::domain}": } + apache::vhost_redirect { "forum.${::domain}": + url => "https://forums.${::domain}/", + } + apache::vhost_redirect { "ssl_forum.${::domain}": + url => "https://forums.${::domain}/", + vhost => "forum.${::domain}", + use_ssl => true, + } + + # forums is running in a VM on the machine so https: isn't necessary + apache::vhost::reverse_proxy { "ssl_forums.${::domain}": + url => "http://forums.${::domain}/", + vhost => "forums.${::domain}", + use_ssl => true, + content => ' + RewriteEngine On + RewriteCond %{QUERY_STRING} mode=register + RewriteRule .*ucp.php - [forbidden] + ', + } + + include libvirtd::kvm + } diff --git a/manifests/nodes_ip.pp b/manifests/nodes_ip.pp new file mode 100644 index 00000000..38553b61 --- /dev/null +++ b/manifests/nodes_ip.pp @@ -0,0 +1,70 @@ +# Nodes IP addresses + +$nodes_ipaddr = { + neru => { + ipv4 => '163.172.148.228', + ipv6 => '2001:bc8:710:175f:dc00:ff:fe2d:c0ff', + }, + ecosse => { + ipv4 => '212.85.158.148', + ipv6 => '2a02:2178:2:7::4', + }, + fiona => { + ipv4 => '212.85.158.150', + ipv6 => '2a02:2178:2:7::6', + }, + sucuk => { + ipv4 => '212.85.158.151', + ipv6 => '2a02:2178:2:7::7', + }, + rabbit => { + ipv4 => '212.85.158.152', + ipv6 => '2a02:2178:2:7::8', + }, + duvel => { + ipv4 => '212.85.158.153', + ipv6 => '2a02:2178:2:7::9', + }, + armlet1 => { + ipv4 => '163.172.148.228', + }, + armlet2 => { + ipv4 => '163.172.148.228', + }, + friteuse => { + ipv4 => '192.168.122.131', + }, + ec2aa1 => { + ipv6 => '2a05:d014:e9:2c02:98ca:ec83:c601:371a', + }, + ec2aa2 => { + ipv6 => '2a05:d014:e9:2c03:b7e1:fda8:eab9:6692', + }, + ec2aa3 => { + ipv6 => '2a05:d014:e9:2c03:17a8:1204:6df6:662c', + }, + ec2aaauto => { + ipv6 => '2a05:d014:e9:2c03:c80d:e2d9:658d:4c28', + }, + ec2x1 => { + ipv6 => '2a05:d014:e9:2c03:ce2e:f80a:bc2b:da0d', + }, + ec2x2 => { + ipv6 => '2a05:d014:e9:2c02:42e4:6e93:ed55:7b2a', + }, + pktaa1 => { + ipv4 => '147.75.69.246', + }, + ociaa1 => { + ipv6 => '2603:c026:c101:f00::1:1', + }, + ociaa2 => { + ipv6 => '2603:c026:c101:f00::1:2', + }, + ncaa1 => { + ipv4 => '89.58.19.166', + ipv6 => '2a0a:4cc0:0:61c::1', + } +} + +# vim: sw=2 diff --git a/manifests/site.pp b/manifests/site.pp index 581dc87b..376c4213 100644 --- a/manifests/site.pp +++ b/manifests/site.pp @@ -1,3 +1,4 @@ import 'extlookup' import 'defaults' +import 'nodes_ip' import 'nodes' diff --git a/modules/amavis/templates/amavisd.conf b/modules/amavis/templates/amavisd.conf index 0e3b3f1d..84a44944 100644 --- a/modules/amavis/templates/amavisd.conf +++ b/modules/amavis/templates/amavisd.conf @@ -22,7 +22,7 @@ $daemon_group = 'amavis'; # (no default; customary: vscan or amavis), -g # a convenient default for other settings could be localhost.localdomain # or change this as your needs -# $MYHOME = '/var/lib/amavis'; # a convenient default for other settings, -H +$MYHOME = '/run/amavis'; # a convenient default for other settings, -H $TEMPBASE = "$MYHOME/tmp"; # working directory, needs to exist, -T $ENV{TMPDIR} = $TEMPBASE; # environment variable TMPDIR, used by SA, etc. $QUARANTINEDIR = '/var/spool/amavis/virusmails'; # -Q @@ -154,8 +154,8 @@ $defang_by_ccat{+CC_BADH.",6"} = 1; # header field syntax error # $myhostname = 'host.example.com'; # must be a fully-qualified domain name! -# $notify_method = 'smtp:[127.0.0.1]:10026'; -# $forward_method = 'smtp:[127.0.0.1]:10026'; # set to undef with milter! +$notify_method = 'smtp:[127.0.0.1]:10026'; +$forward_method = 'smtp:[127.0.0.1]:10026'; # set to undef with milter! # $final_virus_destiny = D_DISCARD; # $final_banned_destiny = D_BOUNCE; @@ -441,7 +441,7 @@ $banned_filename_re = new_RE( # qr/(?:INFECTED|WARNING|SUSPICION|SUSPICIOUS) (.+)/m, # ], # NOTE: one may prefer [0],[2,3,4,5], depending on how suspicious, - # currupted or protected archives are to be handled + # corrupted or protected archives are to be handled ### http://www.kaspersky.com/ # ['KasperskyLab AntiViral Toolkit Pro (AVP)', ['avp'], diff --git a/modules/apache/manifests/base.pp b/modules/apache/manifests/base.pp index 1af8c256..4e1d6ed4 100644 --- a/modules/apache/manifests/base.pp +++ b/modules/apache/manifests/base.pp @@ -1,34 +1,34 @@ class apache::base { + include apache::var - # number of time the log file are rotated before being removed - $httpdlogs_rotate = '24' + $conf_d = '/etc/httpd/conf/conf.d' - $apache_user = 'apache' - $apache_group = 'apache' - - package { 'apache-mpm-prefork': } - - if ($lsbdistrelease == '1') or ($lsbdistid == 'MandrivaLinux') { - package { 'apache-conf': } - } else { - package { 'apache': } + package { 'apache': + alias => 'apache-server', } service { 'httpd': alias => 'apache', - subscribe => [ Package['apache-mpm-prefork'] ], + subscribe => [ Package['apache-server'] ], } - exec { 'service httpd configtest': + exec { 'apachectl configtest': refreshonly => true, notify => Service['apache'], } apache::config { - '/etc/httpd/conf.d/customization.conf': - content => template('apache/customization.conf'); + "${conf_d}/no_hidden_file_dir.conf": + content => template('apache/no_hidden_file_dir.conf'), + require => Package[$apache::var::pkg_conf]; + "${conf_d}/customization.conf": + content => template('apache/customization.conf'), + require => Package[$apache::var::pkg_conf]; '/etc/httpd/conf/vhosts.d/00_default_vhosts.conf': - content => template('apache/00_default_vhosts.conf'); + content => template('apache/00_default_vhosts.conf'), + require => Package[$apache::var::pkg_conf]; + '/etc/httpd/conf/modules.d/50_mod_deflate.conf': + content => template('apache/50_mod_deflate.conf'); } file { '/etc/logrotate.d/httpd': diff --git a/modules/apache/manifests/config.pp b/modules/apache/manifests/config.pp index a6e1e231..0ff0962c 100644 --- a/modules/apache/manifests/config.pp +++ b/modules/apache/manifests/config.pp @@ -1,6 +1,6 @@ define apache::config($content) { file { $name: content => $content, - notify => Exec['service httpd configtest'], + notify => Exec['apachectl configtest'], } } diff --git a/modules/apache/manifests/cve-2011-3192.pp b/modules/apache/manifests/cve-2011-3192.pp index 20b53216..1e39ac04 100644 --- a/modules/apache/manifests/cve-2011-3192.pp +++ b/modules/apache/manifests/cve-2011-3192.pp @@ -1,8 +1,9 @@ class apache::cve-2011-3192 { + include apache::base # temporary protection against CVE-2011-3192 - # http://httpd.apache.org/security/CVE-2011-3192.txt + # https://httpd.apache.org/security/CVE-2011-3192.txt apache::config { - '/etc/httpd/conf.d/CVE-2011-3192.conf': - content => template('apache/CVE-2011-3192.conf'), + "${apache::base::conf_d}/CVE-2011-3192.conf": + content => template('apache/CVE-2011-3192.conf'), } } diff --git a/modules/apache/manifests/init.pp b/modules/apache/manifests/init.pp index 5bfaa004..40779d4d 100644 --- a/modules/apache/manifests/init.pp +++ b/modules/apache/manifests/init.pp @@ -3,18 +3,23 @@ class apache { include apache::base apache::vhost::base { $name: location => $location, - } - } + } + apache::vhost::base { "ssl_${name}": + vhost => $name, + use_ssl => true, + location => $location, + } + } define vhost_redirect($url, - $vhost = false, + $vhost = false, $use_ssl = false) { include apache::base apache::vhost::base { $name: use_ssl => $use_ssl, - vhost => $vhost, + vhost => $vhost, content => template("apache/vhost_redirect.conf"), - } - } + } + } } diff --git a/modules/apache/manifests/mod/deflate.pp b/modules/apache/manifests/mod/deflate.pp deleted file mode 100644 index 0e2211aa..00000000 --- a/modules/apache/manifests/mod/deflate.pp +++ /dev/null @@ -1,4 +0,0 @@ -class apache::mod::deflate { - include apache::base - package { 'apache-mod_deflate': } -} diff --git a/modules/apache/manifests/mod/fastcgi.pp b/modules/apache/manifests/mod/fastcgi.pp index 4f10ccab..2b421291 100644 --- a/modules/apache/manifests/mod/fastcgi.pp +++ b/modules/apache/manifests/mod/fastcgi.pp @@ -2,3 +2,4 @@ class apache::mod::fastcgi { include apache::base package { 'apache-mod_fastcgi': } } + diff --git a/modules/apache/manifests/mod/fcgid.pp b/modules/apache/manifests/mod/fcgid.pp index 6c815681..b8186a64 100644 --- a/modules/apache/manifests/mod/fcgid.pp +++ b/modules/apache/manifests/mod/fcgid.pp @@ -1,4 +1,11 @@ class apache::mod::fcgid { include apache::base package { 'apache-mod_fcgid': } + + file { 'urlescape': + path => '/usr/local/bin/urlescape', + mode => '0755', + notify => Service['apache'], + content => template('apache/urlescape'), + } } diff --git a/modules/apache/manifests/mod/php.pp b/modules/apache/manifests/mod/php.pp index c5de893e..2c8d6733 100644 --- a/modules/apache/manifests/mod/php.pp +++ b/modules/apache/manifests/mod/php.pp @@ -4,7 +4,7 @@ class apache::mod::php { package { 'apache-mod_php': } - apache::config { '/etc/httpd/conf.d/mod_php.conf': + apache::config { "${apache::base::conf_d}/mod_php.conf": content => template('apache/mod/php.conf'), } } diff --git a/modules/apache/manifests/mod/ssl.pp b/modules/apache/manifests/mod/ssl.pp index 6e9be525..ab3d24e4 100644 --- a/modules/apache/manifests/mod/ssl.pp +++ b/modules/apache/manifests/mod/ssl.pp @@ -14,7 +14,7 @@ class apache::mod::ssl { apache::config { '/etc/httpd/conf/vhosts.d/01_default_ssl_vhost.conf': content => template('apache/01_default_ssl_vhost.conf'); - '/etc/httpd/conf.d/ssl.conf': - content => template('apache/mod/ssl.conf'); + "${apache::base::conf_d}/ssl_vhost.conf": + content => template('apache/mod/ssl_vhost.conf'); } } diff --git a/modules/apache/manifests/mod/wsgi.pp b/modules/apache/manifests/mod/wsgi.pp index d2ab72d2..7f4fb719 100644 --- a/modules/apache/manifests/mod/wsgi.pp +++ b/modules/apache/manifests/mod/wsgi.pp @@ -6,7 +6,7 @@ class apache::mod::wsgi { ensure => directory, } - apache::config { '/etc/httpd/conf.d/mod_wsgi.conf': + apache::config { "${apache::base::conf_d}/mod_wsgi.conf": content => template('apache/mod/wsgi.conf'), } } diff --git a/modules/apache/manifests/var.pp b/modules/apache/manifests/var.pp new file mode 100644 index 00000000..4a6d68eb --- /dev/null +++ b/modules/apache/manifests/var.pp @@ -0,0 +1,12 @@ +# $httpdlogs_rotate: +# number of time the log file are rotated before being removed +# $default_vhost_redirect: +# URL to redirect to in case of unknown vhost +class apache::var( + $httpdlogs_rotate = '24', + $apache_user = 'apache', + $apache_group = 'apache', + $default_vhost_redirect = '' +) { + $pkg_conf = 'apache' +} diff --git a/modules/apache/manifests/vhost/base.pp b/modules/apache/manifests/vhost/base.pp index a7e5720d..27a19998 100644 --- a/modules/apache/manifests/vhost/base.pp +++ b/modules/apache/manifests/vhost/base.pp @@ -7,10 +7,11 @@ define apache::vhost::base ($content = '', $access_logfile = false, $error_logfile = false, $options = [], - $enable_public_html = false) { + $enable_public_html = false, + $enable_location = true) { include apache::base $httpd_logdir = '/var/log/httpd' - $filename = "$name.conf" + $filename = "${name}.conf" if ! $vhost { $real_vhost = $name @@ -19,12 +20,12 @@ define apache::vhost::base ($content = '', } if ! $access_logfile { - $real_access_logfile = "$httpd_logdir/${real_vhost}-access_log" + $real_access_logfile = "${httpd_logdir}/${real_vhost}-access_log" } else { $real_access_logfile = $access_logfile } if ! $error_logfile { - $real_error_logfile = "$httpd_logdir/${real_vhost}-error_log" + $real_error_logfile = "${httpd_logdir}/${real_vhost}-error_log" } else { $real_error_logfile = $error_logfile } @@ -34,7 +35,7 @@ define apache::vhost::base ($content = '', if $wildcard_sslcert != true { openssl::self_signed_cert{ $real_vhost: directory => '/etc/ssl/apache/', - before => Apache::Config["/etc/httpd/conf/vhosts.d/$filename"], + before => Apache::Config["/etc/httpd/conf/vhosts.d/${filename}"], } } } @@ -43,8 +44,7 @@ define apache::vhost::base ($content = '', include apache::mod::public_html } - apache::config { "/etc/httpd/conf/vhosts.d/$filename": + apache::config { "/etc/httpd/conf/vhosts.d/${filename}": content => template('apache/vhost_base.conf') } } - diff --git a/modules/apache/manifests/vhost/catalyst_app.pp b/modules/apache/manifests/vhost/catalyst_app.pp index 54a00fb2..1ce40747 100644 --- a/modules/apache/manifests/vhost/catalyst_app.pp +++ b/modules/apache/manifests/vhost/catalyst_app.pp @@ -2,12 +2,22 @@ define apache::vhost::catalyst_app( $script, $location = '', $process = 4, $use_ssl = false, + $aliases = {}, $vhost = false) { - include apache::mod::fastcgi + include apache::mod::fcgid + if ($location) { + $aliases['/static'] = "${location}/root/static" + } + + $script_aliases = { + '/' => "$script/", + } + apache::vhost::base { $name: vhost => $vhost, use_ssl => $use_ssl, - content => template('apache/vhost_catalyst_app.conf'), + content => template('apache/vhost_fcgid.conf'), + aliases => $aliases, } } diff --git a/modules/apache/manifests/vhost/django_app.pp b/modules/apache/manifests/vhost/django_app.pp index 5613e384..91974acd 100644 --- a/modules/apache/manifests/vhost/django_app.pp +++ b/modules/apache/manifests/vhost/django_app.pp @@ -11,8 +11,8 @@ define apache::vhost::django_app ($module = false, # module is a ruby reserved keyword, cannot be used in templates $django_module = $module - file { "$name.wsgi": - path => "/usr/local/lib/wsgi/$name.wsgi", + file { "${name}.wsgi": + path => "/usr/local/lib/wsgi/${name}.wsgi", mode => '0755', notify => Service['apache'], content => template('apache/django.wsgi'), diff --git a/modules/apache/manifests/vhost/other_app.pp b/modules/apache/manifests/vhost/other_app.pp index 69b3ec56..f5a71574 100644 --- a/modules/apache/manifests/vhost/other_app.pp +++ b/modules/apache/manifests/vhost/other_app.pp @@ -1,6 +1,6 @@ define apache::vhost::other_app($vhost_file) { include apache::base - apache::config { "/etc/httpd/conf/vhosts.d/$name.conf": + apache::config { "/etc/httpd/conf/vhosts.d/${name}.conf": content => template($vhost_file), } } diff --git a/modules/apache/manifests/vhost/redirect_ssl.pp b/modules/apache/manifests/vhost/redirect_ssl.pp index 3458d59d..22a4d4f6 100644 --- a/modules/apache/manifests/vhost/redirect_ssl.pp +++ b/modules/apache/manifests/vhost/redirect_ssl.pp @@ -1,5 +1,5 @@ define apache::vhost::redirect_ssl() { - apache::vhost::base { "redirect_ssl_$name": + apache::vhost::base { "redirect_ssl_${name}": vhost => $name, content => template('apache/vhost_ssl_redirect.conf') } diff --git a/modules/apache/manifests/vhost/reverse_proxy.pp b/modules/apache/manifests/vhost/reverse_proxy.pp index a6570c2f..a32aaff0 100644 --- a/modules/apache/manifests/vhost/reverse_proxy.pp +++ b/modules/apache/manifests/vhost/reverse_proxy.pp @@ -1,6 +1,7 @@ define apache::vhost::reverse_proxy($url, $vhost = false, - $use_ssl = false) { + $use_ssl = false, + $content = '') { include apache::mod::proxy apache::vhost::base { $name: use_ssl => $use_ssl, diff --git a/modules/apache/manifests/webapp_other.pp b/modules/apache/manifests/webapp_other.pp index 277558b5..147a2370 100644 --- a/modules/apache/manifests/webapp_other.pp +++ b/modules/apache/manifests/webapp_other.pp @@ -1,7 +1,7 @@ define apache::webapp_other($webapp_file) { include apache::base $webappname = $name - apache::config { "/etc/httpd/conf/webapps.d/$webappname.conf": + apache::config { "/etc/httpd/conf/webapps.d/${webappname}.conf": content => template($webapp_file), } } diff --git a/modules/apache/templates/00_default_vhosts.conf b/modules/apache/templates/00_default_vhosts.conf index 25f59b5e..9a5f586c 100644 --- a/modules/apache/templates/00_default_vhosts.conf +++ b/modules/apache/templates/00_default_vhosts.conf @@ -3,5 +3,13 @@ <Location /> Allow from all </Location> - Redirect / http://www.<%= domain %>/ + <%- + default_redirect = scope.lookupvar('apache::var::default_vhost_redirect') + if default_redirect == '' + -%> + Redirect 404 / + ErrorDocument 404 "Page Not Found" + <%- else -%> + Redirect / <%= default_redirect %> + <%- end -%> </VirtualHost> diff --git a/modules/apache/templates/01_default_ssl_vhost.conf b/modules/apache/templates/01_default_ssl_vhost.conf index d2aa9f94..323bf145 100644 --- a/modules/apache/templates/01_default_ssl_vhost.conf +++ b/modules/apache/templates/01_default_ssl_vhost.conf @@ -15,7 +15,7 @@ # General setup for the virtual host DocumentRoot "/var/www/html" #ServerName localhost:443 -ServerAdmin root@<%= domain %> +ServerAdmin root@<%= @domain %> ErrorLog logs/ssl_error_log <IfModule mod_log_config.c> @@ -29,17 +29,19 @@ SSLEngine on # SSL Cipher Suite: # List the ciphers that the client is permitted to negotiate. # See the mod_ssl documentation for a complete list. -SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW +SSLHonorCipherOrder On +SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS + # SSL Protocol support: # List the enable protocol levels with which clients will be able to -# connect. Disable SSLv2 access by default: -SSLProtocol all -SSLv2 +# connect. Disable SSLv2/v3 access by default: +SSLProtocol ALL -SSLv2 -SSLv3 -<%- if wildcard_sslcert == 'true' then -%> -SSLCertificateFile /etc/ssl/wildcard.<%= domain %>.crt -SSLCertificateKeyFile /etc/ssl/wildcard.<%= domain %>.key -SSLCACertificateFile /etc/ssl/wildcard.<%= domain %>.pem +<%- if @wildcard_sslcert == 'true' then -%> +SSLCertificateFile /etc/ssl/wildcard.<%= @domain %>.crt +SSLCertificateKeyFile /etc/ssl/wildcard.<%= @domain %>.key +SSLCACertificateFile /etc/ssl/wildcard.<%= @domain %>.pem SSLVerifyClient None <%- else -%> SSLCertificateFile /etc/ssl/apache/localhost.pem diff --git a/modules/apache/templates/50_mod_deflate.conf b/modules/apache/templates/50_mod_deflate.conf new file mode 100644 index 00000000..5192bf6e --- /dev/null +++ b/modules/apache/templates/50_mod_deflate.conf @@ -0,0 +1,36 @@ +<IfModule mod_deflate.c> + # Compress HTML, CSS, JavaScript, JSON, Text, XML and fonts + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/json + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/vnd.ms-fontobject + AddOutputFilterByType DEFLATE application/x-font + AddOutputFilterByType DEFLATE application/x-font-opentype + AddOutputFilterByType DEFLATE application/x-font-otf + AddOutputFilterByType DEFLATE application/x-font-truetype + AddOutputFilterByType DEFLATE application/x-font-ttf + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE font/opentype + AddOutputFilterByType DEFLATE font/otf + AddOutputFilterByType DEFLATE font/ttf + AddOutputFilterByType DEFLATE image/svg+xml + AddOutputFilterByType DEFLATE image/x-icon + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/xml + + # Level of compression (9=highest compression level) + DeflateCompressionLevel 1 + + # Do not compress certain file types + SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|heif|heic|webp|mp4|mov|mpg|webm|avi)$ no-gzip dont-vary + SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|xz|zst|lzo|lzma|sit|rar|cab|rpm)$ no-gzip dont-vary + SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary + + # Make sure proxies don't deliver the wrong content + Header append Vary User-Agent env=!dont-vary +</IfModule> diff --git a/modules/apache/templates/django.wsgi b/modules/apache/templates/django.wsgi index aa0b82c8..2188e1e7 100644 --- a/modules/apache/templates/django.wsgi +++ b/modules/apache/templates/django.wsgi @@ -6,8 +6,8 @@ if path not in sys.path: sys.path.append(path) <%- end -%> -<%- if django_module -%> -os.environ['DJANGO_SETTINGS_MODULE'] = '<%= django_module %>.settings' +<%- if @django_module -%> +os.environ['DJANGO_SETTINGS_MODULE'] = '<%= @django_module %>.settings' <%- else -%> os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' <%- end -%> diff --git a/modules/apache/templates/logrotate b/modules/apache/templates/logrotate index f84ae9fe..823989eb 100644 --- a/modules/apache/templates/logrotate +++ b/modules/apache/templates/logrotate @@ -1,13 +1,23 @@ /var/log/httpd/*_log /var/log/httpd/apache_runtime_status /var/log/httpd/ssl_mutex { - rotate <%= httpdlogs_rotate %> +<% if @hostname == 'duvel' %> + rotate 60 + daily +<% elsif @hostname == 'friteuse' %> + # The virtual disk is very small so keep log sizes down + rotate 26 + weekly +<% elsif @hostname == 'sucuk' %> + rotate 52 + weekly +<% else %> + rotate <%= scope.lookupvar('apache::var::httpdlogs_rotate') %> monthly +<% end %> missingok notifempty + sharedscripts compress - prerotate - /etc/rc.d/init.d/httpd closelogs > /dev/null 2>&1 || : - endscript postrotate - /etc/rc.d/init.d/httpd closelogs > /dev/null 2>&1 || : + /bin/systemctl restart httpd.service > /dev/null 2>/dev/null || true endscript } diff --git a/modules/apache/templates/mod/php.conf b/modules/apache/templates/mod/php.conf index 6d64ffb8..8bc20078 100644 --- a/modules/apache/templates/mod/php.conf +++ b/modules/apache/templates/mod/php.conf @@ -1,5 +1,5 @@ # as php insist to have this value set, let's # look on the system for him -php_value date.timezone "<%= php_date_timezone %>" -php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f root@<%= domain %>" +php_value date.timezone "<%= @php_date_timezone %>" +php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f root@<%= @domain %>" diff --git a/modules/apache/templates/mod/ssl.conf b/modules/apache/templates/mod/ssl_vhost.conf index bcfe8201..bcfe8201 100644 --- a/modules/apache/templates/mod/ssl.conf +++ b/modules/apache/templates/mod/ssl_vhost.conf diff --git a/modules/apache/templates/mod/wsgi.conf b/modules/apache/templates/mod/wsgi.conf index 0ecba31a..18678bc6 100644 --- a/modules/apache/templates/mod/wsgi.conf +++ b/modules/apache/templates/mod/wsgi.conf @@ -1,4 +1,4 @@ -# http://code.google.com/p/modwsgi/wiki/ApplicationIssues +# https://code.google.com/p/modwsgi/wiki/ApplicationIssues # mainly for viewvc at the moment , when doing a diff WSGIRestrictStdout Off # again viewvc : @@ -7,6 +7,6 @@ WSGIRestrictStdout Off # WSGIRestrictSignal Off # reenabled, as this prevent apache from restarting properly -# make sure transifex client work fine, as we need wsgi to pass autorisation +# make sure transifex client work fine, as we need wsgi to pass authorisation # header to django ( otherwise, this just show error 401 ) WSGIPassAuthorization On diff --git a/modules/apache/templates/no_hidden_file_dir.conf b/modules/apache/templates/no_hidden_file_dir.conf new file mode 100644 index 00000000..dce78912 --- /dev/null +++ b/modules/apache/templates/no_hidden_file_dir.conf @@ -0,0 +1,4 @@ +# +# dont serve up any hidden files or dirs like .git*, .svn, ... +# +RedirectMatch 404 /\..*$ diff --git a/modules/apache/templates/urlescape b/modules/apache/templates/urlescape new file mode 100644 index 00000000..8feb7fa4 --- /dev/null +++ b/modules/apache/templates/urlescape @@ -0,0 +1,9 @@ +#!/usr/bin/python3 -u +# URL escape each path given on stdin +import sys +import urllib.parse +while True: + l = sys.stdin.readline() + if not l: + break + print(urllib.parse.quote(l.rstrip("\n"))) diff --git a/modules/apache/templates/vhost_base.conf b/modules/apache/templates/vhost_base.conf index 2d89dccc..da26b683 100644 --- a/modules/apache/templates/vhost_base.conf +++ b/modules/apache/templates/vhost_base.conf @@ -1,4 +1,4 @@ -<%- if use_ssl then +<%- if @use_ssl then port = 443 else port = 80 @@ -6,28 +6,19 @@ end -%> <VirtualHost *:<%= port %>> -<%- if use_ssl then -%> - SSLEngine on - <%- if wildcard_sslcert == 'true' then -%> - SSLCertificateFile /etc/ssl/wildcard.<%= domain %>.crt - SSLCertificateKeyFile /etc/ssl/wildcard.<%= domain %>.key - SSLCACertificateFile /etc/ssl/wildcard.<%= domain %>.pem - SSLVerifyClient None - <%- else -%> - SSLCertificateFile /etc/ssl/apache/<%= real_vhost %>.pem - SSLCertificateKeyFile /etc/ssl/apache/<%= real_vhost %>.pem - <%- end -%> +<%- if @use_ssl then -%> +<%= scope.function_template(["apache/vhost_ssl.conf"]) %> <%- end -%> - ServerName <%= real_vhost %> -<%- server_aliases.each do |key| -%> + ServerName <%= @real_vhost %> +<%- @server_aliases.each do |key| -%> ServerAlias <%= key %> <%- end -%> - DocumentRoot <%= location %> + DocumentRoot <%= @location %> - CustomLog <%= real_access_logfile %> combined - ErrorLog <%= real_error_logfile %> + CustomLog <%= @real_access_logfile %> combined + ErrorLog <%= @real_error_logfile %> -<%- if enable_public_html -%> +<%- if @enable_public_html -%> #TODO add the rest UserDir public_html <%- else -%> @@ -36,20 +27,27 @@ end </IfModule> <%- end -%> -<%- aliases.keys.sort {|a,b| a.size <=> b.size }.reverse.each do |key| -%> - Alias <%= key %> <%= aliases[key] %> +<%- @aliases.keys.sort {|a,b| a.size <=> b.size }.reverse.each do |key| -%> + Alias <%= key %> <%= @aliases[key] %> <%- end -%> - <%= content %> + <%= @content %> -<%- if options.length > 0 -%> - <Directory <%= location %>> - Options <%= options.join(" ") %> +<%- if @options.length > 0 -%> + <Directory <%= @location %>> + Options <%= @options.join(" ") %> </Directory> <%- end -%> +<%- if @enable_location -%> <Location /> - Allow from all + <IfModule mod_authz_core.c> + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + Allow from all + </IfModule> </Location> +<%- end -%> </VirtualHost> diff --git a/modules/apache/templates/vhost_catalyst_app.conf b/modules/apache/templates/vhost_catalyst_app.conf deleted file mode 100644 index eaa652d7..00000000 --- a/modules/apache/templates/vhost_catalyst_app.conf +++ /dev/null @@ -1,5 +0,0 @@ -<%- if location != '' then -%> -Alias /static <%= location %>/root/static -<%- end -%> -Alias / <%= script %>/ -FastCgiServer <%= script %> -processes <%= process %> -idle-timeout 30 diff --git a/modules/apache/templates/vhost_django_app.conf b/modules/apache/templates/vhost_django_app.conf index 3310045e..d85cf7a9 100644 --- a/modules/apache/templates/vhost_django_app.conf +++ b/modules/apache/templates/vhost_django_app.conf @@ -1 +1 @@ -WSGIScriptAlias / /usr/local/lib/wsgi/<%= name %>.wsgi +WSGIScriptAlias / /usr/local/lib/wsgi/<%= @name %>.wsgi diff --git a/modules/apache/templates/vhost_fcgid.conf b/modules/apache/templates/vhost_fcgid.conf new file mode 100644 index 00000000..fefa4a49 --- /dev/null +++ b/modules/apache/templates/vhost_fcgid.conf @@ -0,0 +1,6 @@ +AddHandler fcgid-script .pl +<%- @script_aliases.keys.sort {|a,b| a.size <=> b.size }.reverse.each do |key| -%> + ScriptAlias <%= key %> <%= @script_aliases[key] %> +<%- end -%> +FcgidMinProcessesPerClass <%= @process %> +FcgidIdleTimeout 30 diff --git a/modules/apache/templates/vhost_fcgid_norobot.conf b/modules/apache/templates/vhost_fcgid_norobot.conf new file mode 100644 index 00000000..0643cac9 --- /dev/null +++ b/modules/apache/templates/vhost_fcgid_norobot.conf @@ -0,0 +1,45 @@ +AddHandler fcgid-script .pl +<%- @script_aliases.keys.sort {|a,b| a.size <=> b.size }.reverse.each do |key| -%> + ScriptAlias <%= key %> <%= @script_aliases[key] %> +<%- end -%> +FcgidMinProcessesPerClass <%= @process %> +FcgidIdleTimeout 30 + +# These robots were scraping the whole of svnweb in 2024-04, causing severe +# load, so they are banned. It's not clear whether they obey robots.txt or +# not (we didn't give them enough of a chance to find out), so we could +# consider giving them a chance to redeem themselves at some point in the +# future. +RewriteEngine on +RewriteCond %{HTTP_USER_AGENT} ClaudeBot|Amazonbot +RewriteRule . - [R=403,L] + +# Block expensive SVN operations on all common robots ("spider" covers a +# bunch). "Expensive" is considered to be most operations other than showing a +# directory or downloading a specific version of a file. +# Note: eliminating view=log and annotate= doesn't make much difference to the +# CPU load when robots are hitting the server in real world operation. +#RewriteCond %{QUERY_STRING} pathrev=|r1= +# Treat anything other than a plain path as "expensive" +RewriteCond %{QUERY_STRING} . +RewriteCond %{HTTP_USER_AGENT} "Googlebot|GoogleOther|bingbot|Yahoo! Slurp|ClaudeBot|Amazonbot|YandexBot|SemrushBot|Barkrowler|DataForSeoBot|PetalBot|facebookexternalhit|GPTBot|ImagesiftBot|spider|Spider|iPod|Trident|Presto" +RewriteRule . - [R=403,L] + +# Only let expensive operations through when a cookie is set. If no cookie is +# set, redirect to a page where it will be set using JavaScript and redirect +# back. This will block requests from user agents that do not support +# JavaScript, which includes many robots. +RewriteMap urlescape prg:/usr/local/bin/urlescape +#RewriteCond %{QUERY_STRING} pathrev=|r1= +# Treat anything other than a plain path as "expensive" +RewriteCond %{QUERY_STRING} . +RewriteCond %{REQUEST_URI} !/_check +RewriteCond %{HTTP_COOKIE} !session=([^;]+) [novary] +RewriteRule . %{REQUEST_SCHEME}://%{SERVER_NAME}:%{SERVER_PORT}/_check?to=%{REQUEST_URI}?${urlescape:%{QUERY_STRING}} [R=302,L] + +# Block abusive spiders by IP address who don't identify themselves in the +# User-Agent: string +RewriteCond expr "-R '47.76.0.0/14' || -R '47.80.0.0/14' || -R '47.208.0.0/16' || -R '47.238.0.0/16' || -R '8.210.0.0/16' || -R '8.218.0.0/16' || -R '188.239.0.0/18' || -R '166.108.192.0/18' || -R '124.243.160.0/19' || -R '101.46.0.0/20'" +RewriteRule . - [R=403,L] + +ErrorDocument 403 "<html><body>Impolite robots are not allowed</body></html>" diff --git a/modules/apache/templates/vhost_redirect.conf b/modules/apache/templates/vhost_redirect.conf index 0f256881..c787311e 100644 --- a/modules/apache/templates/vhost_redirect.conf +++ b/modules/apache/templates/vhost_redirect.conf @@ -1,2 +1,2 @@ -Redirect / <%= url %> +Redirect / <%= @url %> diff --git a/modules/apache/templates/vhost_reverse_proxy.conf b/modules/apache/templates/vhost_reverse_proxy.conf index 23dc7545..4859bda3 100644 --- a/modules/apache/templates/vhost_reverse_proxy.conf +++ b/modules/apache/templates/vhost_reverse_proxy.conf @@ -1,3 +1,5 @@ +<%= @content %> + ProxyRequests Off ProxyPreserveHost On @@ -5,9 +7,9 @@ Order deny,allow Allow from all </Proxy> -<%- if url =~ /^https/ -%> +<%- if @url =~ /^https/ -%> SSLProxyEngine On <%- end -%> - ProxyPass / <%= url %> - ProxyPassReverse / <%= url %> + ProxyPass / <%= @url %> + ProxyPassReverse / <%= @url %> diff --git a/modules/apache/templates/vhost_simple.conf b/modules/apache/templates/vhost_simple.conf index ec39b192..77b55287 100644 --- a/modules/apache/templates/vhost_simple.conf +++ b/modules/apache/templates/vhost_simple.conf @@ -1,9 +1,14 @@ <VirtualHost *:80> - ServerName <%= name %> - DocumentRoot <%= location %> + ServerName <%= @name %> + DocumentRoot <%= @location %> <Location /> - Allow from all + <IfModule mod_authz_core.c> + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + Allow from all + </IfModule> </Location> </VirtualHost> diff --git a/modules/apache/templates/vhost_ssl.conf b/modules/apache/templates/vhost_ssl.conf new file mode 100644 index 00000000..0cb52eca --- /dev/null +++ b/modules/apache/templates/vhost_ssl.conf @@ -0,0 +1,13 @@ + SSLEngine on + SSLProtocol ALL -SSLv2 -SSLv3 + SSLHonorCipherOrder On + SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS + <%- if @wildcard_sslcert == 'true' then -%> + SSLCertificateFile /etc/ssl/wildcard.<%= @domain %>.crt + SSLCertificateKeyFile /etc/ssl/wildcard.<%= @domain %>.key + SSLCACertificateFile /etc/ssl/wildcard.<%= @domain %>.pem + SSLVerifyClient None + <%- else -%> + SSLCertificateFile /etc/ssl/apache/<%= @real_vhost %>.pem + SSLCertificateKeyFile /etc/ssl/apache/<%= @real_vhost %>.pem + <%- end -%> diff --git a/modules/apache/templates/vhost_ssl_redirect.conf b/modules/apache/templates/vhost_ssl_redirect.conf index d13c3093..23a7eabe 100644 --- a/modules/apache/templates/vhost_ssl_redirect.conf +++ b/modules/apache/templates/vhost_ssl_redirect.conf @@ -1 +1 @@ -Redirect / https://<%= name %>/ +Redirect / https://<%= @name %>/ diff --git a/modules/apache/templates/vhost_wsgi.conf b/modules/apache/templates/vhost_wsgi.conf index 34926411..2f1ba585 100644 --- a/modules/apache/templates/vhost_wsgi.conf +++ b/modules/apache/templates/vhost_wsgi.conf @@ -1,3 +1,3 @@ -WSGIScriptAlias / <%= wsgi_path %> +WSGIScriptAlias / <%= @wsgi_path %> diff --git a/modules/auto_installation/manifests/init.pp b/modules/auto_installation/manifests/init.pp index 1c4fbbd1..642cddfd 100644 --- a/modules/auto_installation/manifests/init.pp +++ b/modules/auto_installation/manifests/init.pp @@ -1,21 +1,21 @@ # what should be possible : -# install a base system +# install a base system # - mandriva # - mageia # - others ? ( for testing package ? ) -# install a server -# - by name, with a valstart clone +# install a server +# - by name, with a valstar clone class auto_installation { class variables { $pxe_dir = "/var/lib/pxe" # m/ for menu. There is limitation on the path length so # while we will likely not hit the limit, it may be easier - $pxe_menu_dir = "$pxe_dir/pxelinux.cfg/m/" + $pxe_menu_dir = "${pxe_dir}/pxelinux.cfg/m/" } - class download { + class download { import "download.rb" } @@ -23,77 +23,77 @@ class auto_installation { package { 'syslinux': } - + file { $pxe_dir: ensure => directory, } - file { "$pxe_dir/pxelinux.0": + file { "${pxe_dir}/pxelinux.0": ensure => "/usr/lib/syslinux/pxelinux.0", } - - file { "$pxe_dir/menu.c32": + + file { "${pxe_dir}/menu.c32": ensure => "/usr/lib/syslinux/menu.c32" } - - file { "$pxe_dir/pxelinux.cfg": + + file { "${pxe_dir}/pxelinux.cfg": ensure => directory, } - # m for menu, there is some limitation on the path lenght so I - # prefer to - file { "$pxe_menu_dir": + # m for menu, there is some limitation on the path length so I + # prefer to + file { "${pxe_menu_dir}": ensure => directory, } # TODO make it tag aware $menu_entries = list_exported_ressources('Auto_installation::Pxe_menu_base') - # default file should have exported ressources - file { "$pxe_dir/pxelinux.cfg/default": - ensure => present, + # default file should have exported resources + file { "${pxe_dir}/pxelinux.cfg/default": + ensure => present, content => template('auto_installation/default'), } - Auto_installation::Pxe_menu_base <<| tag == $fqdn |>> + Auto_installation::Pxe_menu_base <<| tag == $fqdn |>> } define pxe_menu_base($content) { include auto_installation::variables - file { "$auto_installation::variables::pxe_menu_dir/$name": - ensure => present, + file { "${auto_installation::variables::pxe_menu_dir}/${name}": + ensure => present, content => $content, } } define pxe_menu_entry($kernel_path, $append, $label) { - @@auto_installation::pxe_menu_base { $name: - tag => $fqdn, + @@auto_installation::pxe_menu_base { $name: + tag => $fqdn, content => template('auto_installation/menu'), } } - # define pxe_linux_entry + # define pxe_linux_entry # meant to be exported - # name - # label + # name + # label # kernel # append class netinst_storage { - # to ease the creation of test iso + # to ease the creation of test iso $netinst_path = "/var/lib/libvirt/netinst" file { $netinst_path: - ensure => directory, + ensure => directory, require => Package[libvirt-utils], } libvirtd::storage { "netinst": - path => $netinst_path, + path => $netinst_path, require => File[$netinst_path], } } define download_file($destination_path, $download_url) { - exec { "wget -q -O $destination_path/$name $download_url/$name": - creates => "$destination_path/$name", + exec { "wget -q -O ${destination_path}/${name} ${download_url}/${name}": + creates => "${destination_path}/${name}", } } @@ -103,36 +103,36 @@ class auto_installation { $server = "ftp.free.fr" $mirror_url_base = "/pub/Distributions_Linux/MandrivaLinux/" $mirror_url_middle = $version ? { - "cooker" => "devel/cooker/$arch/", - default => "official/$version/$arch/" + "cooker" => "devel/cooker/${arch}/", + default => "official/${version}/${arch}/" } - $mirror_url = "$mirror_url_base/$mirror_url_middle" + $mirror_url = "${mirror_url_base}/${mirror_url_middle}" $mirror_url_end = "isolinux/alt0" - $destination_path = "$netinst_storage::netinst_path/$name" + $destination_path = "${netinst_storage::netinst_path}/${name}" - file { "$destination_path": + file { "${destination_path}": ensure => directory, } - $download_url = "$protocol\\://$server/$mirror_url/$mirror_url_end" - + $download_url = "${protocol}\\://${server}/${mirror_url}/${mirror_url_end}" + download_file { ['all.rdz','vmlinuz']: destination_path => $destination_path, - download_url => $download_url, - require => File[$destination_path], + download_url => $download_url, + require => File[$destination_path], } - pxe_menu_entry { "mandriva_$version_$arch": - kernel_path => "$name/vmlinuz", - label => "Mandriva $version $arch", + pxe_menu_entry { "mandriva_${version}_${arch}": + kernel_path => "${name}/vmlinuz", + label => "Mandriva ${version} ${arch}", #TODO add autoinst.cfg - append => "$name/all.rdz useless_thing_accepted=1 lang=fr automatic=int:eth0,netw:dhcp,met:$protocol,ser:$server,dir:$mirror_url ", - } + append => "${name}/all.rdz useless_thing_accepted=1 lang=fr automatic=int:eth0,netw:dhcp,met:${protocol},ser:${server},dir:${mirror_url} ", + } } - # + # # define a template for autoinst # - basic installation # - server installation ( with server name as a parameter ) diff --git a/modules/auto_installation/templates/default b/modules/auto_installation/templates/default index f8b8e82b..a9ea8de3 100644 --- a/modules/auto_installation/templates/default +++ b/modules/auto_installation/templates/default @@ -13,5 +13,3 @@ LABEL local <% for m in menu_entries %> INCLUDE pxelinux.cfg/m/<%= m %> <% end %> - - diff --git a/modules/auto_installation/templates/menu b/modules/auto_installation/templates/menu index b7f6c910..3d0ce6fa 100644 --- a/modules/auto_installation/templates/menu +++ b/modules/auto_installation/templates/menu @@ -2,4 +2,4 @@ LABEL <%= name %> MENU DEFAULT MENU LABEL Install <%= label %> kernel <%= kernel_path %> - append <%= append %> + append <%= append %> diff --git a/modules/bcd/manifests/base.pp b/modules/bcd/manifests/base.pp index 8bee2907..d515f3e1 100644 --- a/modules/bcd/manifests/base.pp +++ b/modules/bcd/manifests/base.pp @@ -1,6 +1,6 @@ class bcd::base { include sudo - include bcd + include bcd group { $bcd::login: } diff --git a/modules/bcd/manifests/init.pp b/modules/bcd/manifests/init.pp index 81f0ef1c..1ff57144 100644 --- a/modules/bcd/manifests/init.pp +++ b/modules/bcd/manifests/init.pp @@ -1,5 +1,5 @@ class bcd { $login = 'bcd' $home = '/home/bcd' - $public_isos = "$home/public_html/isos" + $public_isos = "${home}/public_html/isos" } diff --git a/modules/bcd/manifests/rsync.pp b/modules/bcd/manifests/rsync.pp index 7b772b24..0a9ccc34 100644 --- a/modules/bcd/manifests/rsync.pp +++ b/modules/bcd/manifests/rsync.pp @@ -1,7 +1,7 @@ class bcd::rsync { include bcd::base $public_isos = $bcd::public_isos - class { rsyncd: - rsyncd_conf => 'bcd/rsyncd.conf', - } + class { 'rsyncd': + rsyncd_conf => 'bcd/rsyncd.conf', + } } diff --git a/modules/bcd/manifests/web.pp b/modules/bcd/manifests/web.pp index abfa5647..d670cf5d 100644 --- a/modules/bcd/manifests/web.pp +++ b/modules/bcd/manifests/web.pp @@ -1,15 +1,9 @@ class bcd::web { include bcd::base - $location = "$bcd::home/public_html" + $location = "${bcd::home}/public_html" - apache::vhost::base { "bcd.$::domain": + apache::vhost::base { "bcd.${::domain}": location => $location, content => template('bcd/vhost_bcd.conf'), } - - # not sure if that's useful, since the file is public and trivially - # bruteforced - file { "$bcd::home/htpasswd": - content => template('bcd/htpasswd') - } } diff --git a/modules/bcd/templates/htpasswd b/modules/bcd/templates/htpasswd deleted file mode 100644 index 457a13a7..00000000 --- a/modules/bcd/templates/htpasswd +++ /dev/null @@ -1,2 +0,0 @@ -valstar:42Mx5EawIqVTY - diff --git a/modules/bcd/templates/rsyncd.conf b/modules/bcd/templates/rsyncd.conf index 26197765..75c7d335 100644 --- a/modules/bcd/templates/rsyncd.conf +++ b/modules/bcd/templates/rsyncd.conf @@ -4,7 +4,7 @@ uid = nobody gid = nogroup [isos] - path = <%= public_isos %> + path = <%= scope.lookupvar("bcd::public_isos") %> comment = Mageia ISOs exclude = .htaccess .htpasswd read only = yes diff --git a/modules/bcd/templates/sudoers.bcd b/modules/bcd/templates/sudoers.bcd index b768f653..c462bffd 100644 --- a/modules/bcd/templates/sudoers.bcd +++ b/modules/bcd/templates/sudoers.bcd @@ -3,6 +3,8 @@ /usr/sbin/urpmi, \ /usr/sbin/urpmi.addmedia, \ /usr/sbin/urpmi.removemedia, \ +/usr/sbin/urpmi.update, \ +/usr/bin/urpmq, \ /bin/rm -%<%= isomakers_group %> ALL=(<%= scope.lookupvar('bcd::login') %>) SETENV: NOPASSWD: ALL +%<%= @isomakers_group %> ALL=(<%= scope.lookupvar('bcd::login') %>) SETENV: NOPASSWD: ALL diff --git a/modules/bcd/templates/vhost_bcd.conf b/modules/bcd/templates/vhost_bcd.conf index 536b09d5..c89955e2 100644 --- a/modules/bcd/templates/vhost_bcd.conf +++ b/modules/bcd/templates/vhost_bcd.conf @@ -1,8 +1,8 @@ -<Directory <%= location %>> +<Directory <%= @location %>> AuthUserFile <%= scope.lookupvar('bcd::home') %>/htpasswd AuthGroupFile /dev/null AuthName "QA test isos, restricted access" - ErrorDocument 403 "For the password, please contact the QA team ( http://wiki.<%= domain %>/en/QA_Team )" + ErrorDocument 403 "For the password, please contact the QA team ( https://wiki.<%= @domain %>/en/QA_Team )" AuthType Basic require valid-user diff --git a/modules/bind/manifests/master.pp b/modules/bind/manifests/master.pp index c5ea1ccc..a82d4757 100644 --- a/modules/bind/manifests/master.pp +++ b/modules/bind/manifests/master.pp @@ -2,6 +2,15 @@ class bind::master inherits bind { Tld_redirections::Domain <<| |>> $managed_tlds = list_exported_ressources('Tld_redirections::Domain') + + file { "/var/lib/named/var/named/master": + ensure => directory + } + + file { "/var/lib/named/var/named/reverse": + ensure => directory + } + File['/var/lib/named/etc/named.conf'] { content => template('bind/named_base.conf', 'bind/named_master.conf'), } diff --git a/modules/bind/manifests/zone.pp b/modules/bind/manifests/zone.pp index 24367206..17f2075e 100644 --- a/modules/bind/manifests/zone.pp +++ b/modules/bind/manifests/zone.pp @@ -1,10 +1,11 @@ define bind::zone($type, $content = false) { if ! $content { - $zone_content = template("bind/zones/$name.zone") + $zone_content = template("bind/zones/${name}.zone") } else { $zone_content = $content } - file { "/var/lib/named/var/named/$type/$name.zone": + + file { "/var/named/${type}/${name}.zone": content => $zone_content, require => Package['bind'], notify => Exec['named_reload'] diff --git a/modules/bind/templates/named_base.conf b/modules/bind/templates/named_base.conf index c066f16a..5adba9f3 100644 --- a/modules/bind/templates/named_base.conf +++ b/modules/bind/templates/named_base.conf @@ -32,7 +32,6 @@ options { version ""; directory "/var/named"; dump-file "/var/tmp/named_dump.db"; - pid-file "/var/run/named.pid"; statistics-file "/var/tmp/named.stats"; zone-statistics yes; // datasize 256M; @@ -101,37 +100,31 @@ zone "." IN { zone "localdomain" IN { type master; - file "master/localdomain.zone"; + file "named.localhost"; allow-update { none; }; }; zone "localhost" IN { type master; - file "master/localhost.zone"; + file "named.localhost"; allow-update { none; }; }; -zone "0.0.127.in-addr.arpa" IN { +zone "1.0.0.127.in-addr.arpa" IN { type master; - file "reverse/named.local"; + file "named.loopback"; allow-update { none; }; }; -zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN { +zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN { type master; - file "reverse/named.ip6.local"; - allow-update { none; }; -}; - -zone "255.in-addr.arpa" IN { - type master; - file "reverse/named.broadcast"; + file "named.loopback"; allow-update { none; }; }; zone "0.in-addr.arpa" IN { type master; - file "reverse/named.zero"; + file "named.empty"; allow-update { none; }; }; diff --git a/modules/bind/templates/named_slave.conf b/modules/bind/templates/named_slave.conf index feae30ef..b59db37f 100644 --- a/modules/bind/templates/named_slave.conf +++ b/modules/bind/templates/named_slave.conf @@ -1,7 +1,7 @@ zone "mageia.org" IN { type slave; file "slave/mageia.org"; - allow-update { 212.85.158.146; }; + allow-update { 212.85.158.151; }; }; <% @@ -11,7 +11,7 @@ for tld in managed_tlds zone "mageia.<%= tld %>" IN { type master; file "master/mageia.<= tld %>"; - allow-update { 212.85.158.146; }; + allow-update { 212.85.158.151; }; }; <% @@ -21,11 +21,11 @@ end zone "7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa" IN { type slave; file "slave/7.0.0.0.2.0.0.0.8.7.1.2.2.0.a.2.ip6.arpa.zone"; - allow-update { 212.85.158.146; }; + allow-update { 212.85.158.151; }; }; zone "2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa" IN { type slave; file "slave/2.1.0.0.0.0.0.1.b.0.e.0.1.0.a.2.ip6.arpa.zone"; - allow-update { 212.85.158.146; }; + allow-update { 212.85.158.151; }; }; diff --git a/modules/blog/manifests/init.pp b/modules/blog/manifests/init.pp index 585b5c16..c89a8168 100644 --- a/modules/blog/manifests/init.pp +++ b/modules/blog/manifests/init.pp @@ -1,9 +1,11 @@ class blog { class base { - $blog_domain = "blog.$::domain" - $blog_location = "/var/www/vhosts/$blog_domain" - $blog_db_backupdir = "/var/lib/backups/blog_db" - $blog_files_backupdir = "/var/lib/backups/blog_files" + $blog_domain = "blog.${::domain}" + $blog_location = "/var/www/vhosts/${blog_domain}" + $blog_db_backupdir = '/var/lib/backups/blog_db' + $blog_files_backupdir = '/var/lib/backups/blog_files' + $blog_newpost_email_to = "i18n-reports@ml.${::domain}" + $blog_newpost_email_from = "Mageia Blog bot <blog@${::domain}>" user { 'blog': groups => apache, @@ -11,13 +13,21 @@ class blog { home => '/var/lib/blog', } } - + class files_bots inherits base { - package { ['php-mysql', +if versioncmp($::lsbdistrelease, '9') < 0 { + package { ['php-mysqlnd', + 'php-ldap', + 'unzip', + 'nail']: } +} else { + package { ['php-mysqlnd', 'php-ldap', - 'unzip']: } + 'unzip', + 's-nail']: } +} - mga-common::local_script { 'check_new-blog-post.sh': + mga_common::local_script { 'check_new-blog-post.sh': content => template('blog/check_new-blog-post.sh'), } @@ -25,27 +35,27 @@ class blog { user => 'blog', minute => '*/15', command => '/usr/local/bin/check_new-blog-post.sh', - require => Local_script['check_new-blog-post.sh'], + require => Mga_common::Local_script['check_new-blog-post.sh'], } include apache::mod::php - apache::vhost::base { "$blog_domain": + apache::vhost::base { "${blog_domain}": location => $blog_location, - content => template('blog/blogs_vhosts.conf'), + content => template('blog/blogs_vhosts.conf'), } - apache::vhost::base { "ssl_$blog_domain": - use_ssl => true, - vhost => $blog_domain, + apache::vhost::base { "ssl_${blog_domain}": + use_ssl => true, + vhost => $blog_domain, location => $blog_location, - content => template('blog/blogs_vhosts.conf'), + content => template('blog/blogs_vhosts.conf'), } file { $blog_location: - ensure => directory, - owner => apache, - group => apache, + ensure => directory, + owner => apache, + group => apache, } } @@ -54,7 +64,7 @@ class blog { ensure => directory, } - mga-common::local_script { 'backup_blog-db.sh': + mga_common::local_script { 'backup_blog-db.sh': content => template('blog/backup_blog-db.sh'), } @@ -63,7 +73,7 @@ class blog { hour => '23', minute => '42', command => '/usr/local/bin/backup_blog-db.sh', - require => Local_script['backup_blog-db.sh'], + require => Mga_common::Local_script['backup_blog-db.sh'], } } @@ -72,7 +82,7 @@ class blog { ensure => directory, } - mga-common::local_script { 'backup_blog-files.sh': + mga_common::local_script { 'backup_blog-files.sh': content => template('blog/backup_blog-files.sh'), } @@ -81,7 +91,7 @@ class blog { hour => '23', minute => '42', command => '/usr/local/bin/backup_blog-files.sh', - require => Local_script['backup_blog-files.sh'], + require => Mga_common::Local_script['backup_blog-files.sh'], } } } diff --git a/modules/blog/templates/backup_blog-files.sh b/modules/blog/templates/backup_blog-files.sh index 3d66caa0..e268ad2b 100755 --- a/modules/blog/templates/backup_blog-files.sh +++ b/modules/blog/templates/backup_blog-files.sh @@ -1,17 +1,18 @@ -#!/bin/sh +#!/bin/bash # Initialization PATH_TO_FILE=${PATH_TO_FILE:-<%= blog_files_backupdir %>} [ ! -f $PATH_TO_FILE/count ] && echo 0 > $PATH_TO_FILE/count COUNT=$(cat "$PATH_TO_FILE/count") # Backup each locale -for locale in de el en es fr it nl pl pt ro ru tr uk +for locale in de el en es fr it nl pl pt ro ru sv tr uk do if [ ! -d $PATH_TO_FILE/$locale ] then /bin/mkdir $PATH_TO_FILE/$locale fi - tar Jcf $PATH_TO_FILE/$locale/$locale-$COUNT.tar.xz <%= blog_location %>/$locale + # use relative paths to avoid "Removing leading `/' from member names'" warning + tar -C / -Jcf "$PATH_TO_FILE/$locale/$locale-$COUNT.tar.xz" "$(sed s,^/,, <<< "<%= blog_location %>/$locale")" done # Check count file to have a week of backup in the directory if [ $COUNT -ne 6 ] diff --git a/modules/blog/templates/blogs_vhosts.conf b/modules/blog/templates/blogs_vhosts.conf index 48b6d9ad..ff3c792f 100644 --- a/modules/blog/templates/blogs_vhosts.conf +++ b/modules/blog/templates/blogs_vhosts.conf @@ -2,7 +2,7 @@ Order deny,allow Allow from All AllowOverride All - Options FollowSymlinks + Options FollowSymlinks Options +Indexes </Directory> # Add a permanent redirection for 'pt' as it was 'pt-br' before diff --git a/modules/blog/templates/check_new-blog-post.sh b/modules/blog/templates/check_new-blog-post.sh index da142fd0..f2089a52 100755 --- a/modules/blog/templates/check_new-blog-post.sh +++ b/modules/blog/templates/check_new-blog-post.sh @@ -2,14 +2,15 @@ # Initialization PATH_TO_FILE=${PATH_TO_FILE:-/var/lib/blog} -/usr/bin/wget -qO $PATH_TO_FILE"/last_tmp" http://blog.mageia.org/en/?feed=rss2 -if [ $? -ne 0 ] +/usr/bin/wget -qO $PATH_TO_FILE"/last_tmp" https://blog.mageia.org/en/?feed=rss2 +if [ $? -ne 0 ] then - exit 2 + exit 2 fi last_title=$(grep "title" $PATH_TO_FILE"/last_tmp" | head -n 2 | sed '1d' | sed 's/<title>//' | sed 's/<\/title>//' | sed 's/^[ \t]*//') last_pub=$(grep "pubDate" $PATH_TO_FILE"/last_tmp" | head -n 1 | sed 's/<pubDate>//' | sed 's/<\/pubDate>//' | sed 's/^[ \t]*//') -echo -e "$last_title\n$last_pub" > $PATH_TO_FILE"/last_tmp" +last_creator=$(grep "creator" $PATH_TO_FILE"/last_tmp" | head -n 1 | sed 's/<dc:creator>//' | sed 's/<\/dc:creator>//' | sed 's/^[ \t]*//') +echo -e "$last_title\n$last_pub\n$last_creator" > $PATH_TO_FILE"/last_tmp" # Check if 'last_entry' exists if [ ! -f $PATH_TO_FILE"/last_entry" ] @@ -22,32 +23,28 @@ fi /bin/date +"%d:%m:%Y %H:%M" > $PATH_TO_FILE"/last_check" # Check if a new blog post on EN needs to be translated on other blogs -tmp_new=$(cat $PATH_TO_FILE"/last_tmp" | sed '1d') -tmp_old=$(cat $PATH_TO_FILE"/last_entry" | sed '1d') +tmp_new=$(cat $PATH_TO_FILE"/last_tmp" | sed -n '1p') +tmp_old=$(cat $PATH_TO_FILE"/last_entry" | sed -n '1p') if [ "$tmp_old" = "$tmp_new" ] then # Nothing new - echo "NO" >> $PATH_TO_FILE"/last_check" - else - tmp_new=$(cat $PATH_TO_FILE"/last_tmp" | sed '2d') - tmp_old=$(cat $PATH_TO_FILE"/last_entry" | sed '2d') - if [ "$tmp_old" = "$tmp_new" ] + tmp_new=$(cat $PATH_TO_FILE"/last_tmp" | sed -n '2p') + tmp_old=$(cat $PATH_TO_FILE"/last_entry" | sed -n '2p') + if [ "$tmp_old" != "$tmp_new" ] then - # Modification on last post - cat $PATH_TO_FILE"/last_check" > $PATH_TO_FILE"/last_need_translation" - echo $tmp_new >> $PATH_TO_FILE"/last_need_translation" + # Modification on latest post echo "YES - Modification" >> $PATH_TO_FILE"/last_check" - echo -e "Info: the last blog post had been modified and need to be checked.\nTitle: \"$tmp_new\"\n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -s "Modification of the last entry on English Blog" mageia-blogteam@<%= domain %> + echo -e "The latest blog post has been modified and needs to be checked!\n\nTitle:\t$last_title\nAuthor:\t$last_creator\n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -r '<%= blog_newpost_email_from %>' -s "Modification of the latest entry on English Blog" <%= blog_newpost_email_to %> echo $DATE else - # New post to translate - cat $PATH_TO_FILE"/last_check" > $PATH_TO_FILE"/last_need_translation" - echo $tmp_new >> $PATH_TO_FILE"/last_need_translation" - echo "YES - New entry" >> $PATH_TO_FILE"/last_check" - echo -e "Info: a new blog post is waiting for translation.\nTitle: \"$tmp_new\"\n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -s "New entry on English Blog" mageia-blogteam@<%= domain %> - echo $DATE - fi - fi + echo "NO" >> $PATH_TO_FILE"/last_check" + fi + else + # New post to translate + echo "YES - New entry" >> $PATH_TO_FILE"/last_check" + echo -e "A new blog post is waiting for translation:\n\nTitle:\t$last_title\nAuthor:\t$last_creator\n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -r '<%= blog_newpost_email_from %>' -s "New entry on English Blog" <%= blog_newpost_email_to %> + echo $DATE +fi # Clean tmp files and copy RSS_new to RSS_old /bin/mv -f $PATH_TO_FILE"/last_tmp" $PATH_TO_FILE"/last_entry" diff --git a/modules/bugzilla-dev/manifests/init.pp b/modules/bugzilla-dev/manifests/init.pp new file mode 100755 index 00000000..c6623872 --- /dev/null +++ b/modules/bugzilla-dev/manifests/init.pp @@ -0,0 +1,81 @@ +class bugzilla-dev { + + $bugzilla_dev_location = '/usr/share/bugzilla/' + + package {['graphviz', + 'perl-Template-GD', # needed for graphical_report support + 'perl-Test-Taint', + 'perl-JSON-RPC', + 'perl-Email-MIME', + 'perl-Email-Sender', + 'Math-Random-ISAAC', + 'perl-Chart', + 'perl-PatchReader', + 'perl-ldap', + 'perl-SOAP-Lite', + 'perl-XMLRPC-Lite', + 'perl-CGI']: } + + $pgsql_password = extlookup('bugzilla_pgsql','x') + $ldap_password = extlookup('bugzilla_ldap','x') + + postgresql::remote_db_and_user { 'bugs': + description => 'Bugzilla database', + password => $pgsql_password, + } + + file { '/usr/share/bugzilla/localconfig': + group => 'apache', + mode => '0640', + content => template('bugzilla-dev/localconfig') + } + + + file { '/usr/share/bugzilla/data/params.json': + group => 'apache', + mode => '0640', + content => template('bugzilla-dev/params.json') + } + + apache::webapp_other { 'bugzilla-dev': + webapp_file => 'bugzilla-dev/webapp_bugzilla.conf', + } + + $bugs_vhost = "bugs-dev.${::domain}" + $vhost_root = '/usr/share/bugzilla' + + apache::vhost::redirect_ssl { $bugs_vhost: } + + apache::vhost::base { $bugs_vhost: + content => template('bugzilla-dev/vhost.conf'), + aliases => { '/bugzilla/' => $vhost_root }, + use_ssl => true, + location => $vhost_root, + vhost => $bugs_vhost, + } + + git::snapshot { $bugzilla_dev_location: + source => "git://git.${::domain}/web/bugs" + } + + file { 'Mageia': + ensure => directory, + path => '/usr/share/bugzilla', + group => 'apache', + recurse => true, + require => Git::Snapshot[$bugzilla_dev_location], + } + + file { '/usr/share/bugzilla/robots.txt': + group => 'apache', + mode => '0640', + content => template('bugzilla-dev/robots.txt') + } + + cron { 'collectstats': + command => '/usr/share/bugzilla/bin/collectstats.pl', + user => 'apache', + hour => 2, + minute => 30, + } +} diff --git a/modules/bugzilla-dev/templates/localconfig b/modules/bugzilla-dev/templates/localconfig new file mode 100755 index 00000000..2b7d6035 --- /dev/null +++ b/modules/bugzilla-dev/templates/localconfig @@ -0,0 +1,121 @@ +# If you are using Apache as your web server, Bugzilla can create .htaccess +# files for you, which will keep this file (localconfig) and other +# confidential files from being read over the web. +# +# If this is set to 1, checksetup.pl will create .htaccess files if +# they don't exist. +# +# If this is set to 0, checksetup.pl will not create .htaccess files. +$create_htaccess = 0; + +# The name of the group that your web server runs as. On Red Hat +# distributions, this is usually "apache". On Debian/Ubuntu, it is +# usually "www-data". +# +# If you have use_suexec turned on below, then this is instead the name +# of the group that your web server switches to to run cgi files. +# +# If this is a Windows machine, ignore this setting, as it does nothing. +# +# If you do not have access to the group your scripts will run under, +# set this to "". If you do set this to "", then your Bugzilla installation +# will be _VERY_ insecure, because some files will be world readable/writable, +# and so anyone who can get local access to your machine can do whatever they +# want. You should only have this set to "" if this is a testing installation +# and you cannot set this up any other way. YOU HAVE BEEN WARNED! +# +# If you set this to anything other than "", you will need to run checksetup.pl +# as root or as a user who is a member of the specified group. +$webservergroup = 'apache'; + +# Set this to 1 if Bugzilla runs in an Apache SuexecUserGroup environment. +# +# If your web server runs control panel software (cPanel, Plesk or similar), +# or if your Bugzilla is to run in a shared hosting environment, then you are +# almost certainly in an Apache SuexecUserGroup environment. +# +# If this is a Windows box, ignore this setting, as it does nothing. +# +# If set to 0, checksetup.pl will set file permissions appropriately for +# a normal webserver environment. +# +# If set to 1, checksetup.pl will set file permissions so that Bugzilla +# works in a SuexecUserGroup environment. +$use_suexec = 0; + +# What SQL database to use. Default is mysql. List of supported databases +# can be obtained by listing Bugzilla/DB directory - every module corresponds +# to one supported database and the name of the module (before ".pm") +# corresponds to a valid value for this variable. +$db_driver = 'pg'; + +# The DNS name or IP address of the host that the database server runs on. +$db_host = 'pg.mageia.org'; + +# The name of the database. For Oracle, this is the database's SID. For +# SQLite, this is a name (or path) for the DB file. +$db_name = 'bugs'; + +# Who we connect to the database as. +$db_user = 'bugs'; + +# Enter your database password here. It's normally advisable to specify +# a password for your bugzilla database user. +# If you use apostrophe (') or a backslash (\) in your password, you'll +# need to escape it by preceding it with a '\' character. (\') or (\) +# (It is far simpler to just not use those characters.) +$db_pass = '<%= pgsql_password %>'; + +# Sometimes the database server is running on a non-standard port. If that's +# the case for your database server, set this to the port number that your +# database server is running on. Setting this to 0 means "use the default +# port for my database server." +$db_port = 0; + +# MySQL Only: Enter a path to the unix socket for MySQL. If this is +# blank, then MySQL's compiled-in default will be used. You probably +# want that. +$db_sock = ''; + +# Should checksetup.pl try to verify that your database setup is correct? +# With some combinations of database servers/Perl modules/moonphase this +# doesn't work, and so you can try setting this to 0 to make checksetup.pl +# run. +$db_check = 1; + +# Path to a PEM file with a list of trusted SSL CA certificates. +# The file must be readable by web server user. +$db_mysql_ssl_ca_file = ''; + +# Path to a directory containing trusted SSL CA certificates in PEM format. +# Directory and files inside must be readable by the web server user. +$db_mysql_ssl_ca_path = ''; + +# Full path to the client SSL certificate in PEM format we will present to the DB server. +# The file must be readable by web server user. +$db_mysql_ssl_client_cert = ''; + +# Full path to the private key corresponding to the client SSL certificate. +# The file must not be password-protected and must be readable by web server user. +$db_mysql_ssl_client_key = ''; + +# Most web servers will allow you to use index.cgi as a directory +# index, and many come preconfigured that way, but if yours doesn't +# then you'll need an index.html file that provides redirection +# to index.cgi. Setting $index_html to 1 below will allow +# checksetup.pl to create an index.html for you if it doesn't exist. +# NOTE: checksetup.pl will not replace an existing file, so if you +# wish to have checksetup.pl create one for you, you must +# make sure that index.html doesn't already exist. +$index_html = 0; + +# If you want to use the "Difference Between Two Patches" feature of the +# Patch Viewer, please specify the full path to the "interdiff" executable +# here. +$interdiffbin = '/usr/bin/interdiff'; + +# For the "Difference Between Two Patches" feature to work, we need to know +# what directory the "diff" bin is in. (You only need to set this if you +# are using that feature of the Patch Viewer.) +$diffpath = '/usr/bin'; + diff --git a/modules/bugzilla-dev/templates/params.json b/modules/bugzilla-dev/templates/params.json new file mode 100644 index 00000000..b51b4c00 --- /dev/null +++ b/modules/bugzilla-dev/templates/params.json @@ -0,0 +1,104 @@ +{ + "LDAPBaseDN" : "ou=People,<%= dc_suffix %>", + "LDAPbinddn" : "cn=bugzilla-alamut,ou=System Accounts,<%= dc_suffix %>:<%= ldap_password %>", + "LDAPfilter" : "", + "LDAPmailattribute" : "mail", + "LDAPserver" : "ldap.<%= domain %>", + "LDAPstarttls" : "1", + "LDAPuidattribute" : "uid", + "RADIUS_NAS_IP" : "", + "RADIUS_email_suffix" : "", + "RADIUS_secret" : "", + "RADIUS_server" : "", + "ajax_user_autocompletion" : "1", + "allow_attachment_deletion" : "0", + "allow_attachment_display" : "1", + "allowbugdeletion" : "0", + "allowemailchange" : "0", + "allowuserdeletion" : "0", + "announcehtml" : "", + "attachment_base" : "", + "auth_env_email" : "", + "auth_env_id" : "", + "auth_env_realname" : "", + "chartgroup" : "editbugs", + "collapsed_comment_tags" : "obsolete, spam", + "comment_taggers_group" : "editbugs", + "commentonchange_resolution" : "1", + "commentonduplicate" : "0", + "confirmuniqueusermatch" : "1", + "cookiedomain" : "", + "cookiepath" : "/", + "createemailregexp" : ".*", + "debug_group" : "editbugs", + "default_search_limit" : "500", + "defaultopsys" : "Linux", + "defaultplatform" : "All", + "defaultpriority" : "Normal", + "defaultquery" : "bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailassigned_to1=1&emailassigned_to2=1&emailreporter2=1&emailcc2=1&emailqa_contact2=1&order=Importance&long_desc_type=substring", + "defaultseverity" : "normal", + "duplicate_or_move_bug_status" : "RESOLVED", + "emailregexp" : "^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$", + "emailregexpdesc" : "A legal address must contain exactly one '@', and at least one '.' after the @.", + "emailsuffix" : "", + "font_file" : "", + "globalwatchers" : "bugs-dev@ml.mageia.org", + "inbound_proxies" : "", + "insidergroup" : "secteam", + "last_visit_keep_days" : "10", + "letsubmitterchoosemilestone" : "1", + "letsubmitterchoosepriority" : "1", + "mail_delivery_method" : "SMTP", + "mailfrom" : "bugzilla-daemon@<%= domain %>", + "maintainer" : "sysadmin@group.<%= domain %>", + "makeproductgroups" : "0", + "max_search_results" : "10000", + "maxattachmentsize" : "1000", + "maxlocalattachment" : "0", + "maxusermatches" : "1000", + "memcached_namespace" : "bugzilla:", + "memcached_servers" : "", + "musthavemilestoneonaccept" : "0", + "mybugstemplate" : "buglist.cgi?bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&email1=%userid%&field0-0-0=bug_status&type0-0-0=notequals&value0-0-0=UNCONFIRMED&field0-0-1=reporter&type0-0-1=equals&value0-0-1=%userid%", + "noresolveonopenblockers" : "0", + "or_groups" : "0", + "password_check_on_login" : "1", + "password_complexity" : "no_constraints", + "proxy_url" : "", + "querysharegroup" : "editbugs", + "quip_list_entry_control" : "open", + "rememberlogin" : "on", + "requirelogin" : "0", + "search_allow_no_criteria" : "0", + "shadowdb" : "", + "shadowdbhost" : "", + "shadowdbport" : "3306", + "shadowdbsock" : "", + "shutdownhtml" : "", + "smtp_debug" : "0", + "smtp_password" : "", + "smtp_ssl" : "0", + "smtp_username" : "", + "smtpserver" : "localhost", + "ssl_redirect" : "1", + "sslbase" : "https://bugs-dev.<%= domain %>/", + "strict_isolation" : "0", + "strict_transport_security" : "off", + "timetrackinggroup" : "", + "upgrade_notification" : "latest_stable_release", + "urlbase" : "http://bugs-dev.<%= domain %>/", + "use_mailer_queue" : "0", + "use_see_also" : "1", + "useclassification" : "0", + "usemenuforusers" : "0", + "useqacontact" : "1", + "user_info_class" : "CGI", + "user_verify_class" : "LDAP", + "usestatuswhiteboard" : "1", + "usetargetmilestone" : "1", + "usevisibilitygroups" : "0", + "utf8" : "1", + "webdotbase" : "/usr/bin/dot", + "webservice_email_filter" : "0", + "whinedays" : "0" +} diff --git a/modules/bugzilla/templates/robots.txt b/modules/bugzilla-dev/templates/robots.txt index 63639f02..63639f02 100644..100755 --- a/modules/bugzilla/templates/robots.txt +++ b/modules/bugzilla-dev/templates/robots.txt diff --git a/modules/bugzilla-dev/templates/vhost.conf b/modules/bugzilla-dev/templates/vhost.conf new file mode 100755 index 00000000..79eab9fb --- /dev/null +++ b/modules/bugzilla-dev/templates/vhost.conf @@ -0,0 +1,2 @@ +RewriteEngine On +RewriteRule ^/([0-9]+)$ /show_bug.cgi?id=$1 [R=301,L] diff --git a/modules/bugzilla-dev/templates/webapp_bugzilla.conf b/modules/bugzilla-dev/templates/webapp_bugzilla.conf new file mode 100755 index 00000000..a8f37a00 --- /dev/null +++ b/modules/bugzilla-dev/templates/webapp_bugzilla.conf @@ -0,0 +1,73 @@ +<% +path_data_directory = "/var/lib/bugzilla" +%> + +<Directory /usr/share/bugzilla/> + AddHandler cgi-script .cgi + Options +ExecCGI +FollowSymLinks + DirectoryIndex index.cgi index.html + AllowOverride All +</Directory> + +# The duplicates.rdf must be accessible, as it is used by +# duplicates.xul +<Directory <%= path_data_directory %>> + <Files duplicates.rdf> + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> + </Files> +</Directory> + +# The png files locally created locally must be accessible +<Directory <%= path_data_directory %>/webdot> + <FilesMatch \.png$> + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> + </FilesMatch> +</Directory> + +Alias /graphs/ <%= path_data_directory %>/graphs/ +<Directory <%= path_data_directory %>/graphs> + <FilesMatch \.png$> + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> + </FilesMatch> +</Directory> + +# This should work automatically, but perhaps something +# in our Bugzilla packaging breaks this? +Alias /extensions/Mageia/web/ <%= scope.lookupvar("bugzilla::extension_location") %>/web/ +<Directory <%= scope.lookupvar("bugzilla::extension_location") %>/web/> + <FilesMatch \.png$> + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> + </FilesMatch> +</Directory> diff --git a/modules/bugzilla/manifests/init.pp b/modules/bugzilla/manifests/init.pp index 2acb1d95..e66ddf0e 100644..100755 --- a/modules/bugzilla/manifests/init.pp +++ b/modules/bugzilla/manifests/init.pp @@ -1,71 +1,202 @@ class bugzilla { - $bugzilla_location = '/usr/share/bugzilla/template/en/custom' + $bugzilla_location = '/usr/share/bugzilla' - package {['bugzilla', - 'bugzilla-extension-sitemap', - 'graphviz', + package {['graphviz', 'perl-Template-GD', # needed for graphical_report support 'perl-Test-Taint', - 'perl-JSON-RPC']: } + 'perl-JSON-RPC', + 'perl-JSON-XS', + 'perl-Email-MIME', + 'perl-Email-Sender', + 'perl-Math-Random-ISAAC', + 'perl-Chart', + 'perl-PatchReader', + 'perl-ldap', + 'perl-SOAP-Lite', + 'perl-XMLRPC-Lite', + 'perl-CGI', + 'perl-HTML-Scrubber', + 'perl-Encode-Detect', + 'perl-File-MimeInfo', + 'perl-Email-Reply', + 'perl-HTML-FormatText-WithLinks', + 'perl-Cache-Memcached', + 'perl-File-Copy-Recursive', + 'perl-Daemon-Generic']: } $pgsql_password = extlookup('bugzilla_pgsql','x') $ldap_password = extlookup('bugzilla_ldap','x') + $bugzilla_secret_key = extlookup('bugzilla_secret_key','x') postgresql::remote_db_and_user { 'bugs': description => 'Bugzilla database', password => $pgsql_password, } - file { '/etc/bugzilla/localconfig': + file { "$bugzilla_location/localconfig": group => 'apache', mode => '0640', - content => template('bugzilla/localconfig'), - require => Package['bugzilla'], + content => template('bugzilla/localconfig') } - file { '/var/lib/bugzilla/params': + file { "$bugzilla_location/data/params.json": group => 'apache', mode => '0640', - content => template('bugzilla/params'), - require => Package['bugzilla'], + content => template('bugzilla/params.json') + } + file { "$bugzilla_location/graphs": + ensure => directory, + owner => 'apache', + group => 'apache', + mode => '0770' } apache::webapp_other { 'bugzilla': webapp_file => 'bugzilla/webapp_bugzilla.conf', } - $bugs_vhost = "bugs.$::domain" - $vhost_root = '/usr/share/bugzilla/www' + $bugs_vhost = "bugs.${::domain}" + $vhost_root = $bugzilla_location apache::vhost::redirect_ssl { $bugs_vhost: } apache::vhost::base { $bugs_vhost: + content => template('bugzilla/vhost.conf'), aliases => { '/bugzilla/' => $vhost_root }, use_ssl => true, location => $vhost_root, vhost => $bugs_vhost, + enable_location => false, } - subversion::snapshot { $bugzilla_location: - source => 'svn://svn.mageia.org/svn/web/templates/bugzilla/trunk', - require => Package['bugzilla'], + git::snapshot { $bugzilla_location: + source => "git://git.${::domain}/web/bugs" } - file { 'custom': + file { 'Mageia': ensure => directory, - path => '/usr/share/bugzilla/template/en/custom', + path => $bugzilla_location, group => 'apache', - mode => '0640', recurse => true, - require => Subversion::Snapshot[$bugzilla_location], + require => Git::Snapshot[$bugzilla_location], } - file { '/usr/share/bugzilla/www/robots.txt': + file { ["$bugzilla_location/data", + "$bugzilla_location/data/mining"]: + ensure => directory, + owner => 'apache', + group => 'apache', + mode => '0770' + } + + file { "$bugzilla_location/data/assets": + ensure => directory, + owner => 'apache', + group => 'apache', + mode => '0770' + } + + file { "$bugzilla_location/robots.txt": group => 'apache', - mode => '0640', - content => template('bugzilla/robots.txt'), - require => Package['bugzilla-extension-sitemap'], + mode => '0640' + } + + file { "$bugzilla_location/data/bugzilla-update.xml": + owner => 'apache', + group => 'apache', + mode => '0640' } + + file { [ + "$bugzilla_location/admin.cgi", + "$bugzilla_location/attachment.cgi", + "$bugzilla_location/buglist.cgi", + "$bugzilla_location/chart.cgi", + "$bugzilla_location/colchange.cgi", + "$bugzilla_location/config.cgi", + "$bugzilla_location/createaccount.cgi", + "$bugzilla_location/describecomponents.cgi", + "$bugzilla_location/describekeywords.cgi", + "$bugzilla_location/duplicates.cgi", + "$bugzilla_location/editclassifications.cgi", + "$bugzilla_location/editfields.cgi", + "$bugzilla_location/editgroups.cgi", + "$bugzilla_location/editmilestones.cgi", + "$bugzilla_location/editproducts.cgi", + "$bugzilla_location/editusers.cgi", + "$bugzilla_location/editversions.cgi", + "$bugzilla_location/editworkflow.cgi", + "$bugzilla_location/editcomponents.cgi", + "$bugzilla_location/editflagtypes.cgi", + "$bugzilla_location/editkeywords.cgi", + "$bugzilla_location/editparams.cgi", + "$bugzilla_location/editsettings.cgi", + "$bugzilla_location/editvalues.cgi", + "$bugzilla_location/editwhines.cgi", + "$bugzilla_location/enter_bug.cgi", + "$bugzilla_location/index.cgi", + "$bugzilla_location/jsonrpc.cgi", + "$bugzilla_location/page.cgi", + "$bugzilla_location/post_bug.cgi", + "$bugzilla_location/process_bug.cgi", + "$bugzilla_location/query.cgi", + "$bugzilla_location/quips.cgi", + "$bugzilla_location/relogin.cgi", + "$bugzilla_location/reports.cgi", + "$bugzilla_location/rest.cgi", + "$bugzilla_location/search_plugin.cgi", + "$bugzilla_location/show_bug.cgi", + "$bugzilla_location/showdependencytree.cgi", + "$bugzilla_location/testagent.cgi", + "$bugzilla_location/userprefs.cgi", + "$bugzilla_location/xmlrpc.cgi", + "$bugzilla_location/report.cgi", + "$bugzilla_location/request.cgi", + "$bugzilla_location/sanitycheck.cgi", + "$bugzilla_location/show_activity.cgi", + "$bugzilla_location/showdependencygraph.cgi", + "$bugzilla_location/summarize_time.cgi", + "$bugzilla_location/token.cgi", + "$bugzilla_location/votes.cgi", + "$bugzilla_location/checksetup.pl", + "$bugzilla_location/clean-bug-user-last-visit.pl", + "$bugzilla_location/collectstats.pl", + "$bugzilla_location/email_in.pl", + "$bugzilla_location/importxml.pl", + "$bugzilla_location/install-module.pl", + "$bugzilla_location/jobqueue.pl", + "$bugzilla_location/migrate.pl", + "$bugzilla_location/runtests.pl", + "$bugzilla_location/sanitycheck.pl", + "$bugzilla_location/testserver.pl", + "$bugzilla_location/whineatnews.pl", + "$bugzilla_location/whine.pl", + ]: + group => 'apache', + mode => '0750', + } + +# Improper file permissions makes this fail, and nobody seems to care +# cron { 'collectstats': +# command => "cd $bugzilla_location && ./collectstats.pl", +# user => 'apache', +# hour => 2, +# minute => 30, +# } + + cron { 'clean-bug-user-last-visit': + command => "cd $bugzilla_location && ./clean-bug-user-last-visit.pl", + user => 'apache', + hour => 3, + minute => 0, + } + cron { 'sanitycheck': + command => "cd $bugzilla_location && $bugzilla_location/sanitycheck.pl --login LpSolit@gmail.com", + user => 'apache', + hour => 21, + minute => 0, + } + } diff --git a/modules/bugzilla/templates/localconfig b/modules/bugzilla/templates/localconfig index 5ef4a9ab..61935552 100644 --- a/modules/bugzilla/templates/localconfig +++ b/modules/bugzilla/templates/localconfig @@ -1,51 +1,59 @@ - # If you are using Apache as your web server, Bugzilla can create .htaccess -# files for you that will instruct Apache not to serve files that shouldn't -# be accessed from the web browser (like your local configuration data and non-cgi -# executable files). For this to work, the directory your Bugzilla -# installation is in must be within the jurisdiction of a <Directory> block -# in the httpd.conf file that has 'AllowOverride Limit' in it. If it has -# 'AllowOverride All' or other options with Limit, that's fine. -# (Older Apache installations may use an access.conf file to store these -# <Directory> blocks.) -# If this is set to 1, Bugzilla will create these files if they don't exist. -# If this is set to 0, Bugzilla will not create these files. -$create_htaccess = 0; - -# Usually, this is the group your web server runs as. -# If you have a Windows box, ignore this setting. -# If you have use_suexec switched on below, this is the group Apache switches -# to in order to run Bugzilla scripts. +# files for you, which will keep this file (localconfig) and other +# confidential files from being read over the web. +# +# If this is set to 1, checksetup.pl will create .htaccess files if +# they don't exist. +# +# If this is set to 0, checksetup.pl will not create .htaccess files. +$create_htaccess = 1; + +# The name of the group that your web server runs as. On Red Hat +# distributions, this is usually "apache". On Debian/Ubuntu, it is +# usually "www-data". +# +# If you have use_suexec turned on below, then this is instead the name +# of the group that your web server switches to to run cgi files. +# +# If this is a Windows machine, ignore this setting, as it does nothing. +# # If you do not have access to the group your scripts will run under, # set this to "". If you do set this to "", then your Bugzilla installation # will be _VERY_ insecure, because some files will be world readable/writable, # and so anyone who can get local access to your machine can do whatever they # want. You should only have this set to "" if this is a testing installation # and you cannot set this up any other way. YOU HAVE BEEN WARNED! +# # If you set this to anything other than "", you will need to run checksetup.pl -# asroot, or as a user who is a member of the specified group. +# as root or as a user who is a member of the specified group. $webservergroup = 'apache'; -# Set this if Bugzilla runs in an Apache SuexecUserGroup environment. -# (If your web server runs control panel software (cPanel, Plesk or similar), +# Set this to 1 if Bugzilla runs in an Apache SuexecUserGroup environment. +# +# If your web server runs control panel software (cPanel, Plesk or similar), # or if your Bugzilla is to run in a shared hosting environment, then you are -# almost certainly in an Apache SuexecUserGroup environment.) -# If you have a Windows box, ignore this setting. -# If set to 0, Bugzilla will set file permissions as tightly as possible. -# If set to 1, Bugzilla will set file permissions so that it may work in an -# SuexecUserGroup environment. The difference is that static files (CSS, -# JavaScript and so on) will receive world read permissions. +# almost certainly in an Apache SuexecUserGroup environment. +# +# If this is a Windows box, ignore this setting, as it does nothing. +# +# If set to 0, checksetup.pl will set file permissions appropriately for +# a normal webserver environment. +# +# If set to 1, checksetup.pl will set file permissions so that Bugzilla +# works in a SuexecUserGroup environment. $use_suexec = 0; # What SQL database to use. Default is mysql. List of supported databases # can be obtained by listing Bugzilla/DB directory - every module corresponds -# to one supported database and the name corresponds to a driver name. +# to one supported database and the name of the module (before ".pm") +# corresponds to a valid value for this variable. $db_driver = 'pg'; -# The DNS name of the host that the database server runs on. -$db_host = 'pgsql.<%= domain %>'; +# The DNS name or IP address of the host that the database server runs on. +$db_host = 'pg.mageia.org'; -# The name of the database +# The name of the database. For Oracle, this is the database's SID. For +# SQLite, this is a name (or path) for the DB file. $db_name = 'bugs'; # Who we connect to the database as. @@ -55,7 +63,7 @@ $db_user = 'bugs'; # a password for your bugzilla database user. # If you use apostrophe (') or a backslash (\) in your password, you'll # need to escape it by preceding it with a '\' character. (\') or (\) -# (Far simpler just not to use those characters.) +# (It is far simpler to just not use those characters.) $db_pass = '<%= pgsql_password %>'; # Sometimes the database server is running on a non-standard port. If that's @@ -70,35 +78,50 @@ $db_port = 0; $db_sock = ''; # Should checksetup.pl try to verify that your database setup is correct? -# (with some combinations of database servers/Perl modules/moonphase this -# doesn't work) +# With some combinations of database servers/Perl modules/moonphase this +# doesn't work, and so you can try setting this to 0 to make checksetup.pl +# run. $db_check = 1; -# With the introduction of a configurable index page using the -# template toolkit, Bugzilla's main index page is now index.cgi. +# Path to a PEM file with a list of trusted SSL CA certificates. +# The file must be readable by web server user. +$db_mysql_ssl_ca_file = ''; + +# Path to a directory containing trusted SSL CA certificates in PEM format. +# Directory and files inside must be readable by the web server user. +$db_mysql_ssl_ca_path = ''; + +# Full path to the client SSL certificate in PEM format we will present to the DB server. +# The file must be readable by web server user. +$db_mysql_ssl_client_cert = ''; + +# Full path to the private key corresponding to the client SSL certificate. +# The file must not be password-protected and must be readable by web server user. +$db_mysql_ssl_client_key = ''; + # Most web servers will allow you to use index.cgi as a directory # index, and many come preconfigured that way, but if yours doesn't # then you'll need an index.html file that provides redirection # to index.cgi. Setting $index_html to 1 below will allow -# checksetup.pl to create one for you if it doesn't exist. +# checksetup.pl to create an index.html for you if it doesn't exist. # NOTE: checksetup.pl will not replace an existing file, so if you # wish to have checksetup.pl create one for you, you must -# make sure that index.html doesn't already exist +# make sure that index.html doesn't already exist. $index_html = 0; -# For some optional functions of Bugzilla (such as the pretty-print patch -# viewer), we need the cvs binary to access files and revisions. -# Because it's possible that this program is not in your path, you can specify -# its location here. Please specify the full path to the executable. -$cvsbin = '/usr/bin/cvs'; - -# For some optional functions of Bugzilla (such as the pretty-print patch -# viewer), we need the interdiff binary to make diffs between two patches. -# Because it's possible that this program is not in your path, you can specify -# its location here. Please specify the full path to the executable. +# If you want to use the "Difference Between Two Patches" feature of the +# Patch Viewer, please specify the full path to the "interdiff" executable +# here. $interdiffbin = '/usr/bin/interdiff'; -# The interdiff feature needs diff, so we have to have that path. -# Please specify the directory name only; do not use trailing slash. +# For the "Difference Between Two Patches" feature to work, we need to know +# what directory the "diff" bin is in. (You only need to set this if you +# are using that feature of the Patch Viewer.) $diffpath = '/usr/bin'; +# This secret key is used by your installation for the creation and +# validation of encrypted tokens. These tokens are used to implement +# security features in Bugzilla, to protect against certain types of attacks. +# A random string is generated by default. It's very important that this key +# is kept secret. It also must be very long. +$site_wide_secret = '<%= bugzilla_secret_key %>'; diff --git a/modules/bugzilla/templates/params b/modules/bugzilla/templates/params index 0be18af3..2e71a39d 100644 --- a/modules/bugzilla/templates/params +++ b/modules/bugzilla/templates/params @@ -1,6 +1,6 @@ %param = ( 'LDAPBaseDN' => 'ou=People,<%= dc_suffix %>', - 'LDAPbinddn' => 'cn=bugzilla-<%= hostname %>,ou=System Accounts,<%= dc_suffix %>:<%= ldap_password %>', + 'LDAPbinddn' => 'cn=bugzilla-alamut,ou=System Accounts,<%= dc_suffix %>:<%= ldap_password %>', 'LDAPfilter' => '', 'LDAPmailattribute' => 'mail', 'LDAPserver' => 'ldap.<%= domain %>', @@ -10,6 +10,7 @@ 'RADIUS_email_suffix' => '', 'RADIUS_secret' => '', 'RADIUS_server' => '', + 'ajax_user_autocompletion' => '1', 'allow_attach_url' => 0, 'allow_attachment_deletion' => 0, 'allow_attachment_display' => 1, @@ -29,28 +30,31 @@ 'confirmuniqueusermatch' => 1, 'cookiedomain' => '', 'cookiepath' => '/', - 'createemailregexp' => '.*', - 'cvsroot' => '', - 'cvsroot_get' => '', - 'defaultopsys' => 'Linux', - 'defaultplatform' => 'i586', - 'defaultpriority' => 'Normal', - 'defaultquery' => 'bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailassigned_to1=1&emailassigned_to2=1&emailreporter2=1&emailcc2=1&emailqa_contact2=1&order=Importance&long_desc_type=substring', - 'defaultseverity' => 'normal', - 'docs_urlbase' => ' http://www.bugzilla.org/docs/3.6/en/html/', + 'createemailregexp' => '.*', + 'cvsroot' => '', + 'cvsroot_get' => '', + 'debug_group' => 'editbugs', + 'default_search_limit' => '500', + 'defaultopsys' => 'Linux', + 'defaultplatform' => 'All', + 'defaultpriority' => 'Normal', + 'defaultquery' => 'bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailassigned_to1=1&emailassigned_to2=1&emailreporter2=1&emailcc2=1&emailqa_contact2=1&order=Importance&long_desc_type=substring', + 'defaultseverity' => 'normal', + 'docs_urlbase' => ' https://www.bugzilla.org/docs/4.4/en/html/', 'duplicate_or_move_bug_status' => 'RESOLVED', 'emailregexp' => '^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$', 'emailregexpdesc' => 'A legal address must contain exactly one \'@\', and at least one \'.\' after the @.', 'emailsuffix' => '', 'globalwatchers' => 'bugs@ml.<%= domain %>', 'inbound_proxies' => '', - 'insidergroup' => '', + 'insidergroup' => 'secteam', 'letsubmitterchoosemilestone' => 1, 'letsubmitterchoosepriority' => 1, 'lxr_root' => '', 'lxr_url' => '', 'mail_delivery_method' => 'SMTP', - 'mailfrom' => 'bugzilla-daemon@<%= domain %>', + 'mailfrom' => 'bugzilla_noreply@ml.<%= domain %>', + 'maintainer' => 'sysadmin@group.<%= domain %>', 'makeproductgroups' => 0, 'maxattachmentsize' => '1000', 'maxlocalattachment' => '0', @@ -72,23 +76,23 @@ 'quip_list_entry_control' => 'open', 'rememberlogin' => 'on', 'requirelogin' => '0', + 'search_allow_no_criteria' => '0', 'sendmailnow' => 1, - 'shadowdb' => '', - 'shadowdbhost' => '', - 'shadowdbport' => '3306', - 'shadowdbsock' => '', - 'shutdownhtml' => '', - 'smtp_debug' => 0, - 'smtp_password' => '', - 'smtp_username' => '', - 'smtpserver' => 'localhost', - 'specific_search_allow_empty_words' => 1, - 'ssl_redirect' => 1, - 'sslbase' => 'https://bugs.<%= domain %>/', - 'strict_isolation' => 0, - 'timetrackinggroup' => '', + 'shadowdb' => '', + 'shadowdbhost' => '', + 'shadowdbport' => '3306', + 'shadowdbsock' => '', + 'smtp_debug' => 0, + 'smtp_password' => '', + 'smtp_username' => '', + 'smtpserver' => 'localhost', + 'specific_search_allow_empty_words' => 1, + 'ssl_redirect' => 1, + 'sslbase' => 'https://bugs.<%= domain %>/', + 'strict_isolation' => 0, + 'timetrackinggroup' => '', 'upgrade_notification' => 'latest_stable_release', - 'urlbase' => 'http://bugs.<%= domain %>/', + 'urlbase' => 'https://bugs.<%= domain %>/', 'use_mailer_queue' => 0, 'use_see_also' => 1, 'usebugaliases' => 0, diff --git a/modules/bugzilla/templates/params.json b/modules/bugzilla/templates/params.json new file mode 100644 index 00000000..05325bc7 --- /dev/null +++ b/modules/bugzilla/templates/params.json @@ -0,0 +1,104 @@ +{ + "LDAPBaseDN" : "ou=People,<%= dc_suffix %>", + "LDAPbinddn" : "cn=bugzilla-alamut,ou=System Accounts,<%= dc_suffix %>:<%= ldap_password %>", + "LDAPfilter" : "", + "LDAPmailattribute" : "mail", + "LDAPserver" : "ldap.<%= domain %>", + "LDAPstarttls" : "1", + "LDAPuidattribute" : "uid", + "RADIUS_NAS_IP" : "", + "RADIUS_email_suffix" : "", + "RADIUS_secret" : "", + "RADIUS_server" : "", + "ajax_user_autocompletion" : "1", + "allow_attachment_deletion" : "0", + "allow_attachment_display" : "1", + "allowbugdeletion" : "0", + "allowemailchange" : "0", + "allowuserdeletion" : "0", + "announcehtml" : "", + "attachment_base" : "", + "auth_env_email" : "", + "auth_env_id" : "", + "auth_env_realname" : "", + "chartgroup" : "editbugs", + "collapsed_comment_tags" : "obsolete, spam, off-topic", + "comment_taggers_group" : "editbugs", + "commentonchange_resolution" : "1", + "commentonduplicate" : "0", + "confirmuniqueusermatch" : "1", + "cookiedomain" : "", + "cookiepath" : "/", + "createemailregexp" : ".*", + "debug_group" : "admin", + "default_search_limit" : "500", + "defaultopsys" : "Linux", + "defaultplatform" : "All", + "defaultpriority" : "Normal", + "defaultquery" : "resolution=---&emailassigned_to1=1&emailassigned_to2=1&emailreporter2=1&emailcc2=1&emailqa_contact2=1&emaillongdesc3=1&order=Importance&long_desc_type=substring", + "defaultseverity" : "normal", + "duplicate_or_move_bug_status" : "RESOLVED", + "emailregexp" : "^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$", + "emailregexpdesc" : "A legal address must contain exactly one '@', and at least one '.' after the @.", + "emailsuffix" : "", + "font_file" : "", + "globalwatchers" : "bugs@ml.mageia.org", + "inbound_proxies" : "", + "insidergroup" : "secteam", + "last_visit_keep_days" : "60", + "letsubmitterchoosemilestone" : "1", + "letsubmitterchoosepriority" : "1", + "mail_delivery_method" : "SMTP", + "mailfrom" : "bugzilla_noreply@ml.<%= domain %>", + "maintainer" : "sysadmin@group.<%= domain %>", + "makeproductgroups" : "0", + "max_search_results" : "10000", + "maxattachmentsize" : "1000", + "maxlocalattachment" : "0", + "maxusermatches" : "1000", + "memcached_namespace" : "bugzilla:", + "memcached_servers" : "", + "musthavemilestoneonaccept" : "0", + "mybugstemplate" : "buglist.cgi?resolution=---&emailassigned_to1=1&emailreporter1=1&emailtype1=exact&email1=%userid%", + "noresolveonopenblockers" : "0", + "or_groups" : "0", + "password_check_on_login" : "1", + "password_complexity" : "no_constraints", + "proxy_url" : "", + "querysharegroup" : "editbugs", + "quip_list_entry_control" : "open", + "rememberlogin" : "on", + "requirelogin" : "0", + "search_allow_no_criteria" : "0", + "shadowdb" : "", + "shadowdbhost" : "", + "shadowdbport" : "3306", + "shadowdbsock" : "", + "shutdownhtml" : "", + "smtp_debug" : "0", + "smtp_password" : "", + "smtp_ssl" : "0", + "smtp_username" : "", + "smtpserver" : "localhost", + "ssl_redirect" : "1", + "sslbase" : "https://bugs.<%= domain %>/", + "strict_isolation" : "0", + "strict_transport_security" : "off", + "timetrackinggroup" : "", + "upgrade_notification" : "latest_stable_release", + "urlbase" : "https://bugs.<%= domain %>/", + "use_mailer_queue" : "0", + "use_see_also" : "1", + "useclassification" : "0", + "usemenuforusers" : "0", + "useqacontact" : "1", + "user_info_class" : "CGI", + "user_verify_class" : "LDAP", + "usestatuswhiteboard" : "1", + "usetargetmilestone" : "1", + "usevisibilitygroups" : "0", + "utf8" : "1", + "webdotbase" : "/usr/bin/dot", + "webservice_email_filter" : "0", + "whinedays" : "0" +} diff --git a/modules/bugzilla/templates/vhost.conf b/modules/bugzilla/templates/vhost.conf new file mode 100644 index 00000000..fd55e5f2 --- /dev/null +++ b/modules/bugzilla/templates/vhost.conf @@ -0,0 +1,14 @@ +RewriteEngine On +RewriteRule ^/([0-9]+)$ /show_bug.cgi?id=$1 [R=301,L] + + <Directory /usr/share/bugzilla> + Require all granted + </Directory> + + + <Directory /usr/share/bugzilla> + AllowOverride all + AddHandler cgi-script .cgi + Options +ExecCGI +FollowSymLinks + DirectoryIndex index.cgi index.html + </Directory> diff --git a/modules/bugzilla/templates/webapp_bugzilla.conf b/modules/bugzilla/templates/webapp_bugzilla.conf index 16e94168..d2e3f395 100644 --- a/modules/bugzilla/templates/webapp_bugzilla.conf +++ b/modules/bugzilla/templates/webapp_bugzilla.conf @@ -1,37 +1,11 @@ <% -path_data_directory = "/var/lib/bugzilla" +path_data_directory = "/usr/share/bugzilla/" %> -<Directory /usr/share/bugzilla/www> - Order allow,deny - Allow from all - - Options ExecCGI - DirectoryIndex index.cgi -</Directory> - -# The duplicates.rdf must be accessible, as it is used by -# duplicates.xul -<Directory <%= path_data_directory %>> - <Files duplicates.rdf> - Order allow,deny - Allow from all - </Files> +<Directory <%= path_data_directory %> > + AddHandler cgi-script .cgi + Options +ExecCGI +FollowSymLinks + DirectoryIndex index.cgi index.html + AllowOverride All </Directory> -# The png files locally created locally must be accessible -<Directory <%= path_data_directory %>/webdot> - <FilesMatch \.png$> - Order allow,deny - Allow from all - </FilesMatch> -</Directory> - -Alias /graphs/ <%= path_data_directory %>/graphs/ -<Directory <%= path_data_directory %>/graphs> - - <FilesMatch \.png$> - Order allow,deny - Allow from all - </FilesMatch> -</Directory> diff --git a/modules/buildsystem/files/Mageia.pm b/modules/buildsystem/files/Mageia.pm index 109aeb29..443f6cb7 100644 --- a/modules/buildsystem/files/Mageia.pm +++ b/modules/buildsystem/files/Mageia.pm @@ -225,7 +225,7 @@ sub _get_distribution_paths { my $arch = $package->get_arch(); $arch = $translate_arch{$arch} || $arch; if ($arch eq 'noarch') { - map { "$target/$_" } $self->get_extra_arches; + map { "$target/$_" } $self->get_target_arches($target); } elsif ($arch eq 'src') { die "no way to get distribution path using a $arch package"; } else { @@ -264,26 +264,7 @@ sub get_replaced_packages { my @replaced_packages = $self->SUPER::get_replaced_packages($package, $target, $user_context, $app_context); - # mandriva lib policy: - # library package names change with revision, making mandatory to - # duplicate older revisions search with a custom pattern my $name = $package->get_name(); - if ($name =~ /^(lib\w+[a-zA-Z_])[\d_\.]+([-\w]*)$/) { - push(@replaced_packages, - grep { $package->compare($_) > 0 } - map { PACKAGE_CLASS->new(file => $_) } - $self->get_files( - $self->{_install_root}, - $self->get_install_path($package, $target, $user_context, $app_context), - PACKAGE_CLASS->get_pattern( - $1 . '[\d_\.]+' . $2, # custom name pattern - undef, - undef, - $package->get_arch() - ), - ) - ); - } # kernel packages have the version in the name # binary dkms built for old kernels have to be removed too @@ -454,13 +435,14 @@ sub get_upload_newer_revisions { my ($self, $package, $target, $user_context, $app_context) = @_; croak "Not a class method" unless ref $self; my $arch = $package->get_arch(); - my $name = $package->get_full_name; + my $name = $package->as_string(); $name =~ s/^\@\d+://; my $pattern = $self->get_package_class()->get_pattern($package->get_name(), undef, undef, $arch); my $media = $self->_get_media_config($target); my @packages; foreach my $state (@{$self->{_upload_state}}) { foreach my $m (keys %{$media->{$arch}}) { + next if defined($user_context->{section}) and $user_context->{section} ne $m; my $path = "$self->{_upload_root}/$state/$target/$m"; print "Looking for package $package revisions for $target in $path (pattern $pattern)\n" if $self->{_verbose}; find( @@ -498,35 +480,6 @@ sub get_svn_url { $self->{_svn} } -sub get_revisions { - my ($self, $package, $target, $user_context, $app_context, $filter) = @_; - croak "Not a class method" unless ref $self; - print "Looking for package $package revisions for $target\n" if $self->{_verbose} > 0; - - my $arch = $app_context->{arch} || $user_context->{arch} || $package->get_arch(); - my $media_arch = $arch eq 'noarch' ? $self->{_noarch} : $arch; - my $path = $arch eq 'src' ? "$target/SRPMS/" : "$target/$media_arch/media"; - my $media = $self->_get_section($package, $target, $user_context, $app_context); - my $name = $package->get_name(); - my @packages = map { $self->get_package_class()->new(file => $_) } - $self->get_files( - $self->{_install_root}, - "$path/$media", - $self->get_package_class()->get_pattern( - $name, - undef, - undef, - $package->get_arch(), - ) - ); - - @packages = grep { $filter->($_) } @packages if $filter; - - return - sort { $b->compare($a) } # sort by revision order - @packages; -} - sub reject { my ($self, $package, $target, $user_context, $app_context) = @_; croak "Not a class method" unless ref $self; diff --git a/modules/buildsystem/templates/signbot/mga-signpackage b/modules/buildsystem/files/signbot/mga-signpackage index bd88efeb..199dbe0e 100755 --- a/modules/buildsystem/templates/signbot/mga-signpackage +++ b/modules/buildsystem/files/signbot/mga-signpackage @@ -16,7 +16,7 @@ sub signpackage { my $sign = RPM4::Sign->new( name => $name, path => $path, - passphrase => '', + passphrase => '', ); $sign->rpmssign($file) diff --git a/modules/buildsystem/templates/signbot/sign-check-package b/modules/buildsystem/files/signbot/sign-check-package index fc9704fd..fc9704fd 100644 --- a/modules/buildsystem/templates/signbot/sign-check-package +++ b/modules/buildsystem/files/signbot/sign-check-package diff --git a/modules/buildsystem/templates/signbot/signbot-rpmmacros b/modules/buildsystem/files/signbot/signbot-rpmmacros index aab7e389..aab7e389 100644 --- a/modules/buildsystem/templates/signbot/signbot-rpmmacros +++ b/modules/buildsystem/files/signbot/signbot-rpmmacros diff --git a/modules/buildsystem/lib/puppet/parser/functions/group_members.rb b/modules/buildsystem/lib/puppet/parser/functions/group_members.rb deleted file mode 100644 index c5cecbe8..00000000 --- a/modules/buildsystem/lib/puppet/parser/functions/group_members.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'etc' -# group_members($group) -# -> return a array with the login of the group members - -module Puppet::Parser::Functions - newfunction(:group_members, :type => :rvalue) do |args| - group = args[0] - return Etc.getgrnam(group).mem - end -end diff --git a/modules/buildsystem/manifests/base.pp b/modules/buildsystem/manifests/base.pp deleted file mode 100644 index 8befa33d..00000000 --- a/modules/buildsystem/manifests/base.pp +++ /dev/null @@ -1,4 +0,0 @@ -class buildsystem::base { - $packagers_group = 'mga-packagers' - $packagers_committers_group = 'mga-packagers-committers' -} diff --git a/modules/buildsystem/manifests/binrepo.pp b/modules/buildsystem/manifests/binrepo.pp index 037352a0..5bf16b53 100644 --- a/modules/buildsystem/manifests/binrepo.pp +++ b/modules/buildsystem/manifests/binrepo.pp @@ -1,29 +1,29 @@ class buildsystem::binrepo { - include buildsystem::base + include buildsystem::var::binrepo + include buildsystem::var::groups include sudo - $login = 'binrepo' - $homedir = "/var/lib/$login" - $repodir = "$homedir/data" - $uploadinfosdir = "$homedir/infos" - $uploadbinpath = '/usr/local/bin/upload-bin' - $uploadmail_from = "root@$::domain" - $uploadmail_to = "packages-commits@ml.$::domain" - - # used in templates - $packagers_committers_group = $buildsystem::base::packagers_committers_group + # upload-bin script uses the mailx command provided by nail +if versioncmp($::lsbdistrelease, '9') < 0 { + package { 'nail': + ensure => installed, + } +} else { + package { 's-nail': + ensure => installed, + } +} - user { $login: - comment => 'Binary files repository', - home => $homedir, + user { $buildsystem::var::binrepo::login: + home => $buildsystem::var::binrepo::homedir, } - file { [$repodir, $uploadinfosdir]: + file { [$buildsystem::var::binrepo::repodir, $buildsystem::var::binrepo::uploadinfosdir]: ensure => directory, - owner => $login, + owner => $buildsystem::var::binrepo::login, } - mga-common::local_script { + mga_common::local_script { 'upload-bin': content => template('buildsystem/binrepo/upload-bin'); 'wrapper.upload-bin': @@ -34,8 +34,15 @@ class buildsystem::binrepo { content => template('buildsystem/binrepo/sudoers.binrepo') } - apache::vhost::base { "binrepo.$::domain": - location => $repodir, + apache::vhost::base { $buildsystem::var::binrepo::hostname: + location => $buildsystem::var::binrepo::repodir, + content => template('buildsystem/binrepo/vhost_binrepo.conf'), + } + + apache::vhost::base { "ssl_${buildsystem::var::binrepo::hostname}": + use_ssl => true, + vhost => $buildsystem::var::binrepo::hostname, + location => $buildsystem::var::binrepo::repodir, content => template('buildsystem/binrepo/vhost_binrepo.conf'), } } diff --git a/modules/buildsystem/manifests/buildnode.pp b/modules/buildsystem/manifests/buildnode.pp index bf898f32..1573c093 100644 --- a/modules/buildsystem/manifests/buildnode.pp +++ b/modules/buildsystem/manifests/buildnode.pp @@ -1,11 +1,12 @@ class buildsystem::buildnode { - include buildsystem::base include buildsystem::iurt - include buildsystem::scheduler::var + include buildsystem::var::scheduler + include buildsystem::var::iurt include buildsystem::sshkeys - # permit to scheduler to run iurt - ssh::auth::server { $buildsystem::scheduler::var::login: - user => $buildsystem::iurt::user::login, + sshkeys::set_authorized_keys { 'iurt-allow-scheduler': + keyname => $buildsystem::var::scheduler::login, + home => $buildsystem::var::iurt::homedir, + user => $buildsystem::var::iurt::login, } } diff --git a/modules/buildsystem/manifests/config.pp b/modules/buildsystem/manifests/config.pp deleted file mode 100644 index b038da21..00000000 --- a/modules/buildsystem/manifests/config.pp +++ /dev/null @@ -1,10 +0,0 @@ -class buildsystem::config( - architectures = ['i586', 'x86_64'], - dev_distros = ['cauldron'], - stable_distros = ['1', '2'], - distrosections = ['core', 'nonfree', 'tainted'], - sectionsrepos = ['release', 'updates', 'updates_testing', 'backports', - 'backports_testing'] -) -{ -} diff --git a/modules/buildsystem/manifests/create_upload_dir.rb b/modules/buildsystem/manifests/create_upload_dir.rb index dd30d00d..8023ab5d 100644 --- a/modules/buildsystem/manifests/create_upload_dir.rb +++ b/modules/buildsystem/manifests/create_upload_dir.rb @@ -1,22 +1,25 @@ -define "create_upload_dir", :owner, :group, :releases do +hostclass "buildsystem::create_upload_dir" do states = ["todo","done","failure","queue","rejected"] + owner = scope.lookupvar('buildsystem::var::scheduler::login') + group = owner + uploads_dir = scope.lookupvar('buildsystem::var::scheduler::homedir') + '/uploads' - file @name, :ensure => 'directory', :owner => @owner, :group => @group + file uploads_dir, :ensure => 'directory', :owner => owner, :group => group for st in states do - file [@name, st].join('/'), :ensure => 'directory', :owner => @owner, :group => @group - - @releases.each{|rel, repositories| - file [@name, st, rel].join('/'), :ensure => 'directory', :owner => @owner, :group => @group - - repositories.each{|rep, medias| - file [@name, st, rel, rep].join('/'), :ensure => 'directory', :owner => @owner, :group => @group - - for med in medias do + file [uploads_dir, st].join('/'), :ensure => 'directory', :owner => owner, :group => group + + scope.lookupvar('buildsystem::var::distros::distros').each{|rel, distro| + file [uploads_dir, st, rel].join('/'), :ensure => 'directory', :owner => owner, :group => group + medias = distro['medias'] + medias.each{|media, m| + file [uploads_dir, st, rel, media].join('/'), :ensure => 'directory', :owner => owner, :group => group + + for repo in m['repos'].keys do if st == 'done' - file [@name, st, rel, rep, med].join('/'), :ensure => 'directory', :owner => @owner, :group => @group, :mode => 0775 + file [uploads_dir, st, rel, media, repo].join('/'), :ensure => 'directory', :owner => owner, :group => group, :mode => 0775 else - file [@name, st, rel, rep, med].join('/'), :ensure => 'directory', :owner => @owner, :group => @group + file [uploads_dir, st, rel, media, repo].join('/'), :ensure => 'directory', :owner => owner, :group => group end end } diff --git a/modules/buildsystem/manifests/distros.rb b/modules/buildsystem/manifests/distros.rb new file mode 100644 index 00000000..a298c0a8 --- /dev/null +++ b/modules/buildsystem/manifests/distros.rb @@ -0,0 +1,97 @@ +hostclass "buildsystem::distros" do + mirror_user = 'root' + schedbot_user = scope.lookupvar('buildsystem::var::scheduler::login') + bootstrap_reporoot = scope.lookupvar('buildsystem::var::repository::bootstrap_reporoot') + scope.lookupvar('buildsystem::var::distros::distros').each{|rel, distro| + file [ bootstrap_reporoot, rel ].join('/'), :ensure => 'directory', + :owner => mirror_user, :group => mirror_user + for arch in distro['arch'] do + # As ruby dsl cannot use defined resources, we have to use a + # workaround with 'find_resource_type' as described in this + # puppet issue: http://projects.puppetlabs.com/issues/11912 + scope.find_resource_type 'buildsystem::media_cfg' + media_cfg_args = { + :distro_name => rel, + :arch => arch, + } + if distro['tmpl_media.cfg'] != nil + media_cfg_args['templatefile'] = distro['tmpl_media.cfg'] + end + if ! distro['no_media_cfg_update'] + create_resource 'buildsystem::media_cfg', + [ rel, ' ', arch ].join('/'), media_cfg_args + end + file [ bootstrap_reporoot, rel, arch ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + mediadir = [ bootstrap_reporoot, rel, arch, 'media' ].join('/') + file mediadir, :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, 'media_info' ].join('/'), :ensure => 'directory', + :owner => schedbot_user, :group => schedbot_user + file [ mediadir, 'debug' ].join('/'), :ensure => 'directory', + :owner => schedbot_user, :group => schedbot_user + distro['medias'].each{|media, m| + file [ mediadir, media ].join('/'), :ensure => 'directory', + :owner => schedbot_user, :group => schedbot_user + file [ mediadir, 'debug', media ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + for repo in m['repos'].keys do + file [ mediadir, media, repo ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, media, repo, 'media_info' ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, media, repo, 'repodata' ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, 'debug', media, repo ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, 'debug', media, repo, 'media_info' ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + file [ mediadir, 'debug', media, repo, 'repodata' ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + end + } + if distro['based_on'] != nil + distro['based_on'].each{|bdistroname, medias| + file [ mediadir, bdistroname ].join('/'), + :ensure => 'directory', :owner => mirror_user, + :group => mirror_user + medias.each{|medianame, media| + mdir = [ mediadir, bdistroname, medianame ].join('/') + file mdir, :ensure => 'directory', + :owner => mirror_user, :group => mirror_user + for reponame in media + file [ mdir, reponame ].join('/'), + :ensure => 'link', + :target => [ + '../../../../..', bdistroname, arch, + 'media', medianame, reponame ].join('/'), + :owner => mirror_user, :group => mirror_user + end + } + } + end + end + # SRPMS + srpmsdir = [ bootstrap_reporoot, rel, 'SRPMS' ].join('/') + file srpmsdir, + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + distro['medias'].each{|media, m| + file [ srpmsdir, media ].join('/'), :ensure => 'directory', + :owner => schedbot_user, :group => schedbot_user + for repo in m['repos'].keys do + file [ srpmsdir, media, repo ].join('/'), + :ensure => 'directory', :owner => schedbot_user, + :group => schedbot_user + end + } + } +end diff --git a/modules/buildsystem/manifests/init.pp b/modules/buildsystem/manifests/init.pp index 65b38b62..f15b5dbf 100644 --- a/modules/buildsystem/manifests/init.pp +++ b/modules/buildsystem/manifests/init.pp @@ -1,18 +1,2 @@ class buildsystem { - # A script to copy on valstar the 2010.1 rpms built on jonund - class sync20101 inherits base { - $build_login = $buildsystem::iurt::user::login - # TODO user iurt::user::homedir too - mga-common::local_script { 'sync2010.1': - content => template('buildsystem/sync2010.1'), - } - } - - # a script to build 2010.1 packages. used on jonund - class iurt20101 inherits base { - $build_login = $buildsystem::iurt::user::login - mga-common::local_script { 'iurt2010.1': - content => template('buildsystem/iurt2010.1'), - } - } } diff --git a/modules/buildsystem/manifests/iurt.pp b/modules/buildsystem/manifests/iurt.pp index e0856a23..231c5373 100644 --- a/modules/buildsystem/manifests/iurt.pp +++ b/modules/buildsystem/manifests/iurt.pp @@ -2,13 +2,11 @@ class buildsystem::iurt { include sudo include buildsystem::iurt::user include buildsystem::iurt::packages - $login = $buildsystem::iurt::user::login - $homedir = $buildsystem::iurt::user::homedir - - ssh::auth::client { $login: } + include buildsystem::var::iurt + include buildsystem::var::distros # remove old build directory - tidy { "$homedir/iurt": + tidy { "${buildsystem::var::iurt::homedir}/iurt": age => '8w', recurse => true, matches => ['[0-9][0-9].*\..*\..*\.[0-9]*','log','*.rpm','*.log','*.mga[0-9]+'], @@ -19,9 +17,10 @@ class buildsystem::iurt { ensure => directory, } - buildsystem::iurt::config { ['2','1','cauldron','mandriva2010.1','infra_1', 'infra_2']: } + $distros_list = hash_keys($buildsystem::var::distros::distros) + buildsystem::iurt::config { $distros_list: } sudo::sudoers_config { 'iurt': - content => template('buildsystem/iurt/sudoers.iurt') + content => template('buildsystem/sudoers.iurt') } } diff --git a/modules/buildsystem/manifests/iurt/config.pp b/modules/buildsystem/manifests/iurt/config.pp index 88c08b66..02f5be63 100644 --- a/modules/buildsystem/manifests/iurt/config.pp +++ b/modules/buildsystem/manifests/iurt/config.pp @@ -1,11 +1,50 @@ define buildsystem::iurt::config() { + include buildsystem::var::iurt + include buildsystem::var::webstatus + include buildsystem::var::repository $distribution = $name # TODO rename the variable too in template - $build_login = $buildsystem::iurt::user::login + $build_login = $buildsystem::var::iurt::login - file { "/etc/iurt/build/$distribution.conf": + $build_timeout = { + 'default' => 36000, + 'atlas' => 57600, + 'blender' => 57600, + 'chromium-browser-stable' => 172800, + 'clang' => 172800, + 'cross-gcc' => 115200, + 'gcc' => 115200, + 'itk' => 115200, + 'java-1.8.0-openjdk' => 172800, + 'java-17-openjdk' => 172800, + 'java-21-openjdk' => 172800, + 'java-latest-openjdk' => 172800, + 'kernel' => 115200, + 'libreoffice' => 432000, + 'llvm' => 115200, + 'llvm17-suite' => 115200, + 'llvm19-suite' => 115200, + 'openfoam' => 115200, + 'paraview' => 115200, + 'qgis' => 57600, + 'qtwebengine5' => 115200, + 'qtwebengine6' => 172800, + 'rust' => 180000, + 'salome' => 57600, + 'vtk' => 57600, + 'webkit' => 57600, + 'webkit2' => 115200, + 'wrapitk' => 115200, + 'rocm-llvm' => 70000, + } + + $allow_network_access = [ + 'libguestfs', # Needs access to the configured mirrors + ] + + file { "/etc/iurt/build/${distribution}.conf": owner => $build_login, group => $build_login, - content => template("buildsystem/iurt/$distribution.conf") + content => template("buildsystem/iurt.conf") } } diff --git a/modules/buildsystem/manifests/iurt/packages.pp b/modules/buildsystem/manifests/iurt/packages.pp index 448b4a89..e814b7c2 100644 --- a/modules/buildsystem/manifests/iurt/packages.pp +++ b/modules/buildsystem/manifests/iurt/packages.pp @@ -1,3 +1,3 @@ class buildsystem::iurt::packages { package { 'iurt': } -} +} diff --git a/modules/buildsystem/manifests/iurt/upload.pp b/modules/buildsystem/manifests/iurt/upload.pp index 8c9026c0..5417d36e 100644 --- a/modules/buildsystem/manifests/iurt/upload.pp +++ b/modules/buildsystem/manifests/iurt/upload.pp @@ -1,8 +1,7 @@ class buildsystem::iurt::upload { - $login = $buildsystem::iurt::user::login - $homedir = $buildsystem::iurt::user::homedir - $sched_login = $buildsystem::scheduler::login - + include buildsystem::var::iurt + include buildsystem::var::webstatus + include buildsystem::var::repository file { '/etc/iurt/upload.conf': require => File['/etc/iurt'], content => template('buildsystem/upload.conf'), diff --git a/modules/buildsystem/manifests/iurt/user.pp b/modules/buildsystem/manifests/iurt/user.pp index b169ee2d..a93ac7e7 100644 --- a/modules/buildsystem/manifests/iurt/user.pp +++ b/modules/buildsystem/manifests/iurt/user.pp @@ -1,10 +1,8 @@ class buildsystem::iurt::user { - $login = 'iurt' - $homedir = "/home/$login" + include buildsystem::var::iurt - buildsystem::sshuser { $login: - homedir => $homedir, - comment => 'System user used to run build bots', + buildsystem::sshuser { $buildsystem::var::iurt::login: + homedir => $buildsystem::var::iurt::homedir, } file { '/etc/iurt': diff --git a/modules/buildsystem/manifests/mainnode.pp b/modules/buildsystem/manifests/mainnode.pp index 45dff1dd..01de764f 100644 --- a/modules/buildsystem/manifests/mainnode.pp +++ b/modules/buildsystem/manifests/mainnode.pp @@ -1,5 +1,7 @@ class buildsystem::mainnode { - include buildsystem::base + include buildsystem::var::repository + include buildsystem::var::scheduler + include buildsystem::var::distros include buildsystem::iurt::user include buildsystem::scheduler include buildsystem::gatherer @@ -7,27 +9,15 @@ class buildsystem::mainnode { include buildsystem::signbot include buildsystem::youri_submit include buildsystem::sshkeys + include buildsystem::distros - $sched_login = $buildsystem::scheduler::var::login - $sched_home_dir = $buildsystem::scheduler::var::homedir - - $build_login = $buildsystem::iurt::user::login - - ssh::auth::client { $sched_login: } - - ssh::auth::server { [$sched_login, $build_login]: } - - $mirror_root = '/distrib/mirror' - apache::vhost::other_app { "repository.$::domain": - vhost_file => 'buildsystem/vhost_repository.conf', - } - - buildsystem::media_cfg { "cauldron i586": - distro => 'cauldron', - arch => 'i586', + sshkeys::set_client_key_pair { $buildsystem::var::scheduler::login: + home => $buildsystem::var::scheduler::homedir, + user => $buildsystem::var::scheduler::login, } - buildsystem::media_cfg { "cauldron x86_64": - distro => 'cauldron', - arch => 'x86_64', + sshkeys::set_authorized_keys { 'scheduler-allow-scheduler': + keyname => $buildsystem::var::scheduler::login, + home => $buildsystem::var::scheduler::homedir, + user => $buildsystem::var::scheduler::login, } } diff --git a/modules/buildsystem/manifests/maintdb.pp b/modules/buildsystem/manifests/maintdb.pp index 02782271..5a961b63 100644 --- a/modules/buildsystem/manifests/maintdb.pp +++ b/modules/buildsystem/manifests/maintdb.pp @@ -1,31 +1,27 @@ class buildsystem::maintdb { + include buildsystem::var::maintdb + include buildsystem::var::groups + include buildsystem::var::webstatus include sudo - $login = 'maintdb' - $homedir = '/var/lib/maintdb' - $dbdir = "$homedir/db" - $binpath = '/usr/local/sbin/maintdb' - $dump = '/var/www/bs/data/maintdb.txt' - $unmaintained = '/var/www/bs/data/unmaintained.txt' - user { $login: - comment => 'Maintainers database', - home => $homedir, + user { $buildsystem::var::maintdb::login: + home => $buildsystem::var::maintdb::homedir, } - file { [$homedir,$dbdir]: + file { [$buildsystem::var::maintdb::homedir,$buildsystem::var::maintdb::dbdir]: ensure => directory, - owner => $login, - group => $login, + owner => $buildsystem::var::maintdb::login, + group => $buildsystem::var::maintdb::login, mode => '0711', - require => User[$login], + require => User[$buildsystem::var::maintdb::login], } - file { $binpath: + file { $buildsystem::var::maintdb::binpath: mode => '0755', content => template('buildsystem/maintdb/maintdb.bin') } - mga-common::local_script { 'wrapper.maintdb': + mga_common::local_script { 'wrapper.maintdb': content => template('buildsystem/maintdb/wrapper.maintdb') } @@ -33,22 +29,30 @@ class buildsystem::maintdb { content => template('buildsystem/maintdb/sudoers.maintdb') } - file { [$dump,"$dump.new", - $unmaintained,"$unmaintained.new"]: - owner => $login, -# TODO uncomment once the situation with pkgsubmit module is cleared ( ie, maintdb depend on it ) -# require => File['/var/www/bs/data'], + file { [$buildsystem::var::maintdb::dump, + "${buildsystem::var::maintdb::dump}.new", + $buildsystem::var::maintdb::unmaintained, + "${buildsystem::var::maintdb::unmaintained}.new"]: + owner => $buildsystem::var::maintdb::login, + require => File["${buildsystem::var::webstatus::location}/data"], } cron { 'update maintdb export': - user => $login, - command => "$binpath root get > $dump.new; cp -f $dump.new $dump; grep ' nobody\$' $dump | sed 's/ nobody\$//' > $unmaintained.new; cp -f $unmaintained.new $unmaintained", + user => $buildsystem::var::maintdb::login, + command => "${buildsystem::var::maintdb::binpath} root get > ${buildsystem::var::maintdb::dump}.new; cp -f ${buildsystem::var::maintdb::dump}.new ${buildsystem::var::maintdb::dump}; grep ' nobody\$' ${buildsystem::var::maintdb::dump} | sed 's/ nobody\$//' > ${buildsystem::var::maintdb::unmaintained}.new; cp -f ${buildsystem::var::maintdb::unmaintained}.new ${buildsystem::var::maintdb::unmaintained}", minute => '*/30', - require => User[$login], + require => User[$buildsystem::var::maintdb::login], } - apache::vhost::base { "maintdb.$::domain": - location => $dbdir, + apache::vhost::base { $buildsystem::var::maintdb::hostname: + location => $buildsystem::var::maintdb::dbdir, + content => template('buildsystem/maintdb/vhost_maintdb.conf'), + } + + apache::vhost::base { "ssl_${buildsystem::var::maintdb::hostname}": + use_ssl => true, + vhost => $buildsystem::var::maintdb::hostname, + location => $buildsystem::var::maintdb::dbdir, content => template('buildsystem/maintdb/vhost_maintdb.conf'), } } diff --git a/modules/buildsystem/manifests/media_cfg.pp b/modules/buildsystem/manifests/media_cfg.pp index c6de0d35..77fcc8fd 100644 --- a/modules/buildsystem/manifests/media_cfg.pp +++ b/modules/buildsystem/manifests/media_cfg.pp @@ -1,10 +1,11 @@ -define buildsystem::media_cfg($distro, $arch, $templatefile = 'buildsystem/media.cfg') { - include buildsystem::scheduler::var +define buildsystem::media_cfg($distro_name, $arch, $templatefile = 'buildsystem/media.cfg') { + include buildsystem::var::repository + include buildsystem::var::scheduler include buildsystem::repository - - file { "${buildsystem::repository::dir}/distrib/${distro}/${arch}/media/media_info/media.cfg": - owner => $buildsystem::base::sched_login, - group => $buildsystem::base::sched_login, - content => template($templatefile), + + file { "${buildsystem::var::repository::bootstrap_reporoot}/${distro_name}/${arch}/media/media_info/media.cfg": + owner => $buildsystem::var::scheduler::login, + group => $buildsystem::var::scheduler::login, + content => template($templatefile), } } diff --git a/modules/buildsystem/manifests/mgarepo.pp b/modules/buildsystem/manifests/mgarepo.pp index 70b71202..14e11e1a 100644 --- a/modules/buildsystem/manifests/mgarepo.pp +++ b/modules/buildsystem/manifests/mgarepo.pp @@ -1,72 +1,36 @@ class buildsystem::mgarepo { - include buildsystem::scheduler::var - $sched_login = $buildsystem::scheduler::var::login - $sched_home_dir = $buildsystem::scheduler::var::homedir + include buildsystem::var::scheduler + include buildsystem::var::distros + include buildsystem::var::groups + include buildsystem::var::binrepo + include buildsystem::create_upload_dir + $sched_login = $buildsystem::var::scheduler::login + $sched_home_dir = $buildsystem::var::scheduler::homedir package { ['mgarepo','rpm-build']: } - file { - '/etc/mgarepo.conf': content => template('buildsystem/mgarepo.conf'); - '/etc/repsys.conf': content => template('buildsystem/mgarepo.conf'); + file { '/etc/mgarepo.conf': + content => template('buildsystem/mgarepo.conf'), } - file { "$sched_home_dir/repsys": + file { "${sched_home_dir}/repsys": ensure => 'directory', owner => $sched_login, require => File[$sched_home_dir], } - file { ["$sched_home_dir/repsys/tmp", "$sched_home_dir/repsys/srpms"]: + file { ["${sched_home_dir}/repsys/tmp", "${sched_home_dir}/repsys/srpms"]: ensure => 'directory', owner => $sched_login, - group => $buildsystem::base::packagers_group, + group => $buildsystem::var::groups::packagers, mode => '1775', - require => File["$sched_home_dir/repsys"], + require => File["${sched_home_dir}/repsys"], } - # FIXME: disabled temporarly as upload dir is a symlink to /var/lib/repsys/uploads - #file { "$sched_home_dir/uploads": + # FIXME: disabled temporarily as upload dir is a symlink to /var/lib/repsys/uploads + #file { "${sched_home_dir}/uploads": # ensure => "directory", # owner => $sched_login, # require => File[$sched_home_dir], #} - - #FIXME This config information should be moved out of this class - $releases = { - 'cauldron' => { - 'core' => ['release','updates_testing','backports_testing','backports','updates'], - 'nonfree' => ['release','updates_testing','backports_testing','backports','updates'], - 'tainted' => ['release','updates_testing','backports_testing','backports','updates'], - }, - '1' => { - 'core' => ['release','updates_testing','backports_testing','backports','updates'], - 'nonfree' => ['release','updates_testing','backports_testing','backports','updates'], - 'tainted' => ['release','updates_testing','backports_testing','backports','updates'], - }, - '2' => { - 'core' => ['release','updates_testing','backports_testing','backports','updates'], - 'nonfree' => ['release','updates_testing','backports_testing','backports','updates'], - 'tainted' => ['release','updates_testing','backports_testing','backports','updates'], - }, - 'infra_1' => { - 'infra' => ['release'] - }, - 'infra_2' => { - 'infra' => ['release'] - }, - } - - import 'create_upload_dir.rb' - create_upload_dir { "$sched_home_dir/uploads": - owner => $sched_login, - group => $sched_login, - releases => $releases, - } - - tidy { "$sched_home_dir/uploads": - type => 'ctime', - recurse => true, - age => '2w', - } - } diff --git a/modules/buildsystem/manifests/pkgsubmit.pp b/modules/buildsystem/manifests/pkgsubmit.pp deleted file mode 100644 index ba575cd2..00000000 --- a/modules/buildsystem/manifests/pkgsubmit.pp +++ /dev/null @@ -1,19 +0,0 @@ -class buildsystem::pkgsubmit { - include buildsystem::scheduler::var - $sched_home_dir = $buildsystem::scheduler::var::homedir - - $location = '/var/www/bs' - file { [$location,"$location/data"]: - ensure => directory, - } - - apache::vhost::base { "pkgsubmit.$::domain": - aliases => { '/uploads' => "$sched_home_dir/uploads" }, - location => $location, - content => template('buildsystem/vhost_pkgsubmit.conf'), - } - - subversion::snapshot { $location: - source => "svn://svn.$::domain/soft/buildsystem/web/", - } -} diff --git a/modules/buildsystem/manifests/release.pp b/modules/buildsystem/manifests/release.pp index 1682d71b..d9feac8e 100644 --- a/modules/buildsystem/manifests/release.pp +++ b/modules/buildsystem/manifests/release.pp @@ -1,7 +1,5 @@ class buildsystem::release { - subversion::snapshot { '/root/release': - source => "svn://svn.$::domain/soft/release/trunk/", + git::snapshot { '/root/release': + source => "git://git.${::domain}/software/infrastructure/release", } - - package { 'hardlink': } } diff --git a/modules/buildsystem/manifests/repoctl.pp b/modules/buildsystem/manifests/repoctl.pp index 024a4a09..8d44e52c 100644 --- a/modules/buildsystem/manifests/repoctl.pp +++ b/modules/buildsystem/manifests/repoctl.pp @@ -1,16 +1,11 @@ class buildsystem::repoctl { - include buildsystem::config + include buildsystem::var::distros + include buildsystem::var::repository - $distroreleases = [$buildsystem::config::dev_distros, - $buildsystem::config::stable_distros] - $distrosections = $buildsystem::config::distrosections - $sectionsrepos = $buildsystem::config::sectionsrepos - $arches = $buildsystem::config::architectures + package{ 'repoctl': } - package{ 'repoctl': } - - file { '/etc/repoctl.conf': - content => template('buildsystem/repoctl.conf'), - require => Package['repoctl'], - } + file { '/etc/repoctl.conf': + content => template('buildsystem/repoctl.conf'), + require => Package['repoctl'], + } } diff --git a/modules/buildsystem/manifests/repository.pp b/modules/buildsystem/manifests/repository.pp index 19e69eff..dda90eb2 100644 --- a/modules/buildsystem/manifests/repository.pp +++ b/modules/buildsystem/manifests/repository.pp @@ -1,6 +1,11 @@ class buildsystem::repository { - $dir = '/distrib/bootstrap' - file { $dir: + include buildsystem::var::repository + file { [ $buildsystem::var::repository::bootstrap_root, + $buildsystem::var::repository::bootstrap_reporoot ] : ensure => directory, - } + } + + apache::vhost::other_app { $buildsystem::var::repository::hostname: + vhost_file => 'buildsystem/vhost_repository.conf', + } } diff --git a/modules/buildsystem/manifests/scheduler.pp b/modules/buildsystem/manifests/scheduler.pp index 6facc8e9..53b248fc 100644 --- a/modules/buildsystem/manifests/scheduler.pp +++ b/modules/buildsystem/manifests/scheduler.pp @@ -1,28 +1,57 @@ class buildsystem::scheduler { - # until ulri is splitted from main iurt rpm - include ssh::auth + # until ulri is split from main iurt rpm include buildsystem::iurt::packages include buildsystem::iurt::upload - include buildsystem::scheduler::var + include buildsystem::var::scheduler - $login = $buildsystem::scheduler::var::login - $homedir = $buildsystem::scheduler::var::homedir - $logdir = $buildsystem::scheduler::var::logdir + $login = $buildsystem::var::scheduler::login + $homedir = $buildsystem::var::scheduler::homedir + $logdir = $buildsystem::var::scheduler::logdir buildsystem::sshuser { $login: homedir => $homedir, - comment => 'System user used to schedule builds', } - file { $logdir: - ensure => directory, - mode => 0755, - owner => $login, - } + file { $logdir: + ensure => directory, + mode => '0755', + owner => $login, + } + + cron { 'dispatch jobs': + user => $login, + command => "EMI_LOG_FILE=${logdir}/emi.log ULRI_LOG_FILE=${logdir}/ulri.log ulri; EMI_LOG_FILE=${logdir}/emi.log emi", + minute => '*', + } - cron { 'dispatch jobs': - user => $login, - command => "ULRI_LOG_FILE=$logdir/ulri.log ulri; EMI_LOG_FILE=$logdir/emi.log emi", - minute => '*', - } + if ($buildsystem::var::scheduler::clean_uploads_logs_age != 0) { + cron { 'clean uploads logs': + user => $login, + # Delete old upload logs + command => sprintf("/usr/bin/find %s/uploads -ignore_readdir_race -xdev -depth -type f -ctime +%d -delete", shellquote($homedir), shellquote($buildsystem::var::scheduler::clean_uploads_logs_age)), + hour => '*/4', + minute => '51', + } + cron { 'clean uploads dirs': + user => $login, + # Remove old empty uploads directories. This will take several + # passes (over several weeks) to delete a directory hierarchy + # because it is looking at ctime instead of mtime, which resets + # every time a file/directory underneath it is deleted. + # Directories don't take much space, so this shouldn't be a + # real issue. + command => sprintf("/usr/bin/find %s/uploads -ignore_readdir_race -mindepth 5 -xdev -depth -type d -ctime +%d -empty -delete", shellquote($homedir), shellquote($buildsystem::var::scheduler::clean_uploads_logs_age)), + hour => '*/4', + minute => '53', + } + } + if ($buildsystem::var::scheduler::clean_uploads_packages_age != 0) { + cron { 'clean uploads packages': + user => $login, + # Delete old upload RPMs + command => sprintf("/usr/bin/find %s/uploads -ignore_readdir_race -xdev -depth -type f -name '*.rpm' -ctime +%d -delete", shellquote($homedir), shellquote($buildsystem::var::scheduler::clean_uploads_packages_age)), + hour => '*/4', + minute => '52', + } + } } diff --git a/modules/buildsystem/manifests/scheduler/var.pp b/modules/buildsystem/manifests/scheduler/var.pp deleted file mode 100644 index e89ef634..00000000 --- a/modules/buildsystem/manifests/scheduler/var.pp +++ /dev/null @@ -1,5 +0,0 @@ -class buildsystem::scheduler::var { - $login = 'schedbot' - $homedir = "/var/lib/$login" - $logdir = "/var/log/$login" -} diff --git a/modules/buildsystem/manifests/signbot.pp b/modules/buildsystem/manifests/signbot.pp index 5e5db5d9..60c7c318 100644 --- a/modules/buildsystem/manifests/signbot.pp +++ b/modules/buildsystem/manifests/signbot.pp @@ -1,38 +1,31 @@ class buildsystem::signbot { - include buildsystem::scheduler::var - $login = 'signbot' - $home_dir = "/var/lib/$login" - $sign_keydir = "$home_dir/keys" - # FIXME: maybe keyid should be defined at an other place - $keyid = '80420F66' - $sched_login = $buildsystem::scheduler::var::login + include buildsystem::var::scheduler + include buildsystem::var::signbot + $sched_login = $buildsystem::var::scheduler::login - sshuser { $login: - homedir => $home_dir, - comment => 'System user used to sign packages', + sshuser { $buildsystem::var::signbot::login: + homedir => $buildsystem::var::signbot::home_dir, groups => [$sched_login], } gnupg::keys{ 'packages': - email => "packages@$::domain", - #FIXME there should be a variable somewhere to change - # the name of the distribution - key_name => 'Mageia Packages', - login => $login, - batchdir => "$home_dir/batches", - keydir => $sign_keydir, + email => $buildsystem::var::signbot::keyemail, + key_name => $buildsystem::var::signbot::keyname, + login => $buildsystem::var::signbot::login, + batchdir => "${buildsystem::var::signbot::home_dir}/batches", + keydir => $buildsystem::var::signbot::sign_keydir, } sudo::sudoers_config { 'signpackage': content => template('buildsystem/signbot/sudoers.signpackage') } - file { "$home_dir/.rpmmacros": - content => template('buildsystem/signbot/signbot-rpmmacros') + file { "${home_dir}/.rpmmacros": + source => 'puppet:///modules/buildsystem/signbot/signbot-rpmmacros', } - mga-common::local_script { - 'sign-check-package': content => template('buildsystem/signbot/sign-check-package'); - 'mga-signpackage': content => template('buildsystem/signbot/mga-signpackage'); + mga_common::local_script { + 'sign-check-package': source => 'puppet:///modules/buildsystem/signbot/sign-check-package'; + 'mga-signpackage': source => 'puppet:///modules/buildsystem/signbot/mga-signpackage'; } } diff --git a/modules/buildsystem/manifests/sshkeys.pp b/modules/buildsystem/manifests/sshkeys.pp index bea2959f..5a1b2900 100644 --- a/modules/buildsystem/manifests/sshkeys.pp +++ b/modules/buildsystem/manifests/sshkeys.pp @@ -1,13 +1,5 @@ class buildsystem::sshkeys { - include ssh::auth - include buildsystem::scheduler::var - include buildsystem::iurt::user + include buildsystem::var::scheduler - ssh::auth::key { $buildsystem::scheduler::var::login: - home => $buildsystem::scheduler::var::homedir, - } - - ssh::auth::key { $buildsystem::iurt::user::login: - home => $buildsystem::iurt::user::homedir - } + sshkeys::create_key { $buildsystem::var::scheduler::login: } } diff --git a/modules/buildsystem/manifests/sshuser.pp b/modules/buildsystem/manifests/sshuser.pp index 0a1cd176..5cad97ad 100644 --- a/modules/buildsystem/manifests/sshuser.pp +++ b/modules/buildsystem/manifests/sshuser.pp @@ -1,5 +1,5 @@ # $groups: array of secondary groups (only local groups, no ldap) -define buildsystem::sshuser($homedir, $comment, $groups = []) { +define buildsystem::sshuser($homedir, $comment = undef, $groups = []) { group { $name: } user { $name: @@ -9,13 +9,13 @@ define buildsystem::sshuser($homedir, $comment, $groups = []) { gid => $name, groups => $groups, shell => '/bin/bash', - notify => Exec["unlock $name"], + notify => Exec["unlock ${name}"], require => Group[$title], } # set password to * to unlock the account but forbid login through login - exec { "unlock $name": - command => "usermod -p '*' $name", + exec { "unlock ${name}": + command => "usermod -p '*' ${name}", refreshonly => true, } @@ -26,7 +26,7 @@ define buildsystem::sshuser($homedir, $comment, $groups = []) { require => User[$name], } - file { "$homedir/.ssh": + file { "${homedir}/.ssh": ensure => directory, mode => '0600', owner => $name, diff --git a/modules/buildsystem/manifests/var/binrepo.pp b/modules/buildsystem/manifests/var/binrepo.pp new file mode 100644 index 00000000..1431ed25 --- /dev/null +++ b/modules/buildsystem/manifests/var/binrepo.pp @@ -0,0 +1,15 @@ +# $uploadmail_from: +# from who will be sent the binrepo upload email notifications +# $uploadmail_to: +# where binrepo email notifications are sent +class buildsystem::var::binrepo( + $hostname = "binrepo.${::domain}", + $login = 'binrepo', + $homedir = '/var/lib/binrepo', + $uploadmail_from, + $uploadmail_to +) { + $repodir = "${homedir}/data" + $uploadinfosdir = "${homedir}/infos" + $uploadbinpath = '/usr/local/bin/upload-bin' +} diff --git a/modules/buildsystem/manifests/var/distros.pp b/modules/buildsystem/manifests/var/distros.pp new file mode 100644 index 00000000..9e45e2c2 --- /dev/null +++ b/modules/buildsystem/manifests/var/distros.pp @@ -0,0 +1,126 @@ +# $default_distro: +# the name of the default distribution +# $repo_allow_from_ips: +# $repo_allow_from_domains: +# list of IP or domains allowed to access the repository. If you don't want to +# filter allowed IPs, don't those values. +# $distros: +# a hash variable containing distributions information indexed by +# distribution name. Each distribution is itself an hash containing +# the following infos: +# { +# # the 'cauldron' distribution +# 'cauldron' => { +# # list of arch supported by 'cauldron' +# 'arch' => [ 'i586', 'x86_64' ], +# # Set this if you don't want media.cfg to be generated +# 'no_media_cfg_update' => true, +# 'medias' => { +# # the 'core' media +# 'core' => { +# 'repos' => { +# # the 'release' repo in the 'core' media +# 'release' => { +# 'media_type' => [ 'release' ], +# 'noauto' => '1', +# # the 'release' repo should be listed first in media.cfg +# 'order' => 0, +# }, +# # the 'updates' repo +# 'updates' => { +# 'media_type' => [ 'updates' ], +# 'noauto' => '1', +# # the 'updates' repo requires the 'release' repo +# 'requires' => [ 'release' ], +# # the 'updates' repo should be listed after 'release' in media.cfg +# 'order' => 1, +# }, +# }, +# # media_type for media.cfg +# 'media_type' => [ 'official', 'free' ], +# # if noauto is set to '1' either in medias or repos, +# # the option will be added to media.cfg +# 'noauto' => '1', +# # list 'core' first in media.cfg +# 'order' => 0, +# }, +# # the 'non-free' media +# 'non-free' => { +# 'repos' => { +# ... +# }, +# 'media_type' => [ 'official', 'non-free' ], +# # the 'non-free' media requires the 'core' media +# 'requires' => [ 'core' ], +# # list 'non-free' second +# 'order' => 1, +# } +# }, +# # the list of media used by iurt to build the chroots +# 'base_medias' => [ 'core/release' ], +# # optionally, a media.cfg template file can be specified, if +# # the default one should not be used +# 'tmpl_media.cfg' => 'buildsystem/something', +# # branch is Devel or Official. Used in media.cfg. +# 'branch' => 'Devel', +# # Version of the distribution +# 'version' => '3', +# # SVN Urls allowed to submit +# 'submit_allowed' => 'svn://svn.something/svn/packages/cauldron', +# # rpm macros to set when build source package +# 'macros' => { +# 'distsuffix' => '.mga', +# 'distribution' => 'Mageia', +# 'vendor' => 'Mageia.Org', +# }, +# # set this if the distro is not mirrored. This is used to add +# # an Alias in the vhost. +# 'no_mirror' => true, +# Optionally, the distribution can be based on the repos from an other +# distribution. In this example we're saying that the distribution is +# based on 2/core/release and 2/core/updates. +# 'based_on' => { +# '2' => { +# 'core' => [ 'release', 'updates' ], +# }, +# }, +# 'youri' => { +# # Configuration for youri-upload +# 'upload' => { +# # list of enabled checks, actions and posts +# 'targets' => { +# 'checks' => [ +# ... +# ], +# 'actions' => [ +# ... +# ], +# 'posts' => [ +# ... +# ], +# }, +# 'checks' => { +# # rpmlint checks options +# 'rpmlint' => { +# 'config' => '/usr/share/rpmlint/config', +# 'path' => ''/usr/bin/rpmlint', +# }, +# }, +# # options for actions +# 'actions' => { +# ... +# }, +# }, +# # Configuration for youri-todo +# 'todo' => { +# ... +# }, +# }, +# }, +# } +class buildsystem::var::distros( + $default_distro, + $repo_allow_from_ips, + $repo_allow_from_domains, + $distros, +) { } diff --git a/modules/buildsystem/manifests/var/groups.pp b/modules/buildsystem/manifests/var/groups.pp new file mode 100644 index 00000000..c0b2c917 --- /dev/null +++ b/modules/buildsystem/manifests/var/groups.pp @@ -0,0 +1,9 @@ +# $packagers: +# name of packagers group, who should be allowed to submit packages +# $packagers_committers: +# name of group of users who are allowed to commit on packages +class buildsystem::var::groups( + $packagers, + $packagers_committers +) { +} diff --git a/modules/buildsystem/manifests/var/iurt.pp b/modules/buildsystem/manifests/var/iurt.pp new file mode 100644 index 00000000..fb65a160 --- /dev/null +++ b/modules/buildsystem/manifests/var/iurt.pp @@ -0,0 +1,5 @@ +class buildsystem::var::iurt( + $login = 'iurt', + $homedir = '/home/iurt', + $timeout_multiplier = 1, +) { } diff --git a/modules/buildsystem/manifests/var/maintdb.pp b/modules/buildsystem/manifests/var/maintdb.pp new file mode 100644 index 00000000..e0079e40 --- /dev/null +++ b/modules/buildsystem/manifests/var/maintdb.pp @@ -0,0 +1,11 @@ +class buildsystem::var::maintdb( + $hostname = "maintdb.${::domain}", + $login = 'maintdb', + $homedir = '/var/lib/maintdb' +) { + include buildsystem::var::webstatus + $dbdir = "${homedir}/db" + $binpath = '/usr/local/sbin/maintdb' + $dump = "${buildsystem::var::webstatus::location}/data/maintdb.txt" + $unmaintained = "${buildsystem::var::webstatus::location}/data/unmaintained.txt" +} diff --git a/modules/buildsystem/manifests/var/mgarepo.pp b/modules/buildsystem/manifests/var/mgarepo.pp new file mode 100644 index 00000000..9099c7ee --- /dev/null +++ b/modules/buildsystem/manifests/var/mgarepo.pp @@ -0,0 +1,22 @@ +# $submit_host: +# hostname used to submit packages +# $svn_hostname: +# hostname of the svn server used for packages +# $svn_root_packages: +# svn root url of the svn repository for packages +# $svn_root_packages_ssh: +# svn+ssh root url of the svn repository for packages +# $oldurl: +# svn url where the import logs of the rpm are stored +# $conf: +# $conf{'global'} is a has table of values used in mgarepo.conf in +# the [global] section +class buildsystem::var::mgarepo( + $submit_host, + $svn_hostname, + $svn_root_packages, + $svn_root_packages_ssh, + $oldurl, + $conf +) { +} diff --git a/modules/buildsystem/manifests/var/repository.pp b/modules/buildsystem/manifests/var/repository.pp new file mode 100644 index 00000000..0ea1058c --- /dev/null +++ b/modules/buildsystem/manifests/var/repository.pp @@ -0,0 +1,9 @@ +class buildsystem::var::repository( + $hostname = "repository.${::domain}", + $bootstrap_root = '/distrib/bootstrap', + $mirror_root = '/distrib/mirror', + $distribdir = 'distrib' +) { + $bootstrap_reporoot = "${bootstrap_root}/${distribdir}" + $mirror_reporoot = "${mirror_root}/${distribdir}" +} diff --git a/modules/buildsystem/manifests/var/scheduler.pp b/modules/buildsystem/manifests/var/scheduler.pp new file mode 100644 index 00000000..b431594c --- /dev/null +++ b/modules/buildsystem/manifests/var/scheduler.pp @@ -0,0 +1,31 @@ +# $admin_mail: +# the email address from which the build failure notifications +# will be sent +# $pkg_uphost: +# hostname of the server where submitted packages are uploaded +# $build_nodes: +# a hash containing available build nodes indexed by architecture +# $build_nodes_aliases: +# a hash containing build nodes indexed by their alias +# $build_src_node: +# hostname of the server building the initial src.rpm +# $clean_uploads_logs_age: +# old logs are cleaned when they are older than some amount of days. +# You can define this amount of time using this variable. Set it to +# 14 for two weeks, 2 for two days, or 0 if you don't want to +# clean old logs at all +# $clean_uploads_packages_age: +# same as $clean_uploads_logs_age but for old RPMs +class buildsystem::var::scheduler( + $admin_mail = "root@${::domain}", + $pkg_uphost = "pkgsubmit.${::domain}", + $build_nodes, + $build_nodes_aliases = {}, + $build_src_node, + $clean_uploads_logs_age = 14, + $clean_uploads_packages_age = 7 +){ + $login = 'schedbot' + $homedir = "/var/lib/${login}" + $logdir = "/var/log/${login}" +} diff --git a/modules/buildsystem/manifests/var/signbot.pp b/modules/buildsystem/manifests/var/signbot.pp new file mode 100644 index 00000000..7d92a324 --- /dev/null +++ b/modules/buildsystem/manifests/var/signbot.pp @@ -0,0 +1,15 @@ +# $keyid: +# the key id of the gnupg key used to sign packages +# $keyemail: +# email address of the key used to sign packages +# $keyname: +# name of the key used to sign packages +class buildsystem::var::signbot( + $keyid, + $keyemail, + $keyname +) { + $login = 'signbot' + $home_dir = "/var/lib/${login}" + $sign_keydir = "${home_dir}/keys" +} diff --git a/modules/buildsystem/manifests/var/webstatus.pp b/modules/buildsystem/manifests/var/webstatus.pp new file mode 100644 index 00000000..21f8d59f --- /dev/null +++ b/modules/buildsystem/manifests/var/webstatus.pp @@ -0,0 +1,25 @@ +# $git_url: +# git url where the sources of webstatus are located +# $hostname: +# vhost name of the webstatus page +# $location: +# path of the directory where the webstatus files are located +# $package_commit_url: +# url to view a commit on a package. %d is replaced by the commit id. +# $max_modified: +# how much history should we display, in days +# $theme_name: +# name of the webstatus theme +# $themes_dir: +# path of the directory where the themes are located. If you want +# to use a theme not included in webstatus, you need to change this. +class buildsystem::var::webstatus( + $git_url = "git://git.${::domain}/web/pkgsubmit", + $hostname = "pkgsubmit.${::domain}", + $location = '/var/www/bs', + $package_commit_url, + $max_modified = '2', + $theme_name = 'mageia', + $themes_dir = '/var/www/bs/themes/' +) { +} diff --git a/modules/buildsystem/manifests/var/youri.pp b/modules/buildsystem/manifests/var/youri.pp new file mode 100644 index 00000000..f20b6c7b --- /dev/null +++ b/modules/buildsystem/manifests/var/youri.pp @@ -0,0 +1,401 @@ +# The youri configuration files are created using information from 3 +# different hash variables : +# - the $youri_conf_default variable defined in this class, containing +# the default configuration for youri. It contains the repository +# configuration, and the definitions of the checks, actions and posts. +# - the $youri_conf parameter passed to this class. The values defined +# in this hash override the values defined in the default configuration. +# - for each distribution defined in the hash variable $distros from +# var::buildsystem::distros the hash defined in index 'youri' contains +# some distro specific options for youri checks, actions or posts. It +# also contains for each distribution the list of active checks, +# actions and posts. +# +# Each of those variables contain the configuration for youri submit-todo +# (in index 'todo') and youri submit-upload (in index 'upload') +# +# +# Parameters : +# $tmpl_youri_upload_conf: +# template file for youri submit-upload.conf +# $tmpl_youri_todo_conf: +# template file for youri submit-todo.conf +# $packages_archivedir: +# the directory where youri will archive old packages when they are +# replaced by a new version +# $youri_conf: +# a hash containing the youri configuration +class buildsystem::var::youri( + $tmpl_youri_upload_conf = 'buildsystem/youri/submit.conf', + $tmpl_youri_todo_conf = 'buildsystem/youri/submit.conf', + $packages_archivedir, + $youri_conf = {} +) { + include buildsystem::var::repository + include buildsystem::var::mgarepo + include buildsystem::var::distros + include buildsystem::var::signbot + include buildsystem::var::scheduler + + $check_tag = { 'class' => 'Youri::Submit::Check::Tag', } + $check_recency = { 'class' => 'Youri::Submit::Check::Recency', } + $check_queue_recency = { 'class' => 'Youri::Submit::Check::Queue_recency', } + $check_host = { + 'class' => 'Youri::Submit::Check::Host', + 'options' => { + 'host_file' => '/etc/youri/host.conf', + }, + } + $check_rpmlint = { 'class' => 'Youri::Submit::Check::Rpmlint', } + $check_acl = { + 'class' => 'Youri::Submit::Check::ACL', + 'options' => { + 'acl_file' => '/etc/youri/acl.conf', + }, + } + $check_source = { 'class' => 'Youri::Submit::Check::Source', } + $check_version = { + 'class' => 'Youri::Submit::Check::Version', + 'options' => {}, + } + + $youri_conf_default = { + 'upload' => { + 'repository' => { + 'class' => 'Youri::Repository::Mageia', + 'options' => { + 'install_root' => $buildsystem::var::repository::bootstrap_reporoot, + 'upload_root' => '$home/uploads/', + 'archive_root' => $packages_archivedir, + 'upload_state' => 'queue', + 'queue' => 'queue', + 'noarch' => 'x86_64', + 'svn' => "${buildsystem::var::mgarepo::svn_root_packages_ssh}/${buildsystem::var::distros::default_distro}", + }, + }, + 'checks' => { + 'tag' => $check_tag, + 'recency' => $check_recency, + 'queue_recency' => $check_queue_recency, + 'host' => $check_host, + 'section' => { + 'class' => 'Youri::Submit::Check::Section', + }, + 'rpmlint' => $check_rpmlint, + 'svn' => { + 'class' => 'Youri::Submit::Check::SVN', + }, + 'acl' => $check_acl, + 'history' => { + 'class' => 'Youri::Submit::Check::History', + }, + 'source' => $check_source, + 'precedence' => { + 'class' => 'Youri::Submit::Check::Precedence', + 'options' => { + 'target' => $buildsystem::var::distros::default_distro, + }, + }, + 'version' => $check_version, + }, + 'actions' => { + 'install' => { + 'class' => 'Youri::Submit::Action::Install', + }, + 'markrelease' => { + 'class' => 'Youri::Submit::Action::Markrelease', + }, + 'link' => { + 'class' => 'Youri::Submit::Action::Link', + }, + 'archive' => { + 'class' => 'Youri::Submit::Action::Archive', + }, + 'clean' => { + 'class' => 'Youri::Submit::Action::Clean', + }, + 'sign' => { + 'class' => 'Youri::Submit::Action::Sign', + 'options' => { + 'signuser' => $buildsystem::var::signbot::login, + 'path' => $buildsystem::var::signbot::sign_keydir, + 'name' => $buildsystem::var::signbot::keyid, + 'signscript' => '/usr/local/bin/sign-check-package', + }, + }, + 'unpack_gfxboot_theme' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'mageia-gfxboot-theme', + 'source_subdir' => '/usr/share/gfxboot/themes/Mageia/install/', + 'dest_directory' => 'isolinux', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_meta_task' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'meta-task', + 'source_subdir' => '/usr/share/meta-task', + 'dest_directory' => 'media/media_info', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_installer_images' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'drakx-installer-images', + 'source_subdir' => '/usr/lib*/drakx-installer-images', + 'dest_directory' => '.', + 'preclean_directory' => 'install/images/alternatives', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_installer_images_nonfree' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'drakx-installer-images-nonfree', + 'source_subdir' => '/usr/lib*/drakx-installer-images', + 'dest_directory' => '.', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_installer_stage2' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'drakx-installer-stage2', + 'source_subdir' => '/usr/lib*/drakx-installer-stage2', + 'dest_directory' => '.', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_installer_advertising' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'drakx-installer-advertising', + 'source_subdir' => '/usr/share/drakx-installer-advertising', + 'dest_directory' => '.', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_installer_rescue' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'drakx-installer-rescue', + 'source_subdir' => '/usr/lib*/drakx-installer-rescue', + 'dest_directory' => 'install/stage2', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_release_notes' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'mageia-release-common', + 'source_subdir' => '/usr/share/doc/mageia-release-common', + 'grep_files' => 'release-notes.*', + 'dest_directory' => '.', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_syslinux' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'syslinux', + 'source_subdir' => '/usr/lib/syslinux/', + 'grep_files' => '\\(hdt\\|ifcpu\\|ldlinux\\|libcom32\\|libgpl\\|libmenu\\|libutil\\).c32', + 'dest_directory' => 'isolinux', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'unpack_pci_usb_ids' => { + 'class' => 'Youri::Submit::Action::Unpack', + 'options' => { + 'name' => 'ldetect-lst', + 'source_subdir' => '/usr/share/', + 'grep_files' => '\\(pci\\|usb\\).ids', + 'dest_directory' => 'isolinux', + 'unpack_inside_distribution_root' => '1', + }, + }, + 'mail' => { + 'class' => 'Youri::Submit::Action::Mail', + 'options' => { + 'mta' => '/usr/sbin/sendmail', + }, + }, + 'maintdb' => { + 'class' => 'Youri::Submit::Action::UpdateMaintDb', + }, + 'rebuild' => { + 'class' => 'Youri::Submit::Action::RebuildPackage', + 'options' => { + 'rules' => { + 'drakx-installer-binaries' => ['drakx-installer-images'], + 'drakx-kbd-mouse-x11' => ['drakx-installer-stage2'], + 'drakx-net' => ['drakx-installer-stage2'], + 'kernel-desktop-latest' => ['drakx-installer-images', 'kmod-virtualbox', 'kmod-xtables-addons'], + 'kernel-desktop586-latest' => ['drakx-installer-images', 'kmod-virtualbox', 'kmod-xtables-addons'], + 'kernel-server-latest' => ['kmod-virtualbox', 'kmod-xtables-addons'], + 'ldetect-lst' => ['drakx-installer-stage2'], + 'meta-task' => ['drakx-installer-stage2'], + 'perl' => ['drakx-installer-stage2'], + 'perl-URPM' => ['drakx-installer-stage2'], + 'rpm' => ['drakx-installer-stage2'], + 'rpm-mageia-setup' => ['drakx-installer-stage2'], + 'urpmi' => ['drakx-installer-stage2'], + }, + }, + }, + }, + 'posts' => { + 'genhdlist2' => { + 'class' => 'Youri::Submit::Post::Genhdlist2', + 'options' => { + 'command' => '/usr/bin/genhdlist2 --xml-info-filter ".lzma:xz -T4" --synthesis-filter ".cz:xz -7 -T8"', + }, + }, + 'genhdlist2_zstd' => { + 'class' => 'Youri::Submit::Post::Genhdlist2', + 'options' => { + 'command' => '/usr/bin/genhdlist2 --xml-info-filter ".lzma:xz -T4" --synthesis-filter ".cz:zstd -19 -T8"', + }, + }, + 'createrepo_mga6' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => 'createrepo_c --no-database --update --workers=10', + }, + }, + 'createrepo_mga7' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => 'createrepo_c --no-database --update --workers=10 --zck --zck-dict-dir /usr/share/mageia-repo-zdicts/mga7/', + }, + }, + 'createrepo_mga8' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => 'createrepo_c --no-database --update --workers=10 --zck --zck-dict-dir /usr/share/mageia-repo-zdicts/mga7/', + }, + }, + 'createrepo_mga9' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => 'createrepo_c --no-database --update --workers=10 --zck --zck-dict-dir /usr/share/mageia-repo-zdicts/mga7/', + }, + }, + 'createrepo_cauldron' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => 'createrepo_c --no-database --update --workers=10', + }, + }, + 'appstream_mga6' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => '/distrib/appstream/appstream-6-modifyrepo.sh', + }, + }, + 'appstream_mga7' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => '/distrib/appstream/appstream-7-modifyrepo.sh', + }, + }, + 'appstream_mga8' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => '/distrib/appstream/appstream-8-modifyrepo.sh', + }, + }, + 'appstream_mga9' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => '/distrib/appstream/appstream-9-modifyrepo.sh', + }, + }, + 'appstream_cauldron' => { + 'class' => 'Youri::Submit::Post::RunOnModifiedMedia', + 'options' => { + 'command' => '/distrib/appstream/appstream-cauldron-modifyrepo.sh', + }, + }, + 'clean_rpmsrate' => { + 'class' => 'Youri::Submit::Post::CleanRpmsrate', + }, + 'mirror' => { + 'class' => 'Youri::Submit::Post::Mirror', + 'options' => { + 'destination' => $buildsystem::var::repository::mirror_reporoot, + }, + }, + }, + }, + 'todo' => { + 'repository' => { + 'class' => 'Youri::Repository::Mageia', + 'options' => { + 'install_root' => $buildsystem::var::repository::bootstrap_reporoot, + 'upload_root' => '$home/uploads/', + 'upload_state' => 'todo done queue', + 'queue' => 'todo', + 'noarch' => 'x86_64', + 'svn' => "${buildsystem::var::mgarepo::svn_root_packages_ssh}/${buildsystem::var::distros::default_distro}", + }, + }, + 'checks' => { + 'tag' => $check_tag, + 'recency' => $check_recency, + 'queue_recency' => $check_queue_recency, + 'host' => $check_host, + 'rpmlint' => $check_rpmlint, + 'acl' => $check_acl, + 'source' => $check_source, + 'version' => $check_version, + 'deps' => { + 'class' => 'Youri::Submit::Check::Deps', + }, + }, + 'actions' => { + 'send' => { + 'class' => 'Youri::Submit::Action::Send', + 'options' => { + 'user' => $buildsystem::var::scheduler::login, + 'keep_svn_release' => 'yes', + 'uphost' => $buildsystem::var::scheduler::pkg_uphost, + 'root' => '$home/uploads', + 'ssh_key' => '$home/.ssh/id_rsa', + }, + }, + 'dependencies' => { + 'class' => 'Youri::Submit::Action::Dependencies', + 'options' => { + 'user' => $buildsystem::var::scheduler::login, + 'uphost' => $buildsystem::var::scheduler::pkg_uphost, + 'root' => '$home/uploads', + 'ssh_key' => '$home/.ssh/id_rsa', + }, + }, + 'rpminfo' => { + 'class' => 'Youri::Submit::Action::Rpminfo', + 'options' => { + 'user' => $buildsystem::var::scheduler::login, + 'uphost' => $buildsystem::var::scheduler::pkg_uphost, + 'root' => '$home/uploads', + 'ssh_key' => '$home/.ssh/id_rsa', + }, + }, + 'ulri' => { + 'class' => 'Youri::Submit::Action::Ulri', + 'options' => { + 'user' => $buildsystem::var::scheduler::login, + 'uphost' => $buildsystem::var::scheduler::pkg_uphost, + 'ssh_key' => '$home/.ssh/id_rsa', + }, + }, + }, + 'posts' => { + }, + }, + } +} diff --git a/modules/buildsystem/manifests/webstatus.pp b/modules/buildsystem/manifests/webstatus.pp new file mode 100644 index 00000000..49346dbc --- /dev/null +++ b/modules/buildsystem/manifests/webstatus.pp @@ -0,0 +1,44 @@ +class buildsystem::webstatus { + include buildsystem::var::webstatus + include buildsystem::var::scheduler + include apache::mod::php + + file { [ $buildsystem::var::webstatus::location, "${buildsystem::var::webstatus::location}/data" ]: + ensure => directory, + } + + $vhost = $buildsystem::var::webstatus::hostname + apache::vhost::base { $vhost: + aliases => { + '/uploads' => "${buildsystem::var::scheduler::homedir}/uploads", + '/autobuild/cauldron/x86_64/core/log/status.core.log' => "${buildsystem::var::webstatus::location}/autobuild/broken.php", + '/themes' => $buildsystem::var::webstatus::themes_dir, + }, + location => $buildsystem::var::webstatus::location, + content => template('buildsystem/vhost_webstatus.conf'), + } + + apache::vhost::base { "ssl_${vhost}": + vhost => $vhost, + use_ssl => true, + aliases => { + '/uploads' => "${buildsystem::var::scheduler::homedir}/uploads", + '/autobuild/cauldron/x86_64/core/log/status.core.log' => "${buildsystem::var::webstatus::location}/autobuild/broken.php", + '/themes' => $buildsystem::var::webstatus::themes_dir, + }, + location => $buildsystem::var::webstatus::location, + content => template('buildsystem/vhost_webstatus.conf'), + } + + git::snapshot { $buildsystem::var::webstatus::location: + source => $buildsystem::var::webstatus::git_url, + } + + file { '/etc/bs-webstatus.conf': + ensure => present, + content => template('buildsystem/bs-webstatus.conf'), + mode => '0644', + owner => root, + group => root, + } +} diff --git a/modules/buildsystem/manifests/youri_submit.pp b/modules/buildsystem/manifests/youri_submit.pp index e5e38fb8..6b4d7dc2 100644 --- a/modules/buildsystem/manifests/youri_submit.pp +++ b/modules/buildsystem/manifests/youri_submit.pp @@ -2,14 +2,10 @@ class buildsystem::youri_submit { include sudo include buildsystem::rpmlint include buildsystem::repository - include buildsystem::scheduler::var + include buildsystem::var::scheduler + include buildsystem::var::youri - $repository_root = $buildsystem::repository::dir - $sched_home_dir = $buildsystem::scheduler::var::homedir - $sched_login = $buildsystem::scheduler::var::login - $packages_archivedir = "$sched_home_dir/old" - - mga-common::local_script { + mga_common::local_script { 'mga-youri-submit': content => template('buildsystem/mga-youri-submit'); 'mga-youri-submit.wrapper': @@ -23,34 +19,54 @@ class buildsystem::youri_submit { sudo::sudoers_config { 'mga-youri-submit': content => template('buildsystem/sudoers.youri') } + $release_managers = group_members('mga-release_managers') # ordering is automatic : - # http://docs.puppetlabs.com/learning/ordering.html#autorequire + # https://docs.puppetlabs.com/learning/ordering.html#autorequire file { '/etc/youri/': ensure => 'directory'; - '/etc/youri/submit-todo.conf': - content => template('buildsystem/youri/submit-todo.conf'); - '/etc/youri/submit-upload.conf': - content => template('buildsystem/youri/submit-upload.conf'); '/etc/youri/acl.conf': content => template('buildsystem/youri/acl.conf'); + '/etc/youri/host.conf': + content => template('buildsystem/youri/host.conf'); + } + + buildsystem::youri_submit_conf{ 'upload': + tmpl_file => $buildsystem::var::youri::tmpl_youri_upload_conf, + } + buildsystem::youri_submit_conf{ 'todo': + tmpl_file => $buildsystem::var::youri::tmpl_youri_todo_conf, } - file { $packages_archivedir: + cron { 'Archive orphan packages from cauldron': + command => "/usr/local/bin/mga-clean-distrib --auto -v cauldron -d ${buildsystem::var::youri::packages_archivedir} -l ${buildsystem::var::scheduler::homedir}/tmp/upload", + hour => 5, + minute => 30, + user => $buildsystem::var::scheduler::login, + } + + file { $buildsystem::var::youri::packages_archivedir: ensure => 'directory', - owner => $sched_login, - require => File[$sched_home_dir], + owner => $buildsystem::var::scheduler::login, + require => File[$buildsystem::var::scheduler::homedir], } - tidy { $packages_archivedir: + tidy { $buildsystem::var::youri::packages_archivedir: type => 'ctime', recurse => true, age => '1w', matches => '*.rpm', } - # FIXME use /usr/local/ once it will be in @INC - file { '/usr/lib/perl5/vendor_perl/5.12.3/Youri/Repository/Mageia.pm': + include mga_common::var::perl + file { [ "${mga_common::var::perl::site_perl_dir}/Youri", + "${mga_common::var::perl::site_perl_dir}/Youri/Repository"]: + ensure => directory, + mode => '0755', + owner => root, + group => root, + } + file { "${mga_common::var::perl::site_perl_dir}/Youri/Repository/Mageia.pm": source => 'puppet:///modules/buildsystem/Mageia.pm', } diff --git a/modules/buildsystem/manifests/youri_submit_conf.pp b/modules/buildsystem/manifests/youri_submit_conf.pp new file mode 100644 index 00000000..28b911d9 --- /dev/null +++ b/modules/buildsystem/manifests/youri_submit_conf.pp @@ -0,0 +1,6 @@ +define buildsystem::youri_submit_conf($tmpl_file) { + $conf_name = $name + file { "/etc/youri/submit-${conf_name}.conf": + content => template($tmpl_file), + } +} diff --git a/modules/buildsystem/templates/binrepo/sudoers.binrepo b/modules/buildsystem/templates/binrepo/sudoers.binrepo index 405f43a3..c20810cf 100644 --- a/modules/buildsystem/templates/binrepo/sudoers.binrepo +++ b/modules/buildsystem/templates/binrepo/sudoers.binrepo @@ -1 +1 @@ -%<%= packagers_committers_group %> ALL =(<%= login %>) NOPASSWD: <%= uploadbinpath %> +%<%= scope.lookupvar('buildsystem::var::groups::packagers_committers') %> ALL =(<%= scope.lookupvar('buildsystem::var::binrepo::login') %>) NOPASSWD: <%= scope.lookupvar('buildsystem::var::binrepo::uploadbinpath') %> diff --git a/modules/buildsystem/templates/binrepo/upload-bin b/modules/buildsystem/templates/binrepo/upload-bin index f90130f3..7cad5838 100755 --- a/modules/buildsystem/templates/binrepo/upload-bin +++ b/modules/buildsystem/templates/binrepo/upload-bin @@ -1,11 +1,11 @@ #!/bin/sh set -e -binrepodir=<%= repodir %> -uploadinfosdir=<%= uploadinfosdir %> +binrepodir=<%= scope.lookupvar('buildsystem::var::binrepo::repodir') %> +uploadinfosdir=<%= scope.lookupvar('buildsystem::var::binrepo::uploadinfosdir') %> tmpfile=$(mktemp) -mail_from="<%= uploadmail_from %>" -mail_dest="<%= uploadmail_to %>" +mail_from="<%= scope.lookupvar('buildsystem::var::binrepo::uploadmail_from') %>" +mail_dest="<%= scope.lookupvar('buildsystem::var::binrepo::uploadmail_to') %>" test $# = 2 || exit 3 username="$1" diff --git a/modules/buildsystem/templates/binrepo/vhost_binrepo.conf b/modules/buildsystem/templates/binrepo/vhost_binrepo.conf index ce29accf..f411c07a 100644 --- a/modules/buildsystem/templates/binrepo/vhost_binrepo.conf +++ b/modules/buildsystem/templates/binrepo/vhost_binrepo.conf @@ -1,3 +1,3 @@ -<Directory <%= repodir %>> +<Directory <%= scope.lookupvar('buildsystem::var::binrepo::repodir') %>> Options None </Directory> diff --git a/modules/buildsystem/templates/binrepo/wrapper.upload-bin b/modules/buildsystem/templates/binrepo/wrapper.upload-bin index 48385a47..3def84a0 100644 --- a/modules/buildsystem/templates/binrepo/wrapper.upload-bin +++ b/modules/buildsystem/templates/binrepo/wrapper.upload-bin @@ -1,8 +1,8 @@ #!/bin/sh -binrepouser="<%= login %>" -uploadbinpath="<%= uploadbinpath %>" -packagerscommittersgroup="<%= packagers_committers_group %>" +binrepouser="<%= scope.lookupvar('buildsystem::var::binrepo::login') %>" +uploadbinpath="<%= scope.lookupvar('buildsystem::var::binrepo::uploadbinpath') %>" +packagerscommittersgroup="<%= scope.lookupvar('buildsystem::var::groups::packagers_committers') %>" function isingroup() { diff --git a/modules/buildsystem/templates/bs-webstatus.conf b/modules/buildsystem/templates/bs-webstatus.conf new file mode 100644 index 00000000..9f37a990 --- /dev/null +++ b/modules/buildsystem/templates/bs-webstatus.conf @@ -0,0 +1,32 @@ +<?php + +/** Where is the current app located. */ +$g_webapp_dir = '<%= scope.lookupvar('buildsystem::var::webstatus::location') %>'; + +/** Full system path where packages are uploaded. */ +$upload_dir = '<%= scope.lookupvar('buildsystem::var::scheduler::homedir') %>/uploads'; + +/** How long a history should we keep, in days. */ +$max_modified = <%= scope.lookupvar('buildsystem::var::webstatus::max_modified') %>; + +/** How many nodes are available. */ +$g_nodes_count = 2; + +/** html > body > h1 title */ +$title = 'Build system status'; + +/** Should crawlers index this page or not? meta[robots] tag.*/ +$robots = 'index,nofollow,nosnippet,noarchive'; + +/** */ +$g_root_url = 'https://<%= scope.lookupvar('buildsystem::var::webstatus::hostname') %>/'; + +/** URL to view a package svn revision. %d is replaced by the revision */ +$package_commit_url = '<%= scope.lookupvar('buildsystem::var::webstatus::package_commit_url') %>'; + +/** name of the theme */ +$theme_name = '<%= scope.lookupvar('buildsystem::var::webstatus::theme_name') %>'; + +/** themes directory */ +$themes_dir = '<%= scope.lookupvar('buildsystem::var::webstatus::themes_dir') %>'; + diff --git a/modules/buildsystem/templates/cleaner.rb b/modules/buildsystem/templates/cleaner.rb index 338d66ba..fa0d08ca 100755 --- a/modules/buildsystem/templates/cleaner.rb +++ b/modules/buildsystem/templates/cleaner.rb @@ -1,114 +1,235 @@ #!/usr/bin/ruby def usage - puts "Usage: #{$0} [options]" - puts "Moves obsolete packages" - puts - puts "-h, --help show help" - puts "-m, --media <path> path to the binary media" - puts "-s, --src <path> path to the associated src media" - puts "-d, --destination <path> path to the old packages storage" + puts "Usage: #{$0} [options]" + puts "Moves obsolete packages" + puts + puts "-h, --help show this help" + puts "-a, --archs <arch1>,<arch2>,... list of architectures to clean" + puts "-a, --auto do not ask confirmation" + puts "-p, --base <path> base path to the repository" + puts "-m, --media <media1>,<media2>,... list of media to clean (default: core/release,tainted/release,nonfree/release)" + puts "-d, --destination <path> path to the old packages storage" + puts "-v, --version <version> version to clean (default: cauldron)" end require 'fileutils' require 'getoptlong' require 'readline' -opts = GetoptLong.new( - [ '--help', '-h', GetoptLong::NO_ARGUMENT ], - [ '--archs', '-a', GetoptLong::REQUIRED_ARGUMENT ], - [ '--base', '-p', GetoptLong::REQUIRED_ARGUMENT ], - [ '--media', '-m', GetoptLong::REQUIRED_ARGUMENT ], - [ '--bmedia', '-b', GetoptLong::REQUIRED_ARGUMENT ], - [ '--smedia', '-s', GetoptLong::REQUIRED_ARGUMENT ], - [ '--destination', '-d', GetoptLong::REQUIRED_ARGUMENT ], - [ '--version', '-v', GetoptLong::REQUIRED_ARGUMENT ] -) - -base_path = "<%= repository_root %>/distrib" -archs = [ "i586", "x86_64" ] -media = "core/release" -old_path = "<%= packages_archivedir %>" -version = "cauldron" - -opts.each do |opt, arg| - case opt - when '--help' - usage - exit 0 - when '--bmedia' - bin_path = arg.split(",") - when '--smedia' - src_path = arg - when '--destination' - old_path = arg - when '--media' - media = arg - when '--archs' - archs = arg.split(",") - when '--base' - base_path = arg - when '--version' - version = arg - end -end +def process + opts = GetoptLong.new( + [ '--help', '-h', GetoptLong::NO_ARGUMENT ], + [ '--archs', '-a', GetoptLong::REQUIRED_ARGUMENT ], + [ '--auto', '-A', GetoptLong::NO_ARGUMENT ], + [ '--base', '-p', GetoptLong::REQUIRED_ARGUMENT ], + [ '--media', '-m', GetoptLong::REQUIRED_ARGUMENT ], + [ '--destination', '-d', GetoptLong::REQUIRED_ARGUMENT ], + [ '--version', '-v', GetoptLong::REQUIRED_ARGUMENT ], + [ '--lockfile', '-l', GetoptLong::REQUIRED_ARGUMENT ], + ) + + base_path = "<%= scope.lookupvar('buildsystem::var::repository::bootstrap_root') %>/distrib" + archs = [ "x86_64", "i686", "aarch64", "armv7hl" ] + medias = ["core/release", "tainted/release", "nonfree/release"] + old_path = "<%= scope.lookupvar('buildsystem::var::youri::packages_archivedir') %>" + version = "cauldron" + auto = false + lockfile = nil + + opts.each do |opt, arg| + case opt + when '--help' + usage + exit 0 + when '--destination' + old_path = arg + when '--media' + medias = arg.split(",") + when '--archs' + archs = arg.split(",") + when '--auto' + auto = true + when '--base' + base_path = arg + when '--version' + version = arg + when '--lockfile' + lockfile = arg + end + end + + take_upload_lock(lockfile) if lockfile -bin_path ||= archs.map{|arch| "#{base_path}/#{version}/#{arch}/media/#{media}" } -src_path ||= "#{base_path}/#{version}/SRPMS/#{media}" -debug_path = bin_path.map{|path| path.sub("/media/", "/media/debug/")} + medias.each{|media| + src_path = "#{base_path}/#{version}/SRPMS/#{media}" -$used_srcs = {} -$srcs = {} + $used_srcs = {} + $old_srcs = {} + $srcs = {} + $srcages = {} + $noarch = {} -# Get a list of all src.rpm + # Get a list of all src.rpm and their build time + `urpmf --synthesis "#{src_path}/media_info/synthesis.hdlist.cz" --qf '%filename:%buildtime:%buildarchs' "."`.each_line{|l| + l2 = l.split(':') + filename = l2[0] + buildtime = l2[1].to_i + buildarch = l2[2].rstrip + name = name_from_filename(filename) + if $srcages[name] then + if buildtime < $srcages[name][1] then + # This src.rpm is older, ignore it and store it in the list to be deleted + $old_srcs[filename] = true + next + else + # This src.rpm has an older version, ignore that version and store it in the list to be deleted + old_filename = $srcages[name][0] + $old_srcs[old_filename] = true + $srcs.delete(old_filename) + end + end + $srcages[name] = [ filename, buildtime ] + $srcs[filename] = true + $noarch[name] = true if buildarch == 'noarch' + } + archs.each{|arch| + bin_path = "#{base_path}/#{version}/#{arch}/media/#{media}" + debug_path = bin_path.sub("/media/", "/media/debug/") + old_packages = check_binaries(arch, $srcs, $srcages, src_path, bin_path, $used_srcs) + old_debug_packages = check_binaries(arch, $srcs, {}, src_path, debug_path, nil) + move_packages(bin_path, old_path, old_packages, auto) + move_packages(debug_path, old_path, old_debug_packages, auto) + } + $used_srcs.keys.each{|s| $srcs.delete(s)} -`urpmf --synthesis "#{src_path}/media_info/synthesis.hdlist.cz" --qf '%filename' "."`.each_line{|l| - $srcs[l.rstrip] = true -} + move_packages(src_path, old_path, $srcs.keys + $old_srcs.keys, auto) + } +end + +def take_upload_lock(path) + start_time = Time.new + has_lock = false + at_exit { + if File.exists?(path) + if File.readlines(path)[0].to_i == Process.pid + File.delete(path) + end + end + } + until has_lock + while File.exists?(path) + if Time.new - start_time > 2*3600.0 + puts "Could not acquire upload lock for more than 2h, giving up" + end + sleep(5) + end + File.write(path, Process.pid) + if File.readlines(path)[0].to_i == Process.pid + has_lock = true + end + end +end + +def move_packages(src, dst, list, auto) + list.reject!{|f| !File.exist?(src + "/" + f)} + return if list.empty? + list.each{|b| + puts b + } + puts "The #{list.length} listed packages will be moved from #{src} to #{dst}." + line = Readline::readline('Are you sure [Yn]? ') unless auto + if auto || line =~ /^y?$/i + list.each{|s| + oldfile = src + "/" + s + newfile = dst + "/" + s + next unless File.exist?(oldfile) + if (File.exist?(newfile)) + File.unlink(oldfile) + else + FileUtils.mv(oldfile, newfile) + end + } + end +end # For each binary media: # - Check if we have the src.rpm (else the binary package is obsolete) +# * If we don't have the src.rpm, check if we have a newer version +# - If there is a new version: +# * check if this architecture has packages from it to avoid deleting armv7hl packages before the new one get rebuilt +# * check if the new version is old enough to allow rebuilding everything (7d?) # - Mark used src.rpm (if one is never marked, the src.rpm is obsolete) -def move_packages(src, dst, list) - list.reject!{|f| !File.exist?(src + "/" + f)} - return if list.empty? - list.each{|b| - puts b - } - puts "The #{list.length} listed packages will be moved from #{src} to #{dst}." - line = Readline::readline('Are you sure [Yn]? ') - if (line =~ /^y?$/i) - list.each{|s| - oldfile = src + "/" + s - newfile = dst + "/" + s - next unless File.exist?(oldfile) - if (File.exist?(newfile)) - File.unlink(oldfile) - else - FileUtils.mv(oldfile, newfile) - end - } - end +def packages(path) + `urpmf --synthesis "#{path}/media_info/synthesis.hdlist.cz" --qf '%sourcerpm:%filename:%buildtime' ":"`.each_line{|l| + l2 = l.split(':') + sourcerpm = l2[0] + filename = l2[1] + buildtime = l2[2].to_i + yield(sourcerpm, filename, buildtime) + } end -def check_binaries(path_list, old_path, mark_used) - path_list.each{|bm| - old_binaries = [] - `urpmf --synthesis "#{bm}/media_info/synthesis.hdlist.cz" --qf '%sourcerpm:%filename' ":"`.each_line{|l| - l2 = l.split(':') - src = l2[0] - filename = l2[1].rstrip - old_binaries << filename unless $srcs[src] - $used_srcs[src] = true if mark_used - } - move_packages(bm, old_path, old_binaries) - } +def name_from_filename(filename) + filename.sub(/-[^-]*-[^-]*$/, '') end -check_binaries(bin_path, old_path, true) -check_binaries(debug_path, old_path, false) +def arch_wanted(src, arch) + exclusive_arch = `rpmquery -p #{src} --qf '[%{EXCLUSIVEARCH} ]'`.rstrip + if exclusive_arch != "" then + if !exclusive_arch.split(/ /).include?(arch) then + return false + end + end + exclude_arch = `rpmquery -p #{src} --qf '[%{EXCLUDEARCH} ]'`.rstrip + if exclude_arch != "" then + if exclude_arch.split(/ /).include?(arch) then + return false + end + end + + return true +end -$used_srcs.keys.each{|s| $srcs.delete(s)} +def check_binaries(arch, srcs, srcages, src_path, path, used_srcs) + used_here_srcs = {} + all_versions = {} + packages(path) {|src, filename, buildtime| + used_srcs[src] = true if used_srcs != nil + if filename =~ /noarch.rpm$/ then + # We need to mark the src.rpm present on this arch only for full noarch packages + used_here_srcs[src] = true if $noarch[name_from_filename(src)] + else + used_here_srcs[src] = true + end + name = name_from_filename(filename) + if all_versions[name] then + all_versions[name] << src + else + all_versions[name] = [src] + end + } + old_binaries = [] + packages(path) {|src, filename, buildtime| + if ! srcs[src] then + srcname = name_from_filename(src) + if srcages[srcname] then + # The src.rpm is gone but there is a different version of it + latestsrc = srcages[srcname][0] + # Only delete old binaries after 7d or if there is a new version + name = name_from_filename(filename) + next unless (srcages[srcname][1] < Time.now.to_i - 24*60*60*7 || all_versions[name].include?(latestsrc)) + # Do not delete if the new version of the package hasn't been built for this arch yet + # but still delete it if it is no longer expected to be built. + next unless (used_here_srcs[latestsrc] || !arch_wanted("#{src_path}/#{latestsrc}", arch)) + end + old_binaries << filename + end + } + old_binaries +end -move_packages(src_path, old_path, $srcs.keys) +if __FILE__ == $0 then + process +end diff --git a/modules/buildsystem/templates/cleaner_test.rb b/modules/buildsystem/templates/cleaner_test.rb new file mode 100644 index 00000000..804bd1b5 --- /dev/null +++ b/modules/buildsystem/templates/cleaner_test.rb @@ -0,0 +1,83 @@ +require 'cleaner' +require "test/unit" + +class TestCleaner < Test::Unit::TestCase + + @pkgs = [] + + def setpackages(pkgs) + @pkgs = pkgs + end + + def packages(path) + @pkgs.map{|p| + l2 = p.split(':') + sourcerpm = l2[0] + filename = l2[1] + buildtime = l2[2].to_i + yield(sourcerpm, filename, buildtime) + } + end + + def test_old + # Package was built on this arch and src.rpm for new version is 15d old + setpackages(['foo-43-1.src.rpm:libfoo2-43-1.armv7hl.rpm:43', 'foo-42-1.src.rpm:libfoo1-42-1.armv7hl.rpm:42']) + srcages = {} + srcages['foo'] = [ 'foo-43-1.src.rpm', Time.now.to_i - 15*24*3600 ] + srcs = {} + srcs['foo-43-1.src.rpm'] = true + assert_equal(['libfoo1-42-1.armv7hl.rpm'], check_binaries('armv7hl', srcs, srcages, '', '', nil)) + end + + def test_recent + # Package was built on this arch but src.rpm for new version is only 1d old + setpackages(['foo-43-1.src.rpm:foo-43-1.armv7hl.rpm:43', 'foo-42-1.src.rpm:foo-42-1.armv7hl.rpm:42']) + srcages = {} + srcages['foo'] = [ 'foo-43.src.rpm', Time.now.to_i - 24*3600 ] + srcs = {} + srcs['foo-43-1.src.rpm'] = true + assert_equal([], check_binaries('armv7hl', srcs, srcages, '', '', nil)) + end + + def test_arm_late + # Package was not yet built on this arch + setpackages(['foo-42-1.src.rpm:foo-42-1.armv7hl.rpm:42']) + srcages = {} + srcages['foo'] = [ 'foo-43.src.rpm', Time.now.to_i - 24*3600 ] + srcs = {} + srcs['foo-43-1.src.rpm'] = true + assert_equal([], check_binaries('armv7hl', srcs, srcages, '', '', nil)) + end + + def test_multiple_versions + # Old package remains (usually happens to noarch due to youri bug) + $noarch = { 'foo' => true } + setpackages(['foo-42-1.src.rpm:foo-42-1.noarch.rpm:42', 'foo-42-2.src.rpm:foo-42-2.noarch.rpm:43']) + srcages = {} + srcages['foo'] = [ 'foo-42-2.src.rpm', Time.now.to_i - 24*3600 ] + srcs = {} + srcs['foo-42-2.src.rpm'] = true + assert_equal(['foo-42-1.noarch.rpm'], check_binaries('i586', srcs, srcages, '', '', nil)) + end + + def test_icu + $noarch = {} + now = Time.now.to_i + srctime = now - 3600 + oldbintime = now - 10*24*3600 + newbintime = now - 3200 + setpackages([ + "icu-71.1-2.mga9.src.rpm:icu71-data-71.1-2.mga9.noarch.rpm:#{oldbintime}", + "icu-71.1-2.mga9.src.rpm:lib64icu71-71.1-2.mga9.aarch64.rpm:#{oldbintime}", + "icu-72.1-1.mga9.src.rpm:icu72-data-72.1-1.mga9.noarch.rpm:#{newbintime}", + "icu-72.1-1.mga9.src.rpm:lib64icu-devel-72.1-1.mga9.aarch64.rpm:#{newbintime}", + "icu-72.1-1.mga9.src.rpm:lib64icu72-72.1-1.mga9.aarch64.rpm:#{newbintime}" + ]) + srcages = {} + srcages['icu'] = [ 'icu-71.1-2.mga9.src.rpm', srctime ] + srcs = {} + srcs['icu-71.1-2.mga9.src.rpm'] = true + assert_equal([], check_binaries('aarch64', srcs, srcages, '', '', nil)) + end + +end diff --git a/modules/buildsystem/templates/iurt.conf b/modules/buildsystem/templates/iurt.conf new file mode 100644 index 00000000..2dd8bf0e --- /dev/null +++ b/modules/buildsystem/templates/iurt.conf @@ -0,0 +1,37 @@ +<%- distro = scope.lookupvar('buildsystem::var::distros::distros')[@distribution] -%> +{ + supported_arch => [ '<%= distro['arch'].join("', '") %>' ], + all_media =>{ +<%- distro['medias'].keys.sort.each{|media| -%> + '<%= media %>' => [ '<%= + distro['medias'][media]['repos'].keys.sort.join("', '") %>' ], +<%- +} -%> + }, + distribution => '<%= distro['macros']['distribution'] %>', + vendor => '<%= distro['macros']['vendor'] %>', + base_media => [ '<%= distro['base_media'].join("', '") %>' ], + upload => '<%= build_login %>@pkgsubmit:~/uploads/', + upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', + unwanted_packages => '^monotone-', + repository => 'http://<%= scope.lookupvar('buildsystem::var::repository::hostname') %>/<%= scope.lookupvar('buildsystem::var::repository::distribdir') %>/', + log_url => 'https://<%= scope.lookupvar('buildsystem::var::webstatus::hostname') %>/queue/build/', + admin => 'mageia-sysadm@mageia.org', + packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', + sendmail => 0, + log_size_limit => '600M', + build_timeout => { +<%- build_timeout.keys.sort.each{|package| -%> + '<%= package %>' => <%= (build_timeout[package].to_f * scope.lookupvar('buildsystem::var::iurt::timeout_multiplier').to_f).to_i %>, +<%- +} -%> + }, + use_netns => { + 'default' => 1, +<%- allow_network_access.sort.each{|package| -%> + '<%= package %>' => 0, +<%- +} -%> + }, +} + diff --git a/modules/buildsystem/templates/iurt/1.conf b/modules/buildsystem/templates/iurt/1.conf deleted file mode 100644 index a37f336c..00000000 --- a/modules/buildsystem/templates/iurt/1.conf +++ /dev/null @@ -1,23 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'core' => [ 'release' ], 'nonfree' => [ 'release' ], 'tainted' => [ 'release' ] }, - base_media => [ 'core/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - unwanted_packages => '^monotone-', - repository => 'http://repository.<%= domain %>/distrib/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, - build_timeout => { - 'default' => 18000, - 'gcc' => 57600, - 'paraview' => 115200, - 'salome' => 57600, - 'itk' => 115200, - 'wrapitk' => 115200, - 'libreoffice' => 345600 - }, -} - diff --git a/modules/buildsystem/templates/iurt/2.conf b/modules/buildsystem/templates/iurt/2.conf deleted file mode 100644 index a37f336c..00000000 --- a/modules/buildsystem/templates/iurt/2.conf +++ /dev/null @@ -1,23 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'core' => [ 'release' ], 'nonfree' => [ 'release' ], 'tainted' => [ 'release' ] }, - base_media => [ 'core/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - unwanted_packages => '^monotone-', - repository => 'http://repository.<%= domain %>/distrib/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, - build_timeout => { - 'default' => 18000, - 'gcc' => 57600, - 'paraview' => 115200, - 'salome' => 57600, - 'itk' => 115200, - 'wrapitk' => 115200, - 'libreoffice' => 345600 - }, -} - diff --git a/modules/buildsystem/templates/iurt/cauldron.conf b/modules/buildsystem/templates/iurt/cauldron.conf deleted file mode 100644 index a37f336c..00000000 --- a/modules/buildsystem/templates/iurt/cauldron.conf +++ /dev/null @@ -1,23 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'core' => [ 'release' ], 'nonfree' => [ 'release' ], 'tainted' => [ 'release' ] }, - base_media => [ 'core/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - unwanted_packages => '^monotone-', - repository => 'http://repository.<%= domain %>/distrib/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, - build_timeout => { - 'default' => 18000, - 'gcc' => 57600, - 'paraview' => 115200, - 'salome' => 57600, - 'itk' => 115200, - 'wrapitk' => 115200, - 'libreoffice' => 345600 - }, -} - diff --git a/modules/buildsystem/templates/iurt/infra_1.conf b/modules/buildsystem/templates/iurt/infra_1.conf deleted file mode 100644 index 5f41e9f2..00000000 --- a/modules/buildsystem/templates/iurt/infra_1.conf +++ /dev/null @@ -1,13 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'infra' => [ 'release' ] }, - base_media => [ 'base/core/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - repository => 'http://repository.<%= domain %>/distrib/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, -} - diff --git a/modules/buildsystem/templates/iurt/infra_2.conf b/modules/buildsystem/templates/iurt/infra_2.conf deleted file mode 100644 index 5f41e9f2..00000000 --- a/modules/buildsystem/templates/iurt/infra_2.conf +++ /dev/null @@ -1,13 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'infra' => [ 'release' ] }, - base_media => [ 'base/core/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - repository => 'http://repository.<%= domain %>/distrib/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, -} - diff --git a/modules/buildsystem/templates/iurt/mandriva2010.1.conf b/modules/buildsystem/templates/iurt/mandriva2010.1.conf deleted file mode 100644 index 124625f6..00000000 --- a/modules/buildsystem/templates/iurt/mandriva2010.1.conf +++ /dev/null @@ -1,23 +0,0 @@ -{ - supported_arch => [ 'i586', 'x86_64' ], - all_media => { 'main' => [ 'release' ], 'contrib' => [ 'release' ] }, - base_media => [ 'main/release' ], - upload => '<%= build_login %>@pkgsubmit:~/uploads/', - upload_queue => '<%= build_login %>@pkgsubmit:~/uploads/queue/', - unwanted_packages => '^monotone-', - repository => 'http://repository.<%= domain %>/mandriva/', - rsync_to => '<%= build_login %>@pkgsubmit:/mnt/BIG/dis/uploads/build/', - log_url => 'http://pkgsubmit.<%= domain %>/queue/build/', - admin => 'mageia-sysadm@mageia.org', - packager => 'Iurt the rebuild bot <mageia-sysadm@mageia.org>', - sendmail => 0, - build_timeout => { - 'default' => 18000, - 'gcc' => 57600, - 'paraview' => 115200, - 'salome' => 57600, - 'itk' => 115200, - 'wrapitk' => 115200 - }, -} - diff --git a/modules/buildsystem/templates/iurt/sudoers.iurt b/modules/buildsystem/templates/iurt/sudoers.iurt deleted file mode 100644 index 408aa92c..00000000 --- a/modules/buildsystem/templates/iurt/sudoers.iurt +++ /dev/null @@ -1 +0,0 @@ -<%= login %> ALL = NOPASSWD: /usr/sbin/iurt_root_command diff --git a/modules/buildsystem/templates/iurt2010.1 b/modules/buildsystem/templates/iurt2010.1 deleted file mode 100755 index 44633e9b..00000000 --- a/modules/buildsystem/templates/iurt2010.1 +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -if [ `whoami` != <%= build_login %> ] -then - echo 'this script should be run as <%= build_login %>' >&2 - exit 1 -fi -ARCH=$(rpm --eval %_target_cpu) -iurt --chrooted-urpmi -m contrib/release main/release ../../../2010.1-mgaserv/$ARCH -- http://repository.<%= domain %>/mandriva/ -r mandriva2010.1 $ARCH $@ diff --git a/modules/buildsystem/templates/maintdb/maintdb.bin b/modules/buildsystem/templates/maintdb/maintdb.bin index b0cfb1ef..903ee009 100755 --- a/modules/buildsystem/templates/maintdb/maintdb.bin +++ b/modules/buildsystem/templates/maintdb/maintdb.bin @@ -1,30 +1,28 @@ -#!/bin/sh +#!/bin/bash -MAINTDBDIR="<%= dbdir %>" +MAINTDBDIR="<%= scope.lookupvar('buildsystem::var::maintdb::dbdir') %>" function checkname() { if [ -z "$1" ] || - echo "$1" | grep -q '[/*{}%]' || - echo "$1" | fgrep -q '..' + echo "$1" | grep -q '[/*{}%]' || + echo "$1" | fgrep -q '..' then - echo "Error: invalid package name." >&2 - exit 1 + echo "Error: invalid package name." >&2 + exit 1 fi } function maintnew() { - if [ a"$user" != "aroot" ] - then - echo "Error: new is only allowed to root." >&2 - exit 1 + if [ "$user" != "root" ]; then + echo "Error: new is only allowed to root." >&2 + exit 1 fi checkname "$1" maintfile="$MAINTDBDIR/$1" - if [ -f "$maintfile" ] - then - exit 0 + if [ -f "$maintfile" ]; then + exit 0 fi echo "$2" > "$maintfile" } @@ -34,79 +32,67 @@ function maintset() checkname "$1" maintfile="$MAINTDBDIR/$1" newmaint="$2" - if ! [ -f "$maintfile" ] - then - echo "Error: package $1 does not exist in maintdb." >&2 - exit 1 + if [ ! -f "$maintfile" ]; then + echo "Error: package $1 does not exist in maintdb." >&2 + exit 1 fi curmaint=$(cat "$maintfile") - if [ a"$newmaint" = "anobody" ] - then - if [ a"$curmaint" = a"$user" ] - then - echo "$newmaint" > "$maintfile" - exit 0 - else - echo "Error: cannot set maintainer for $1." >&2 - exit 1 - fi - elif [ a"$newmaint" = a"$user" ] - then - if [ a"$curmaint" = "anobody" ] - then - echo "$newmaint" > "$maintfile" - exit 0 - else - echo "Error: cannot set maintainer for $1." >&2 - exit 1 - fi + if [ "$newmaint" = "nobody" ] || [[ "$newmaint" = *-team ]]; then + if [ "$curmaint" = "$user" ]; then + echo "$newmaint" > "$maintfile" + exit 0 + else + echo "Error: cannot set maintainer for $1." >&2 + exit 1 + fi + elif [ "$newmaint" = "$user" ]; then + if [ "$curmaint" = "nobody" ] || [[ "$curmaint" = *-team ]]; then + echo "$newmaint" > "$maintfile" + exit 0 + else + echo "Error: cannot set maintainer for $1." >&2 + exit 1 + fi else - echo "Error: cannot set someone else as maintainer." >&2 - exit 1 + echo "Error: cannot set someone else as maintainer." >&2 + exit 1 fi } function maintgetall() { cd "$MAINTDBDIR" - for file in * - do - echo "$file $(cat $file)" + for file in *; do + echo "$file $(cat $file)" done exit 0 } function maintget() { - if [ -z "$1" ] - then - maintgetall + if [ -z "$1" ]; then + maintgetall fi checkname "$1" maintfile="$MAINTDBDIR/$1" - if [ -f "$maintfile" ] - then - cat "$maintfile" + if [ -f "$maintfile" ]; then + cat "$maintfile" else - echo "Error: package $1 does not exist in maintdb." >&2 - exit 1 + echo "Error: package $1 does not exist in maintdb." >&2 + exit 1 fi } user="$1" action="$2" -if [ a"$action" = "anew" ] -then +if [ "$action" = "new" ]; then maintnew "$3" "$4" -elif [ a"$action" = "aset" ] -then +elif [ "$action" = "set" ]; then maintset "$3" "$4" -elif [ a"$action" = "aget" ] -then +elif [ "$action" = "get" ]; then maintget "$3" else - echo "Error: unknow command." >&2 + echo "Error: unknown command." >&2 exit 2 fi - diff --git a/modules/buildsystem/templates/maintdb/sudoers.maintdb b/modules/buildsystem/templates/maintdb/sudoers.maintdb index 8dd19c42..91c88e47 100644 --- a/modules/buildsystem/templates/maintdb/sudoers.maintdb +++ b/modules/buildsystem/templates/maintdb/sudoers.maintdb @@ -1,2 +1,4 @@ -%<%= scope.lookupvar('buildsystem::base::packagers_group') %> ALL =(<%= login %>) NOPASSWD: <%= binpath %> -<%= scope.lookupvar('buildsystem::base::sched_login') %> ALL =(<%= login %>) NOPASSWD: <%= binpath %> +%<%= scope.lookupvar('buildsystem::var::groups::packagers') %> ALL =(<%= scope.lookupvar('buildsystem::var::maintdb::login') %>) NOPASSWD: <%= scope.lookupvar('buildsystem::var::maintdb::binpath') %> [a-z]* get +%<%= scope.lookupvar('buildsystem::var::groups::packagers') %> ALL =(<%= scope.lookupvar('buildsystem::var::maintdb::login') %>) NOPASSWD: <%= scope.lookupvar('buildsystem::var::maintdb::binpath') %> [a-z]* [gs]et [a-zA-Z0-9]* +%<%= scope.lookupvar('buildsystem::var::groups::packagers') %> ALL =(<%= scope.lookupvar('buildsystem::var::maintdb::login') %>) NOPASSWD: <%= scope.lookupvar('buildsystem::var::maintdb::binpath') %> [a-z]* set [a-zA-Z0-9]* [a-z]* +<%= scope.lookupvar('buildsystem::var::scheduler::login') %> ALL =(<%= scope.lookupvar('buildsystem::var::maintdb::login') %>) NOPASSWD: <%= scope.lookupvar('buildsystem::var::maintdb::binpath') %> [a-z]* new [a-zA-Z0-9]* [a-z]* diff --git a/modules/buildsystem/templates/maintdb/vhost_maintdb.conf b/modules/buildsystem/templates/maintdb/vhost_maintdb.conf index 225c7215..146413a7 100644 --- a/modules/buildsystem/templates/maintdb/vhost_maintdb.conf +++ b/modules/buildsystem/templates/maintdb/vhost_maintdb.conf @@ -1,3 +1,3 @@ -<Directory <%= dbdir %>> +<Directory <%= scope.lookupvar('buildsystem::var::maintdb::dbdir') %>> Options None </Directory> diff --git a/modules/buildsystem/templates/maintdb/wrapper.maintdb b/modules/buildsystem/templates/maintdb/wrapper.maintdb index 8420022d..fcf69dab 100644 --- a/modules/buildsystem/templates/maintdb/wrapper.maintdb +++ b/modules/buildsystem/templates/maintdb/wrapper.maintdb @@ -1,8 +1,8 @@ #!/bin/sh -maintdbuser="<%= login %>" -maintdbpath="<%= binpath %>" -packagersgroup="<%= scope.lookupvar('buildsystem::base::packagers_group') %>" +maintdbuser="<%= scope.lookupvar('buildsystem::var::maintdb::login') %>" +maintdbpath="<%= scope.lookupvar('buildsystem::var::maintdb::binpath') %>" +packagersgroup="<%= scope.lookupvar('buildsystem::var::groups::packagers') %>" function isingroup() { @@ -22,5 +22,4 @@ then exit 1 fi -sudo -u "$maintdbuser" "$maintdbpath" $(whoami) $@ - +sudo -u "$maintdbuser" "$maintdbpath" $(whoami) "$@" diff --git a/modules/buildsystem/templates/media.cfg b/modules/buildsystem/templates/media.cfg index e0470733..64757a2b 100644 --- a/modules/buildsystem/templates/media.cfg +++ b/modules/buildsystem/templates/media.cfg @@ -1,395 +1,142 @@ +<%- +def media_name(media, repo, type, archname) + name = [ media.capitalize ] + if archname != nil + name += [ archname ] + end + for r in repo.split('_') do + name += [ r.capitalize ] + end + if type != nil + name += [ type.capitalize ] + end + return name.join(' ') +end + +def media_out(name, media_hash) + media_out = "[%s]\n" % name + media_hash.keys.sort.each{|key| + value = media_hash[key] + if value != nil + media_out += "%s=%s\n" % [ key, value ] + end + } + return media_out +end +distro = scope.lookupvar('buildsystem::var::distros::distros')[@distro_name] +-%> [media_info] -<% - if @distro == 'cauldron' -%>version=3<% - else -%>version=<%= @distro %><% end %> +version=<%= distro['version'] %> mediacfg_version=2 -<% - if @distro == 'cauldron' -%>branch=Devel<% - else -%>branch=Official<% - end -%> +branch=<%= distro['branch'] %> +<%- +if @arch != 'armv7hl' +-%> arch=<%= @arch %> +<%- +end +-%> xml-info=1 -[core/release] -hdlist=hdlist_core_release.cz -name=Core Release -srpms=../../SRPMS/core/release -media_type=official:free:release - -[debug/core/release] -hdlist=hdlist_debug_core_release.cz -name=Core Release Debug -srpms=../../SRPMS/debug/core/release -media_type=official:free:release:debug -noauto=1 - -[../../SRPMS/core/release] -hdlist=hdlist_core_release.src.cz -name=Core Release Sources -rpms=core/release -media_type=official:free:release:source -noauto=1 - -[core/updates] -hdlist=hdlist_core_updates.cz -name=Core Updates -srpms=../../SRPMS/core/updates -media_type=official:free:updates -updates_for=core/release - -[debug/core/updates] -hdlist=hdlist_debug_core_updates.cz -name=Core Updates Debug -srpms=../../SRPMS/debug/core/updates -media_type=official:free:updates:debug -noauto=1 - -[../../SRPMS/core/updates] -hdlist=hdlist_core_updates.src.cz -name=Core Updates Sources -rpms=core/updates -media_type=official:free:updates:source -noauto=1 - -[core/updates_testing] -hdlist=hdlist_core_updates_testing.cz -name=Core Updates Testing -srpms=../../SRPMS/core/updates_testing -media_type=official:free:testing -noauto=1 - -[debug/core/updates_testing] -hdlist=hdlist_debug_core_updates_testing.cz -name=Core Updates Testing Debug -srpms=../../SRPMS/debug/core/updates_testing -media_type=official:free:testing:debug -noauto=1 - -[../../SRPMS/core/updates_testing] -hdlist=hdlist_core_updates_testing.src.cz -name=Core Updates Testing Sources -rpms=core/updates_testing -media_type=official:free:testing:source -noauto=1 - -[core/backports] -hdlist=hdlist_core_backports.cz -name=Core Backports -srpms=../../SRPMS/core/backports -media_type=official:free:backports -noauto=1 - -[debug/core/backports] -hdlist=hdlist_debug_core_backports.cz -name=Core Backports Debug -srpms=../../SRPMS/debug/core/backports -media_type=official:free:backports:debug -noauto=1 - -[../../SRPMS/core/backports] -hdlist=hdlist_core_backports.src.cz -name=Core Backports Sources -rpms=core/backports -media_type=official:free:backports:source -noauto=1 - -[core/backports_testing] -hdlist=hdlist_core_backports_testing.cz -name=Core Backports Testing -srpms=../../SRPMS/core/backports_testing -media_type=official:free:backports:testing -noauto=1 - -[debug/core/backports_testing] -hdlist=hdlist_debug_core_backports_testing.cz -name=Core Backports Testing Debug -srpms=../../SRPMS/debug/core/backports_testing -media_type=official:free:backports:testing:debug -noauto=1 - -[../../SRPMS/core/backports_testing] -hdlist=hdlist_core_backports_testing.src.cz -name=Core Backports Testing Sources -rpms=core/backports_testing -media_type=official:free:backports:testing:source -noauto=1 - -[nonfree/release] -hdlist=hdlist_nonfree_release.cz -name=Nonfree Release -srpms=../../SRPMS/nonfree/release -media_type=official:release -noauto=1 - -[debug/nonfree/release] -hdlist=hdlist_debug_nonfree_release.cz -name=Nonfree Release Debug -srpms=../../SRPMS/debug/nonfree/release -media_type=official:release:debug -noauto=1 - -[../../SRPMS/nonfree/release] -hdlist=hdlist_nonfree_release.src.cz -name=Nonfree Release Sources -rpms=nonfree/release -media_type=official:release:source -noauto=1 - -[nonfree/updates] -hdlist=hdlist_nonfree_updates.cz -name=Nonfree Updates -srpms=../../SRPMS/nonfree/updates -media_type=official:updates -updates_for=nonfree/release -noauto=1 - -[debug/nonfree/updates] -hdlist=hdlist_debug_nonfree_updates.cz -name=Nonfree Updates Debug -srpms=../../SRPMS/debug/nonfree/updates -media_type=official:updates:debug -noauto=1 - -[../../SRPMS/nonfree/updates] -hdlist=hdlist_nonfree_updates.src.cz -name=Nonfree Updates Sources -rpms=nonfree/updates -media_type=official:updates:source -noauto=1 - -[nonfree/updates_testing] -hdlist=hdlist_nonfree_updates_testing.cz -name=Nonfree Updates Testing -srpms=../../SRPMS/nonfree/updates_testing -media_type=official:testing -noauto=1 - -[debug/nonfree/updates_testing] -hdlist=hdlist_debug_nonfree_updates_testing.cz -name=Nonfree Updates Testing Debug -srpms=../../SRPMS/debug/nonfree/updates_testing -media_type=official:testing:debug -noauto=1 - -[../../SRPMS/nonfree/updates_testing] -hdlist=hdlist_nonfree_updates_testing.src.cz -name=Nonfree Updates Testing Sources -rpms=nonfree/updates_testing -media_type=official:testing:source -noauto=1 - -[nonfree/backports] -hdlist=hdlist_nonfree_backports.cz -name=Nonfree Backports -srpms=../../SRPMS/nonfree/backports -media_type=official:backports -noauto=1 - -[debug/nonfree/backports] -hdlist=hdlist_debug_nonfree_backports.cz -name=Nonfree Backports Debug -srpms=../../SRPMS/debug/nonfree/backports -media_type=official:backports:debug -noauto=1 - -[../../SRPMS/nonfree/backports] -hdlist=hdlist_nonfree_backports.src.cz -name=Nonfree Backports Sources -rpms=nonfree/backports -media_type=official:backports:source -noauto=1 - -[nonfree/backports_testing] -hdlist=hdlist_nonfree_backports_testing.cz -name=Nonfree Backports Testing -srpms=../../SRPMS/nonfree/backports_testing -media_type=official:backports:testing -noauto=1 - -[debug/nonfree/backports_testing] -hdlist=hdlist_debug_nonfree_backports_testing.cz -name=Nonfree Backports Testing Debug -srpms=../../SRPMS/debug/nonfree/backports_testing -media_type=official:backports:testing:debug -noauto=1 - -[../../SRPMS/nonfree/backports_testing] -hdlist=hdlist_nonfree_backports_testing.src.cz -name=Nonfree Backports Testing Sources -rpms=nonfree/backports_testing -media_type=official:backports:testing:source -noauto=1 - -[tainted/release] -hdlist=hdlist_tainted_release.cz -name=Tainted Release -srpms=../../SRPMS/tainted/release -media_type=official:release -noauto=1 - -[debug/tainted/release] -hdlist=hdlist_debug_tainted_release.cz -name=Tainted Release Debug -srpms=../../SRPMS/debug/tainted/release -media_type=official:release:debug -noauto=1 - -[../../SRPMS/tainted/release] -hdlist=hdlist_tainted_release.src.cz -name=Tainted Release Sources -rpms=tainted/release -media_type=official:release:source -noauto=1 - -[tainted/updates] -hdlist=hdlist_tainted_updates.cz -name=Tainted Updates -srpms=../../SRPMS/tainted/updates -media_type=official:updates -updates_for=tainted/release -noauto=1 - -[debug/tainted/updates] -hdlist=hdlist_debug_tainted_updates.cz -name=Tainted Updates Debug -srpms=../../SRPMS/debug/tainted/updates -media_type=official:updates:debug -noauto=1 - -[../../SRPMS/tainted/updates] -hdlist=hdlist_tainted_updates.src.cz -name=Tainted Updates Sources -rpms=tainted/updates -media_type=official:updates:source -noauto=1 - -[tainted/updates_testing] -hdlist=hdlist_tainted_updates_testing.cz -name=Tainted Updates Testing -srpms=../../SRPMS/tainted/updates_testing -media_type=official:testing -noauto=1 - -[debug/tainted/updates_testing] -hdlist=hdlist_debug_tainted_updates_testing.cz -name=Tainted Updates Testing Debug -srpms=../../SRPMS/debug/tainted/updates_testing -media_type=official:testing:debug -noauto=1 - -[../../SRPMS/tainted/updates_testing] -hdlist=hdlist_tainted_updates_testing.src.cz -name=Tainted Updates Testing Sources -rpms=tainted/updates_testing -media_type=official:testing:source -noauto=1 - -[tainted/backports] -hdlist=hdlist_tainted_backports.cz -name=Tainted Backports -srpms=../../SRPMS/tainted/backports -media_type=official:backports -noauto=1 - -[debug/tainted/backports] -hdlist=hdlist_debug_tainted_backports.cz -name=Tainted Backports Debug -srpms=../../SRPMS/debug/tainted/backports -media_type=official:backports:debug -noauto=1 - -[../../SRPMS/tainted/backports] -hdlist=hdlist_tainted_backports.src.cz -name=Tainted Backports Sources -rpms=tainted/backports -media_type=official:backports:source -noauto=1 - -[tainted/backports_testing] -hdlist=hdlist_tainted_backports_testing.cz -name=Tainted Backports Testing -srpms=../../SRPMS/tainted/backports_testing -media_type=official:backports:testing -noauto=1 - -[debug/tainted/backports_testing] -hdlist=hdlist_debug_tainted_backports_testing.cz -name=Tainted Backports Testing Debug -srpms=../../SRPMS/debug/tainted/backports_testing -media_type=official:backports:testing:debug -noauto=1 - -[../../SRPMS/tainted/backports_testing] -hdlist=hdlist_tainted_backports_testing.src.cz -name=Tainted Backports Testing Sources -rpms=tainted/backports_testing -media_type=official:backports:testing:source -noauto=1 - -<% - if arch == 'x86_64' -%>[../../i586/media/core/release] -hdlist=hdlist_core32_release.cz -name=Core 32bit Release -media_type=official:free:release - -[../../i586/media/debug/core/release] -hdlist=hdlist_debug_core32_release.cz -name=Core 32bit Release Debug -media_type=official:free:release:debug -noauto=1 - -[../../i586/media/core/updates] -hdlist=hdlist_core32_updates.cz -name=Core 32bit Updates -media_type=official:free:updates -updates_for=../../i586/media/core/release - -[../../i586/media/debug/core/updates] -hdlist=hdlist_debug_core32_updates.cz -name=Core 32bit Updates Debug -media_type=official:free:updates:debug -noauto=1 - -[../../i586/media/core/updates_testing] -hdlist=hdlist_core32_updates_testing.cz -name=Core 32bit Updates Testing -media_type=official:free:testing -noauto=1 - -[../../i586/media/debug/core/updates_testing] -hdlist=hdlist_debug_core32_updates_testing.cz -name=Core 32bit Updates Testing Debug -media_type=official:free:testing:debug -noauto=1 - -[../../i586/media/core/backports] -hdlist=hdlist_core32_backports.cz -name=Core 32bit Backports -media_type=official:free:backports -noauto=1 - -[../../i586/media/debug/core/backports] -hdlist=hdlist_debug_core32_backports.cz -name=Core 32bit Backports Debug -media_type=official:free:backports:debug -noauto=1 - -[../../i586/media/core/backports_testing] -hdlist=hdlist_core32_backports_testing.cz -name=Core 32bit Backports Testing -media_type=official:free:backports:testing -noauto=1 - -[../../i586/media/debug/core/backports_testing] -hdlist=hdlist_debug_core32_backports_testing.cz -name=Core 32bit Backports Testing Debug -media_type=official:free:backports:testing:debug -noauto=1<% - end -%> +<%- +distro['medias'].keys.sort { |x,y| distro['medias'][x]['order'] <=> distro['medias'][y]['order'] }.each{|medianame| + media = distro['medias'][medianame] + media['repos'].keys.sort { |x,y| media['repos'][x]['order'] <=> media['repos'][y]['order'] }.each{|reponame| + repo = media['repos'][reponame] + media_type = [] + if media['media_type'] != nil + media_type += media['media_type'] + end + if repo['media_type'] != nil + media_type += repo['media_type'] + end + noauto=nil + if (media['noauto'] == '1') or (repo['noauto'] == '1') + noauto='1' + end + updates_for = nil + if repo['updates_for'] != nil + updates_for = [ medianame, repo['updates_for'] ].join('/') + end + -%><%= + media_out [ medianame, reponame ].join('/'), + :hdlist => [ 'hdlist', medianame, reponame ].join('_') + '.cz', + :name => media_name(medianame, reponame, nil, nil), + :srpms => [ '../../SRPMS', medianame, reponame ].join('/'), + :media_type => media_type.join(':'), + :updates_for => updates_for, + :noauto => noauto + + %> + <%-# debug -%> + <%- + debug_media_type = media_type + [ 'debug' ] + -%><%= + media_out [ 'debug', medianame, reponame ].join('/'), + :hdlist => [ 'hdlist_debug', medianame, reponame ].join('_') + '.cz', + :name => media_name(medianame, reponame, 'debug', nil), + :srpms => [ '../../SRPMS', medianame, reponame ].join('/'), + :media_type => debug_media_type.join(':'), + :noauto => '1' + + %> + <%-# source -%> + <%- + source_media_type = media_type + [ 'source' ] + -%><%= + media_out [ '../../SRPMS', medianame, reponame ].join('/'), + :hdlist => [ 'hdlist', medianame, reponame ].join('_') + '.src.cz', + :name => media_name(medianame, reponame, 'sources', nil), + :rpms => [ medianame, reponame ].join('/'), + :media_type => source_media_type.join(':'), + :noauto => '1' + + %> + <%-# we add 32bit media if arch is x86_64 -%> + <%- + if @arch == 'x86_64' and distro['arch'].include?('i586') + medianame32 = [ medianame, '32' ].join('') + -%><%= + media_out [ '../../i586/media', medianame, reponame ].join('/'), + :hdlist => [ 'hdlist', medianame32, reponame ].join('_') + '.src.cz', + :name => media_name(medianame, reponame, nil, '32bit'), + :media_type => media_type.join(':'), + :noauto => noauto + + %> + <%- + end + if @arch == 'x86_64' and distro['arch'].include?('i686') + medianame32 = [ medianame, '32' ].join('') + -%><%= + media_out [ '../../i686/media', medianame, reponame ].join('/'), + :hdlist => [ 'hdlist', medianame32, reponame ].join('_') + '.src.cz', + :name => media_name(medianame, reponame, nil, '32bit'), + :media_type => media_type.join(':'), + :noauto => noauto + + %> + <%- + end + } +} +if distro['based_on'] != nil + distro['based_on'].keys.sort.each{|bdistroname| + bdistro = distro['based_on'][bdistroname] + bdistro.keys.sort.each{|medianame| + media = bdistro[medianame] + for reponame in media + -%><%= + media_out [ bdistroname, medianame, reponame ].join('/'), + :hdlist => [ 'hdlist', bdistroname, medianame, + reponame ].join('_'), + :name => media_name([ medianame, bdistroname].join(''), reponame, nil, nil), + :media_type => 'base_distro', + :noauto => 1 + %> + <%- + end + } + } +end +-%> diff --git a/modules/buildsystem/templates/mgarepo.conf b/modules/buildsystem/templates/mgarepo.conf index 81c21d3b..fbe5109c 100644 --- a/modules/buildsystem/templates/mgarepo.conf +++ b/modules/buildsystem/templates/mgarepo.conf @@ -1,25 +1,27 @@ +<%- + default_distro = scope.lookupvar('buildsystem::var::distros::default_distro') + distros = scope.lookupvar('buildsystem::var::distros::distros') +-%> [global] verbose = no -default_parent = svn://svn.<%= domain %>/svn/packages/cauldron +default_parent = <%= scope.lookupvar('buildsystem::var::mgarepo::svn_root_packages') %>/<%= default_distro %> #url-map = svn\+ssh://svn\.mageia\.org/(.*) file:///\1 tempdir = <%= sched_home_dir %>/repsys/tmp -use-binaries-repository = yes -binaries-repository = svn://svn.<%= domain %>/svn/binrepos -# ldap settings -# ldap is searched first: if not found, then [users] is read -# if ldap search matched, then [users] is not consulted -# if ldap is down, [users] is not consulted either -# -# we should have a generic fqdn here to use round-robin DNS -# enhancement for repsys: support multiple ldap servers here -ldap-server = ldap.<%= domain %> -ldap-base = ou=People,<%= dc_suffix %> -ldap-filterformat = (&(objectClass=inetOrgPerson)(uid=$username)) -ldap-resultformat = $cn <$mail> -trunk-dir = cauldron +trunk-dir = <%= default_distro %> +<%- +conf = scope.lookupvar('buildsystem::var::mgarepo::conf') +if conf['global'] != nil + conf['global'].keys.sort.each{|key| + value = conf['global'][key] + -%><%= key %> = <%= value %> +<%- + } +end +-%> + [log] -oldurl = svn+ssh://svn.<%= domain %>/svn/packages/misc +oldurl = <%= scope.lookupvar('buildsystem::var::mgarepo::oldurl') %> # controls up to which revision the rpm changelog # will be constructed (default zero, i.e., oldest # commit) @@ -28,63 +30,46 @@ oldurl = svn+ssh://svn.<%= domain %>/svn/packages/misc ignore-string = SILENT [template] -path = /usr/share/repsys/default.chlog +path = /usr/share/mgarepo/default.chlog [users] iurt = Mageia build bot <mageia-sysadm@<%= domain %>> [submit] -default = cauldron -host = pkgsubmit.<%= domain %> - -[submit cauldron] -target = <%= sched_home_dir %>/repsys/srpms -allowed = svn://svn.<%= domain %>/svn/packages/cauldron -rpm-macros = global cauldron - -[submit 1] -target = <%= sched_home_dir %>/repsys/srpms -allowed = svn://svn.<%= domain %>/svn/packages/updates/1 -rpm-macros = global 1 - -[submit 2] +default = <%= default_distro %> +host = <%= scope.lookupvar('buildsystem::var::mgarepo::submit_host') %> + +<%- + distros.keys.sort.each{|d| + distro = distros[d] +-%> +[submit <%= d %>] target = <%= sched_home_dir %>/repsys/srpms -allowed = svn://svn.<%= domain %>/svn/packages/updates/2 -rpm-macros = global 2 +allowed = <%= distro['submit_allowed'] %> <%= distro['backports_allowed'] %> +rpm-macros = global <%= d %> -[submit infra_1] -target = <%= sched_home_dir %>/repsys/srpms -allowed = svn://svn.mageia.org/svn/packages/ -rpm-macros = global 1 - -[submit infra_2] -target = <%= sched_home_dir %>/repsys/srpms -allowed = svn://svn.mageia.org/svn/packages/ -rpm-macros = global 2 +<%- + } +-%> [macros global] -distsuffix = .mga # mkrel definition to be removed when rpm-setup is updated on main build node mkrel(c:) = %{-c: 0.%{-c*}.}%{1}%{?subrel:.%subrel}%{?distsuffix:%distsuffix}%{?!distsuffix:.mga}%{?distro_release:%distro_release} -distribution = Mageia -vendor = Mageia.Org -_real_vendor = mageia - -[macros cauldron] -distro_release = 3 -# 100 * major + minor -mgaversion = 300 -mageia_branch = cauldron - -[macros 1] -distro_release = 1 -# 100 * major + minor -mgaversion = 100 - -[macros 2] -distro_release = 2 -# 100 * major + minor -mgaversion = 200 +dist = %{?distsuffix:%distsuffix}%{?!distsuffix:.mga}%{?distro_release:%distro_release} + +<%- + distros.keys.sort.each{|d| + distro = distros[d] +-%> +[macros <%= d %>] +distro_release = <%= distro['version'] %> +<%- + distro['macros'].keys.sort.each{|macro| + value = distro['macros'][macro] + -%><%= macro %> = <%= value %> + <%- } %> +<%- } +%> [helper] create-srpm = /usr/share/repsys/create-srpm @@ -97,6 +82,7 @@ upload-bin = /usr/local/bin/wrapper.upload-bin run-prep = yes [binrepo] -download_url = http://binrepo.<%= domain %>/ -upload_host = binrepo.<%= domain %> +<%- binrepo_hostname = scope.lookupvar('buildsystem::var::binrepo::hostname') -%> +download_url = http://<%= binrepo_hostname %>/ +upload_host = <%= binrepo_hostname %> diff --git a/modules/buildsystem/templates/repoctl.conf b/modules/buildsystem/templates/repoctl.conf index a538fcde..14506a25 100644 --- a/modules/buildsystem/templates/repoctl.conf +++ b/modules/buildsystem/templates/repoctl.conf @@ -1,3 +1,21 @@ +<%- +distribdir = scope.lookupvar('buildsystem::var::repository::distribdir') +distros = scope.lookupvar('buildsystem::var::distros::distros') +arches = {} +distrosections = {} +sectionsrepos = {} +distros.each{|distroname, distro| + distro['medias'].each{|medianame, media| + distrosections[medianame] = 1 + media['repos'].each{|reponame, repo| + sectionsrepos[reponame] = 1 + } + } + distro['arch'].each{|arch| + arches[arch] = 1 + } +} +-%> dryrun=echo if [ -z $SUDO_USER ] then @@ -7,14 +25,14 @@ else fi lockdir=/var/lib/repoctl/locks hdlistsdir=/var/lib/repoctl/hdlists -rootdir=/distrib/bootstrap -finalrootdir=/distrib/mirror -distribdir=$rootdir/distrib -finaldistribdir=$finalrootdir/distrib -distroreleases='<%= distroreleases.flatten.join(' ') -%>' -distrosections='<%= distrosections.flatten.join(' ') -%>' -sectionsrepos='<%= sectionsrepos.flatten.join(' ') -%>' -arches='<%= arches.flatten.join(' ') -%>' +rootdir=<%= scope.lookupvar('buildsystem::var::repository::bootstrap_root') %> +finalrootdir=<%= scope.lookupvar('buildsystem::var::repository::mirror_root') %> +distribdir=$rootdir/<%= distribdir %> +finaldistribdir=$finalrootdir/<%= distribdir %> +distroreleases='<%= distros.keys.sort.join(' ') -%>' +distrosections='<%= distrosections.keys.sort.join(' ') -%>' +sectionsrepos='<%= sectionsrepos.keys.sort.join(' ') -%>' +arches='<%= arches.keys.sort.join(' ') -%>' mirror_rsync_options="-v --delete -alH" timestampfile="mageia_timestamp" sha1sumfile="mageia_sha1sum" diff --git a/modules/buildsystem/templates/signbot/sudoers.signpackage b/modules/buildsystem/templates/signbot/sudoers.signpackage index 05653d30..4ea30238 100644 --- a/modules/buildsystem/templates/signbot/sudoers.signpackage +++ b/modules/buildsystem/templates/signbot/sudoers.signpackage @@ -1,2 +1,2 @@ -<%= sched_login %> ALL =(<%= login %>) NOPASSWD: /usr/local/bin/mga-signpackage -<%= sched_login %> ALL =(<%= login %>) NOPASSWD: /usr/local/bin/sign-check-package +<%= sched_login %> ALL =(<%= scope.lookupvar('buildsystem::var::signbot::login') %>) NOPASSWD: /usr/local/bin/mga-signpackage +<%= sched_login %> ALL =(<%= scope.lookupvar('buildsystem::var::signbot::login') %>) NOPASSWD: /usr/local/bin/sign-check-package diff --git a/modules/buildsystem/templates/submit_package.pl b/modules/buildsystem/templates/submit_package.pl index 2b0e966d..1fdf7749 100755 --- a/modules/buildsystem/templates/submit_package.pl +++ b/modules/buildsystem/templates/submit_package.pl @@ -2,8 +2,8 @@ use strict; use warnings; -my $svn_server = 'svn.<%= domain %>'; -my $packagersgroup="<%= scope.lookupvar('buildsystem::base::packagers_group') %>"; +my $svn_server = '<%= scope.lookupvar('buildsystem::var::mgarepo::svn_hostname') %>'; +my $packagersgroup="<%= scope.lookupvar('buildsystem::var::groups::packagers') %>"; my $login = getpwuid($<); my (undef, undef, undef, $members) = getgrnam $packagersgroup; diff --git a/modules/buildsystem/templates/sudoers.iurt b/modules/buildsystem/templates/sudoers.iurt new file mode 100644 index 00000000..21e81e87 --- /dev/null +++ b/modules/buildsystem/templates/sudoers.iurt @@ -0,0 +1 @@ +<%= scope.lookupvar('buildsystem::var::iurt::login') %> ALL = NOPASSWD: /usr/sbin/iurt_root_command diff --git a/modules/buildsystem/templates/sudoers.youri b/modules/buildsystem/templates/sudoers.youri index f3fa35b0..3bc7cc2d 100644 --- a/modules/buildsystem/templates/sudoers.youri +++ b/modules/buildsystem/templates/sudoers.youri @@ -1,5 +1,6 @@ +<%- sched_login = scope.lookupvar('buildsystem::var::scheduler::login') -%> Cmnd_Alias YOURI = /usr/local/bin/mga-youri-submit.wrapper Defaults!YOURI always_set_home Defaults!YOURI runas_default = <%= sched_login %> Defaults!YOURI !requiretty -%mga-packagers ALL = (<%= sched_login %>) NOPASSWD: YOURI +%<%= scope.lookupvar('buildsystem::var::groups::packagers') -%> ALL = (<%= sched_login %>) NOPASSWD: YOURI diff --git a/modules/buildsystem/templates/sync2010.1 b/modules/buildsystem/templates/sync2010.1 deleted file mode 100644 index 5f8eeebf..00000000 --- a/modules/buildsystem/templates/sync2010.1 +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -if [ `whoami` != <%= sched_login %> ] -then - echo 'this script should be run as <%= sched_login %>' >&2 - exit 1 -fi - -cd /distrib/mandriva/2010.1-mgaserv || exit 1 -rsync -avH <%= build_login %>@jonund:/home/iurt/2010.1-SRPMS/ ./SRPMS - -for i in i586 x86_64; do - mkdir -p $i - cd $i - rsync -avH <%= build_login %>@jonund:/home/iurt/iurt/mandriva2010.1/$i/*.rpm . - ssh <%= build_login %>@jonund rm -f '/home/iurt/iurt/mandriva2010.1/$i/*.rpm' - genhdlist2 . - cd .. -done - diff --git a/modules/buildsystem/templates/upload.conf b/modules/buildsystem/templates/upload.conf index 0118ca7c..af610c92 100644 --- a/modules/buildsystem/templates/upload.conf +++ b/modules/buildsystem/templates/upload.conf @@ -7,12 +7,20 @@ # ### +<%- + build_nodes = scope.lookupvar('buildsystem::var::scheduler::build_nodes') +-%> my %nodes = ( - i586 => [ qw(jonund0 ecosse0 jonund1 ecosse1 ) ], - x86_64 => [ qw(ecosse0 jonund0 ecosse1 jonund1 ) ], +<%- + build_nodes.keys.sort.each{|arch| +-%> + <%= arch -%> => [ '<%= build_nodes[arch].join("', '") -%>' ], +<%- + } +-%> ); -my $repository = "http://repository.<%= domain %>/distrib/"; -my $homedir = "<%= homedir %>"; +my $repository = "http://<%= scope.lookupvar('buildsystem::var::repository::hostname') %>/<%= scope.lookupvar('buildsystem::var::repository::distribdir') %>/"; +my $homedir = "<%= scope.lookupvar('buildsystem::var::iurt::homedir') %>"; { bot => { @@ -23,7 +31,7 @@ my $homedir = "<%= homedir %>"; my $node = $_; ($node => { iurt => { - user => '<%= login %>', + user => '<%= scope.lookupvar('buildsystem::var::iurt::login') %>', # (spuk, 2007-08-16) disabled iurt_cache additional media, locks trying to mount -o bind # command => "iurt --copy-srpm --group -v 6 --config local_spool $homedir/iurt/__DIR__ --no_rsync --chrooted-urpmi -m __MEDIA__ -- $repository --additional-media -m __MEDIA__ -- file://$homedir/cache/ -p \"__PACKAGER__\" -r __TARGET__ __ARCH__", command => "iurt --copy_srpm --group --rpmmacros \"%distro_section __SECTION__\" --config local_spool $homedir/iurt/__DIR__ --no_rsync --chrooted-urpmi -m __MEDIA__ -- $repository -p \"__PACKAGER__\" -r __TARGET__ __ARCH__", @@ -35,39 +43,89 @@ my $homedir = "<%= homedir %>"; } keys %nodes), }, media => { - default => { - "infra/release" => [ "infra/release", "base/core/updates", "base/core/release" ], - "core/release" => [ "core/updates", "core/release" ], - "core/updates" => [ "core/updates", "core/release" ], - "core/updates_testing" => [ "core/updates_testing", "core/updates", "core/release" ], - "core/backports" => [ "core/backports", "core/updates_testing", "core/updates", "core/release" ], - "core/backports_testing" => [ "core/backports_testing", "core/backports", "core/updates_testing", "core/updates", "core/release" ], - "nonfree/release" => [ "core/release", "nonfree/release" ], - "nonfree/updates" => [ "core/updates", "core/release", "nonfree/release", "nonfree/updates" ], - "nonfree/updates_testing" => [ "core/updates", "core/release", "core/updates_testing", "nonfree/release", "nonfree/updates", "nonfree/updates_testing" ], - "nonfree/backports" => [ "core/backports", "core/updates_testing", "core/updates", "core/release", - "nonfree/release", "nonfree/updates", "nonfree/updates_testing", "nonfree/backports" ], - "nonfree/backports_testing" => [ "core/backports_testing", "core/backports", "core/updates_testing", "core/updates", "core/release", - "nonfree/release", "nonfree/updates", "nonfree/updates_testing", "nonfree/backports", "nonfree/backports_testing" ], - "tainted/release" => [ "core/release", "nonfree/release", "tainted/release" ], - "tainted/updates" => [ "core/release", "nonfree/release", "tainted/release", - "core/updates", "nonfree/updates", "tainted/updates" ], - "tainted/updates_testing" => [ "core/release", "nonfree/release", "tainted/release", - "core/updates", "nonfree/updates", "tainted/updates", - "core/updates_testing", "nonfree/updates_testing", "tainted/updates_testing" ], - "tainted/backports" => [ "core/release", "nonfree/release", "tainted/release", - "core/updates", "nonfree/updates", "tainted/updates", - "core/updates_testing", "nonfree/updates_testing", "tainted/updates_testing", - "core/backports", "nonfree/backports", "tainted/backports" ], - "tainted/backports_testing" => [ "core/release", "nonfree/release", "tainted/release", - "core/updates", "nonfree/updates", "tainted/updates", - "core/updates_testing", "nonfree/updates_testing", "tainted/updates_testing", - "core/backports", "nonfree/backports", "tainted/backports", - "core/backports_testing", "nonfree/backports_testing", "tainted/backports_testing" ], - }, + <%- + def repo_deps(distros, dname, mname, rname) + deps = {} + distro = distros[dname] + if distro['based_on'] != nil + distro['based_on'].each{|bdistro, bmedias| + if bmedias[mname] != nil and \ + bmedias[mname].include?(rname) then + deps[ [ bdistro, mname, rname ].join('/') ] = 1 + end + } + end + if distro['medias'][mname] != nil \ + and distro['medias'][mname]['repos'][rname] != nil + then + deps[ [ mname, rname ].join('/') ] = 1 + else + return deps + end + mlist = distro['medias'][mname]['requires'] + mlist = mlist == nil ? [ mname ] : [ mname ] + mlist + mlist.each{|mreq| + rlist = distro['medias'][mname]['repos'][rname]['requires'] + rlist = [] if rlist == nil + rlist += [ rname ] if mreq != mname + rlist.each{|rreq| + deps.merge!(repo_deps(distros, dname, mreq, rreq)) + } + } + return deps + end + distros = scope.lookupvar('buildsystem::var::distros::distros') + distros.keys.sort.each{|distroname| + -%> + '<%= distroname -%>' => { + <%- + distro = distros[distroname] + distro['medias'].keys.sort.each{|medianame| + media = distro['medias'][medianame] + media['repos'].keys.sort.each{|reponame| + deps = repo_deps(distros, distroname, medianame, reponame) + -%> + "<%= [ medianame, reponame ].join('/') %>" => [ "<%= + deps.keys.sort.join('", "') + %>" ], + <%- + } + } + -%> + }, + <%- + } + -%> }, - admin => 'mageia-sysadm@mageia.org', - http_queue => 'http://pkgsubmit.<%= domain %>/uploads', - upload_user => '<%= sched_login %>', + admin => '<%= scope.lookupvar('buildsystem::var::scheduler::admin_mail') %>', + http_queue => 'https://<%= scope.lookupvar('buildsystem::var::webstatus::hostname') %>/uploads', + upload_user => '<%= scope.lookupvar('buildsystem::var::scheduler::login') %>', email_domain => '<%= domain %>', + arch => { + <%- + distros.keys.sort.each{|distroname| + -%> + <%= distroname -%> => [ '<%= distros[distroname]['arch'].join("', '") %>' ], + <%- + } + -%> + default => [ 'i586', 'x86_64' ], + }, + mandatory_arch => { + <%- + distros.keys.sort.each{|distroname| + if distros[distroname]['mandatory_arch'] != nil + march = distros[distroname]['mandatory_arch'] + else + march = distros[distroname]['arch'] + end + -%> + <%= distroname -%> => [ '<%= march.join("', '") %>' ], + <%- + } + -%> + default => [ 'i586', 'x86_64' ], + }, + ssh_options => "-o ServerAliveInterval=10 -o ConnectTimeout=20 -o BatchMode=yes", + faildelay => 360000, } diff --git a/modules/buildsystem/templates/vhost_pkgsubmit.conf b/modules/buildsystem/templates/vhost_pkgsubmit.conf deleted file mode 100644 index af8bb70c..00000000 --- a/modules/buildsystem/templates/vhost_pkgsubmit.conf +++ /dev/null @@ -1,4 +0,0 @@ -<Location /uploads> - Allow from all - Options Indexes -</Location> diff --git a/modules/buildsystem/templates/vhost_repository.conf b/modules/buildsystem/templates/vhost_repository.conf index 176b7f39..e082ffca 100644 --- a/modules/buildsystem/templates/vhost_repository.conf +++ b/modules/buildsystem/templates/vhost_repository.conf @@ -1,61 +1,73 @@ -<% -# FIXME: add a reverse lookup for IPv6 adresses -# allowed hosts are: valstar, ecosse, jonund -buildsystem_nodes = "2a02:2178:2:7::3/64 2a02:2178:2:7::4/64 2a02:2178:2:7::5/64" -%> - +<%- +mirror_root = scope.lookupvar('buildsystem::var::repository::mirror_root') +mirror_reporoot = scope.lookupvar('buildsystem::var::repository::mirror_reporoot') +bootstrap_reporoot = scope.lookupvar('buildsystem::var::repository::bootstrap_reporoot') +distribdir = scope.lookupvar('buildsystem::var::repository::distribdir') +repo_allow_from_ips = scope.lookupvar('buildsystem::var::distros::repo_allow_from_ips') +repo_allow_from_domains = scope.lookupvar('buildsystem::var::distros::repo_allow_from_ips') +distros = scope.lookupvar('buildsystem::var::distros::distros') +-%> <VirtualHost *:80> - ServerName repository.<%= domain %> + ServerName <%= scope.lookupvar('buildsystem::var::repository::hostname') %> DocumentRoot <%= mirror_root %> - Alias /distrib/infra_1/ "/distrib/bootstrap/distrib/infra_1/" - Alias /distrib/infra_2/ "/distrib/bootstrap/distrib/infra_2/" - Alias /mandriva/ "/distrib/mandriva/" - Alias /mageiatools/ "/distrib/mageiatools/" - <Directory <%= mirror_root %>> - Order deny,allow - Deny from all - Allow from localhost, 127.0.0.1 - Allow from <%= buildsystem_nodes %> - Allow from .<%= domain %> - Allow from 10.42.0 - # FIXME: add a reverse lookup for rabbit - Allow from 212.85.158.152 - Options Indexes FollowSymLinks - </Directory> + # Some simple API to check existence of SRPMs for QA + RewriteEngine On - <Directory /distrib/bootstrap/distrib/infra_1> - Header append Cache-Control "public, must-revalidate" - Order deny,allow - Allow from all - Options Indexes FollowSymLinks - </Directory> + RewriteCond /distrib/bootstrap/distrib/$2/SRPMS/$3/$1s_testing/$4.src.rpm -f + RewriteRule ^/qa/checksrpm/(update|backport)/([1-9][0-9]*)/([a-z_]+)/([^/]+)$ http://repository.mageia.org/qa/checksrpm/found [L,R=302] - <Directory /distrib/bootstrap/distrib/infra_2> - Header append Cache-Control "public, must-revalidate" - Order deny,allow - Allow from all - Options Indexes FollowSymLinks - </Directory> + RewriteRule ^/qa/checksrpm/ - [L,G] - <Directory /distrib/mandriva> - Order deny,allow - Deny from all - Allow from localhost, 127.0.0.1 - Allow from <%= buildsystem_nodes %> - Allow from .<%= domain %> - Options Indexes FollowSymLinks - </Directory> - - <Directory /distrib/mandriva/2010.1-mgaserv/> - Order deny,allow - Allow from all +<%- + if repo_allow_from_ips != nil || repo_allow_from_domains != nil then + access_requires = [ 'all denied' ] + if repo_allow_from_ips != nil then + for allow in repo_allow_from_ips do + access_requires << 'ip ' + allow + end + end + if repo_allow_from_domains != nil then + for allow in repo_allow_from_domains do + access_requires << 'host ' + allow + end + end + else + access_requires = [ 'all granted' ] + end +%> + Alias /bootstrap/ "<%= bootstrap_reporoot %>/" +<%- + distros.keys.sort.each{|distroname| + distro = distros[distroname] + if distro['no_mirror'] -%> + Alias /<%= distribdir %>/<%= distroname %>/ "<%= bootstrap_reporoot %>/<%= distroname %>/" +<%- + end + } +-%> + + <Directory <%= bootstrap_reporoot %>> + Header append Cache-Control "public, must-revalidate" +<%- + for req in access_requires do +-%> + Require <%= req %> +<%- + end +-%> Options Indexes FollowSymLinks </Directory> - <Directory /distrib/mageiatools> - Order deny,allow - Allow from all + <Directory <%= mirror_root %>> + Header append Cache-Control "public, must-revalidate" +<%- + for req in access_requires do +-%> + Require <%= req %> +<%- + end +-%> Options Indexes FollowSymLinks </Directory> </VirtualHost> diff --git a/modules/buildsystem/templates/vhost_webstatus.conf b/modules/buildsystem/templates/vhost_webstatus.conf new file mode 100644 index 00000000..3b0e6246 --- /dev/null +++ b/modules/buildsystem/templates/vhost_webstatus.conf @@ -0,0 +1,13 @@ +<Location /uploads> + Require all granted + Options Indexes + IndexOptions NameWidth=* +</Location> +<Location /autobuild> + Require all granted + Options Indexes + IndexOptions NameWidth=* +</Location> +<Directory /var/www/bs/autobuild> + Options FollowSymlinks FollowSymLinks +</Directory> diff --git a/modules/buildsystem/templates/youri/acl.conf b/modules/buildsystem/templates/youri/acl.conf index ada865f0..f0949f8a 100644 --- a/modules/buildsystem/templates/youri/acl.conf +++ b/modules/buildsystem/templates/youri/acl.conf @@ -1,5 +1 @@ .* .* .* ^glib$ ^blacklisted$ -.* .* .* ^cinnamon$ ^blacklisted$ -.* .* .* ^muffin$ ^blacklisted$ -.* .* .* ^nemo$ ^blacklisted$ -.* .* .* ^task-cinnamon$ ^blacklisted$ diff --git a/modules/buildsystem/templates/youri/host.conf b/modules/buildsystem/templates/youri/host.conf new file mode 100644 index 00000000..bf4fa086 --- /dev/null +++ b/modules/buildsystem/templates/youri/host.conf @@ -0,0 +1,23 @@ +<%- + aliases = scope.lookupvar('buildsystem::var::scheduler::build_nodes_aliases') + nodes = {} + nodes['src'] = [ scope.lookupvar('buildsystem::var::scheduler::build_src_node') ] + scope.lookupvar('buildsystem::var::scheduler::build_nodes').each{|arch,n| + a = arch + '|noarch|src' + nodes[a] = [] + n.each{|node| + if aliases[node] != nil + nodes[a] += [ aliases[node] ] + else + nodes[a] += [ node ] + end + } + } + str = '' + nodes.keys.sort.each{|arch| + nodes[arch].sort.uniq.each{|node| + str += node + ' ' + arch + "\n" + } + } +-%> +<%= str -%> diff --git a/modules/buildsystem/templates/youri/submit-todo.conf b/modules/buildsystem/templates/youri/submit-todo.conf deleted file mode 100644 index 2d5d18ff..00000000 --- a/modules/buildsystem/templates/youri/submit-todo.conf +++ /dev/null @@ -1,245 +0,0 @@ -<% -escaped_domain = domain.gsub('.','\.') -%> - -home: <%= sched_home_dir %> - -# repository declaration -repository: - class: Youri::Repository::Mageia - options: - install_root: <%= repository_root %>/distrib - upload_root: ${home}/uploads/ - upload_state: todo done queue - queue: todo - noarch: i586 - svn: svn+ssh://svn.<%= domain %>/svn/packages/cauldron/ - 2: - arch: i586 x86_64 - 1: - arch: i586 x86_64 - infra_1: - arch: i586 x86_64 - infra_2: - arch: i586 x86_64 - cauldron: - arch: i586 x86_64 - -# targets definition -targets: - cauldron: - checks: - - source - - deps - - version - #- svn - - tag - - acl - - host - #- section - - rpmlint - - recency - #- history - - queue_recency - actions: - - send - - rpminfo - - ulri - - 1: - checks: - - source - - version - #- svn - - tag - - acl - - host - #- section - - rpmlint - - recency - #- history - - queue_recency - actions: - - send - - rpminfo - - ulri - - 2: - checks: - - source - - version - #- svn - - tag - - acl - - host - #- section - - rpmlint - - recency - #- history - - queue_recency - actions: - - send - - rpminfo - - ulri - - infra_1: - checks: - - source - - version - - tag - - acl - - rpmlint - - recency - - queue_recency - actions: - - send - - rpminfo - - ulri - - infra_2: - checks: - - source - - version - - tag - - acl - - rpmlint - - recency - - queue_recency - actions: - - send - - rpminfo - - ulri - -# checks definition -checks: - tag: - class: Youri::Submit::Check::Tag - options: - tags: - release: 'mga\d+' - # packager: '<\S+@<%= escaped_domain %>>$' - distribution: '^Mageia' - vendor: '^Mageia.Org$' - - recency: - class: Youri::Submit::Check::Recency - - queue_recency: - class: Youri::Submit::Check::Queue_recency - - host: - class: Youri::Submit::Check::Host - options: - host_file: /etc/youri/host.conf - - section: - class: Youri::Submit::Check::Section - - rpmlint: - class: Youri::Submit::Check::Rpmlint - options: - config: /etc/rpmlint/config - results: - - buildprereq-use - - no-description-tag - - no-summary-tag - - non-standard-group - - non-xdg-migrated-menu - # it breaks dbus - #- patch-not-applied - - percent-in-conflicts - - percent-in-dependency - - percent-in-obsoletes - - percent-in-provides - - summary-ended-with-dot - - invalid-spec-name - - noarch-python-in-64bit-path - cauldron: - config: /usr/share/rpmlint/config - path: /usr/bin/rpmlint - 1: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - 2: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - infra_1: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - infra_2: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - svn: - class: Youri::Submit::Check::SVN - - acl: - class: Youri::Submit::Check::ACL - options: - acl_file: /etc/youri/acl.conf - - history: - class: Youri::Submit::Check::History - - source: - class: Youri::Submit::Check::Source - - precedence: - class: Youri::Submit::Check::Precedence - options: - target: cauldron - - version: - class: Youri::Submit::Check::Version - options: - 2: - authorized_packages: none_package_authorized - authorized_sections: ^(core|nonfree|tainted)/(updates_testing|backports_testing)$ - authorized_arches: none - mode: freeze - - 1: - authorized_packages: none_package_authorized - # authorized_sections: ^(core|nonfree|tainted)/(updates_testing|backports_testing)$ - authorized_arches: none - mode: freeze - - cauldron: - authorized_sections: ^[a-z]+/updates_testing$ - authorized_packages: ^$ - authorized_arches: none - authorized_users: ^<%= scope.function_group_members(['mga-release_managers']).join('|') %>$ - mode: normal -# mode: version_freeze -# mode: freeze - - deps: - class: Youri::Submit::Check::Deps - -# actions definitions -actions: - send: - class: Youri::Submit::Action::Send - options: - user: <%= sched_login %> - keep_svn_release: yes - uphost: pkgsubmit.<%= domain %> - root: ${home}/uploads - ssh_key: ${home}/.ssh/id_rsa - - rpminfo: - class: Youri::Submit::Action::Rpminfo - options: - user: <%= sched_login %> - uphost: pkgsubmit.<%= domain %> - root: ${home}/uploads - ssh_key: ${home}/.ssh/id_rsa - - ulri: - class: Youri::Submit::Action::Ulri - options: - user: <%= sched_login %> - uphost: pkgsubmit.<%= domain %> - ssh_key: ${home}/.ssh/id_rsa - logfile: /var/log/<%= sched_login %>/ulri.log - -# vim:ft=yaml:et:sw=4 diff --git a/modules/buildsystem/templates/youri/submit-upload.conf b/modules/buildsystem/templates/youri/submit-upload.conf deleted file mode 100644 index 879296cb..00000000 --- a/modules/buildsystem/templates/youri/submit-upload.conf +++ /dev/null @@ -1,403 +0,0 @@ -<% -Puppet::Parser::Functions.autoloader.loadall -escaped_domain = domain.gsub('.','\.') -%> - -home: <%= sched_home_dir %> - -# repository declaration -repository: - class: Youri::Repository::Mageia - options: - install_root: <%= repository_root %>/distrib - upload_root: ${home}/uploads/ - archive_root: <%= packages_archivedir %> - upload_state: queue - queue: queue - noarch: i586 - svn: svn+ssh://svn.<%= domain %>/svn/packages/cauldron/ - 2: - arch: i586 x86_64 - 1: - arch: i586 x86_64 - infra_1: - arch: i586 x86_64 - infra_2: - arch: i586 x86_64 - cauldron: - arch: i586 x86_64 - -# targets definition -targets: - cauldron: - checks: - - version - - tag - - acl - - rpmlint - - recency - actions: - - markrelease - - sign - - install - - link - - unpack_release_notes - - unpack_gfxboot_theme - - unpack_meta_task - - unpack_installer_images - - unpack_installer_images_nonfree - - unpack_installer_stage2 - - unpack_installer_advertising - - unpack_installer_rescue - - unpack_syslinux -# - dkms_module_info - - archive - - mail - - maintdb - posts: - - genhdlist2 - - clean_rpmsrate - - mirror - - 1: - checks: - - version - - tag - - acl - - rpmlint - - recency - actions: -# - markrelease - - sign - - install - - link -# - unpack_release_notes -# - unpack_gfxboot_theme -# - unpack_meta_task -# - unpack_installer_images -# - unpack_installer_stage2 -# - unpack_installer_advertising -# - unpack_installer_rescue -# - dkms_module_info - - archive - - mail -# - maintdb - posts: - - genhdlist2 - - clean_rpmsrate - - mirror - - 2: - checks: - - version - - tag - - acl - - rpmlint - - recency - actions: -# - markrelease - - sign - - install - - link -# - unpack_release_notes -# - unpack_gfxboot_theme -# - unpack_meta_task -# - unpack_installer_images -# - unpack_installer_stage2 -# - unpack_installer_advertising -# - unpack_installer_rescue -# - dkms_module_info - - archive - - mail -# - maintdb - posts: - - genhdlist2 - - clean_rpmsrate - - mirror - - infra_1: - checks: - - version - - tag - - acl - - rpmlint - - recency - actions: - - sign - - install - - link - - archive - posts: - - genhdlist2 - - infra_2: - checks: - - version - - tag - - acl - - rpmlint - - recency - actions: - - sign - - install - - link - - archive - posts: - - genhdlist2 - -# checks definition -checks: - tag: - class: Youri::Submit::Check::Tag - options: - tags: - release: 'mga\d+' - # packager: '<\S+@<%= escaped_domain %>>$' - distribution: '^Mageia' - vendor: '^Mageia.Org$' - - recency: - class: Youri::Submit::Check::Recency - - queue_recency: - class: Youri::Submit::Check::Queue_recency - - host: - class: Youri::Submit::Check::Host - options: - host_file: /etc/youri/host.conf - - section: - class: Youri::Submit::Check::Section - - rpmlint: - class: Youri::Submit::Check::Rpmlint - options: - results: - - buildprereq-use - - no-description-tag - - no-summary-tag - - non-standard-group - - non-xdg-migrated-menu - # it breaks dbus - #- patch-not-applied - - percent-in-conflicts - - percent-in-dependency - - percent-in-obsoletes - - percent-in-provides - - summary-ended-with-dot - - unexpanded-macro - - unknown-lsb-keyword - - malformed-line-in-lsb-comment-block - - empty-%postun - - empty-%post - - invalid-desktopfile - - standard-dir-owned-by-package - - use-tmp-in-%postun - - bogus-variable-use-in-%posttrans - - dir-or-file-in-usr-local - - dir-or-file-in-tmp - - dir-or-file-in-mnt - - dir-or-file-in-opt - - dir-or-file-in-home - - dir-or-file-in-var-local - cauldron: - config: /usr/share/rpmlint/config - path: /usr/bin/rpmlint - 1: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - 2: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - infra_1: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - infra_2: - config: /usr/share/rpmlint/config.mga2 - path: /usr/bin/mga2-rpmlint - svn: - class: Youri::Submit::Check::SVN - - acl: - class: Youri::Submit::Check::ACL - options: - acl_file: /etc/youri/acl.conf - - history: - class: Youri::Submit::Check::History - - source: - class: Youri::Submit::Check::Source - - precedence: - class: Youri::Submit::Check::Precedence - options: - target: cauldron - - version: - class: Youri::Submit::Check::Version - options: - 2: - authorized_packages: none_package_authorized - authorized_sections: ^(debug/)?(core|nonfree|tainted)/(updates_testing|backports_testing)$ - authorized_arches: none - mode: freeze - - 1: - authorized_packages: none_package_authorized - # authorized_sections: ^(debug/)?(core|nonfree|tainted)/(updates_testing|backports_testing)$ - authorized_arches: none - mode: freeze - - infra_1: - authorized_users: ^<%= scope.function_group_members(['mga-sysadmin']).join('|') %>$ - mode: freeze - - infra_2: - authorized_users: ^<%= scope.function_group_members(['mga-sysadmin']).join('|') %>$ - mode: freeze - - cauldron: -# <mrl> Prior freeze - mode: normal -## <blino> Version freeze -# authorized_packages: ^$ -# authorized_sections: ^(debug/)?(core|nonfree|tainted)/updates_testing$ -# authorized_arches: ^$ -# authorized_users: ^blino|ennael|nvigier$ -# mode: version_freeze -# <mrl> Freeze config -# authorized_packages: ^mdkonline|drakxtools|urpmi|ia_ora-gnome|ldetect|ldetect-lst|rpm-mageia-setup|perl-MDK-Common$ -# authorized_packages: none_package_authorized -# authorized_sections: ^restricted/release|main/updates_testing|contrib/updates_testing$ -# authorized_arches: none -# authorized_users: ^blino|ennael|nvigier$ -# mode: freeze - -# actions definitions -actions: - install: - class: Youri::Submit::Action::Install - - markrelease: - class: Youri::Submit::Action::Markrelease - - link: - class: Youri::Submit::Action::Link - - archive: - class: Youri::Submit::Action::Archive - - clean: - class: Youri::Submit::Action::Clean - - sign: - class: Youri::Submit::Action::Sign - options: - signuser: <%= scope.lookupvar('buildsystem::signbot::login') %> - path: <%= scope.lookupvar('buildsystem::signbot::sign_keydir') %> - name: <%= scope.lookupvar('buildsystem::signbot::keyid') %> - signscript: /usr/local/bin/sign-check-package - - unpack_gfxboot_theme: - class: Youri::Submit::Action::Unpack - options: - name: mageia-gfxboot-theme - source_subdir: /usr/share/gfxboot/themes/Mageia/install/ - dest_directory: isolinux - unpack_inside_distribution_root: 1 - - unpack_meta_task: - class: Youri::Submit::Action::Unpack - options: - name: meta-task - source_subdir: /usr/share/meta-task - dest_directory: media/media_info - unpack_inside_distribution_root: 1 - - unpack_installer_images: - class: Youri::Submit::Action::Unpack - options: - name: drakx-installer-images - source_subdir: /usr/lib*/drakx-installer-images - dest_directory: . - preclean_directory: install/images/alternatives - unpack_inside_distribution_root: 1 - - unpack_installer_images_nonfree: - class: Youri::Submit::Action::Unpack - options: - name: drakx-installer-images-nonfree - source_subdir: /usr/lib*/drakx-installer-images - dest_directory: . - unpack_inside_distribution_root: 1 - - unpack_installer_stage2: - class: Youri::Submit::Action::Unpack - options: - name: drakx-installer-stage2 - source_subdir: /usr/lib*/drakx-installer-stage2 - dest_directory: . - unpack_inside_distribution_root: 1 - - unpack_installer_advertising: - class: Youri::Submit::Action::Unpack - options: - name: drakx-installer-advertising - source_subdir: /usr/share/drakx-installer-advertising - dest_directory: . - unpack_inside_distribution_root: 1 - - unpack_installer_rescue: - class: Youri::Submit::Action::Unpack - options: - name: drakx-installer-rescue - source_subdir: /usr/lib*/drakx-installer-rescue - dest_directory: install/stage2 - unpack_inside_distribution_root: 1 - - unpack_release_notes: - class: Youri::Submit::Action::Unpack - options: - name: mageia-release-common - source_subdir: /usr/share/doc/mageia-release-common - grep_files: release-notes.* - dest_directory: . - unpack_inside_distribution_root: 1 - - unpack_syslinux: - class: Youri::Submit::Action::Unpack - options: - name: syslinux - source_subdir: /usr/lib/syslinux/ - grep_files: hdt.c32 - dest_directory: isolinux - unpack_inside_distribution_root: 1 - - mail: - class: Youri::Submit::Action::Mail - options: - mta: /usr/sbin/sendmail - to: changelog@ml.<%= domain %> - reply_to: mageia-dev@<%= domain %> - from: buildsystem-daemon@<%= domain %> - prefix: RPM - - maintdb: - class: Youri::Submit::Action::UpdateMaintDb - options: - -posts: - genhdlist2: - class: Youri::Submit::Post::Genhdlist2 - options: - command: /usr/bin/genhdlist2 - clean_rpmsrate: - class: Youri::Submit::Post::CleanRpmsrate - mirror: - class: Youri::Submit::Post::Mirror - options: - destination: /distrib/mirror/distrib - -# vim:ft=yaml:et:sw=4 diff --git a/modules/buildsystem/templates/youri/submit.conf b/modules/buildsystem/templates/youri/submit.conf new file mode 100644 index 00000000..0d7cf927 --- /dev/null +++ b/modules/buildsystem/templates/youri/submit.conf @@ -0,0 +1,140 @@ +<% +Puppet::Parser::Functions.autoloader.loadall +sched_home_dir = scope.lookupvar('buildsystem::var::scheduler::homedir') + +conf = scope.lookupvar('buildsystem::var::youri::youri_conf') +conf_default = scope.lookupvar('buildsystem::var::youri::youri_conf_default') +distros = scope.lookupvar('buildsystem::var::distros::distros') + +def line(text, indent) + res = '' + i = 0 + while i < indent + res += ' ' + i += 1 + end + res += text + "\n" +end + +def array_text(array, indent) + res = '' + array.each{|a| + res += line('- ' + a, indent) + } + return res +end + +def hash_text(hash, indent) + res = '' + curindent = indent + hash.keys.sort.each{|key| + if hash[key].instance_of? Hash + res += line(key + ':', indent) + res += hash_text(hash[key], indent + 4) + elsif hash[key].instance_of? Array + res += line(key + ':', indent) + res += array_text(hash[key], indent + 4) + elsif hash[key].instance_of? String + res += line(key + ': ' + hash[key], indent) + end + } + return res +end + +def class_hash(conf, conf_default) + res = {} + res['class'] = get_conf(conf, ['class']) == nil ? + conf_default['class'] : conf['class'] + res['options'] = get_conf(conf_default, ['options']) == nil ? {} : + conf_default['options'].dup + if get_conf(conf, ['options']) != nil + res['options'].merge!(conf['options']) + end + return res +end + +def get_conf(conf, path) + res = conf + path.each{|p| + if res == nil + return nil + end + res = res[p] + } + return res +end + +def get_distros_conf(distros, conf_name, path) + res = {} + distros.keys.each{|distro| + t = get_conf(distros[distro], [ 'youri', conf_name ] + path) + if t != nil + res[distro] = t.dup + end + } + return res +end + +def get_definitions(def_name, conf_name, conf, conf_default, distros) + res = {} + res[def_name] = {} + def_list = conf_default[conf_name][def_name].keys + def_list += get_conf(conf, [ conf_name, def_name ]) != nil ? \ + conf[conf_name][def_name].keys : [] + def_list.uniq.each{|d| + res[def_name][d] = class_hash( + get_conf(conf, [ conf_name, def_name, d ]), + get_conf(conf_default, [ conf_name, def_name, d ]) + ) + res[def_name][d]['options'].merge!(get_distros_conf(distros, + conf_name, [ def_name, d ])) + } + return res +end + +%> +home: <%= sched_home_dir %> + +<%- + repository = { + 'repository' => class_hash(get_conf(conf[conf_name], + ['repository']), + conf_default[conf_name]['repository']), + } + distros.keys.each{|distro| + repository['repository']['options'][distro] = { + 'arch' => distros[distro]['arch'].join(' '), + } + } +-%> +# repository declaration +<%= hash_text(repository, 0) %> + +<%- + targets = { + 'targets' => get_distros_conf(distros, conf_name, [ 'targets' ]), + } +-%> +# targets definition +<%= hash_text(targets, 0) %> + +<%- + checks = get_definitions('checks', conf_name, conf, conf_default, distros) +-%> +# checks definition +<%= hash_text(checks, 0) -%> + +<%- + actions = get_definitions('actions', conf_name, conf, conf_default, distros) +-%> +# actions definitions +<%= hash_text(actions, 0) -%> + +<%- + posts = get_definitions('posts', conf_name, conf, conf_default, distros) +-%> + +# posts definitions +<%= hash_text(posts, 0) -%> + +# vim:ft=yaml:et:sw=4 diff --git a/modules/catdap/manifests/init.pp b/modules/catdap/manifests/init.pp index 9cb4d22f..f7172208 100644 --- a/modules/catdap/manifests/init.pp +++ b/modules/catdap/manifests/init.pp @@ -1,6 +1,6 @@ class catdap { - $upstream_svn = 'svn://svn.mageia.org/svn/soft/identity/CatDap/' + $upstream_git = "git://git.${::domain}/web/identity" # TODO switch to a proper rpm packaging $rpm_requirement = ['perl-Catalyst-Runtime', @@ -16,7 +16,6 @@ class catdap { 'perl-Catalyst-Plugin-Session-Store-File', 'perl-Catalyst-Plugin-Static-Simple', 'perl-Catalyst-P-S-State-Cookie', - 'perl-Catalyst-P-S-Store-File', 'perl-Catalyst-View-Email', 'perl-Catalyst-View-TT', 'perl-Config-General', @@ -29,20 +28,20 @@ class catdap { 'perl-Crypt-Blowfish', 'perl-Email-Date-Format', 'perl-YAML-LibYAML', - 'perl-Catalyst-Plugin-Unicode-Encoding', 'perl-IO-Socket-INET6' ] package { $rpm_requirement: } $ldap_password = extlookup('catdap_ldap','x') - catdap::snapshot { "identity.$::domain": + catdap::snapshot { "identity.${::domain}": location => '/var/www/identity', - svn_location => "$upstream_svn/branches/live" + git_location => $upstream_git, + git_branch => 'topic/production', } - catdap::snapshot { "identity-trunk.$::domain": + catdap::snapshot { "identity-trunk.${::domain}": location => '/var/www/identity-trunk', - svn_location => "$upstream_svn/trunk" + git_location => $upstream_git, } } diff --git a/modules/catdap/manifests/snapshot.pp b/modules/catdap/manifests/snapshot.pp index 95adefe2..35ca692e 100644 --- a/modules/catdap/manifests/snapshot.pp +++ b/modules/catdap/manifests/snapshot.pp @@ -1,17 +1,18 @@ -define catdap::snapshot($location, $svn_location) { - file { "$location/catdap_local.yml": +define catdap::snapshot($location, $git_location, $git_branch = 'master') { + file { "${location}/catdap_local.yml": group => apache, mode => '0640', content => template('catdap/catdap_local.yml'), - require => Subversion::Snapshot[$location], + require => Git::Snapshot[$location], } - subversion::snapshot { $location: - source => $svn_location + git::snapshot { $location: + source => $git_location, + branch => $git_branch, } apache::vhost::catalyst_app { $name: - script => "$location/script/catdap_fastcgi.pl", + script => "${location}/script/catdap_fastcgi.pl", location => $location, use_ssl => true, } diff --git a/modules/catdap/templates/catdap_local.yml b/modules/catdap/templates/catdap_local.yml index 48dbc99a..d982b40b 100644 --- a/modules/catdap/templates/catdap_local.yml +++ b/modules/catdap/templates/catdap_local.yml @@ -6,15 +6,15 @@ ldap_account = "cn=catdap-#{hostname},ou=System Accounts,#{dc_suffix}" organisation: Mageia apptitle: Mageia Identity Management -emailfrom: noreply@<%= domain %> +emailfrom: noreply@<%= @domain %> Model::Proxy: - base: ou=People,<%= dc_suffix %> + base: ou=People,<%= @dc_suffix %> dn: <%= ldap_account %> - password: <%= ldap_password %> + password: <%= scope.lookupvar("catdap::ldap_password") %> Model::User: - base: <%= dc_suffix %> + base: <%= @dc_suffix %> host: <%= ldap_server %> start_tls: 1 @@ -25,29 +25,98 @@ authentication: store: ldap_server: <%= ldap_server %> binddn: <%= ldap_account %> - bindpw: <%= ldap_password %> - user_basedn: ou=People,<%= dc_suffix %> - role_basedn: <%= dc_suffix %> + bindpw: <%= scope.lookupvar("catdap::ldap_password") %> + user_basedn: ou=People,<%= @dc_suffix %> + role_basedn: <%= @dc_suffix %> register: - login_regex: ^[a-z][a-z0-9-]*$ + login_regex: ^[a-z][a-z0-9]*$ login_blacklist: + - abuse - apache - - mirror - bcd - - iurt - - schedbot - - signbot - - postmaster - hostmaster - - abuse - - noc - - security + - iurt - listmaster - MAILER-DAEMON - - webmaster - - www - - treasurer + - mirror + - noc + - postmaster - president + - schedbot - secretary - security + - signbot + - treasurer + - webmaster + - www + + email_domain_blacklist: + - armyspy.com + - bitmessage.ch + - codehot.co.uk + - crazymailing.com + - dayrep.com + - group.mageia.org + - grr.la + - guerrillamail.biz + - guerrillamail.com + - guerrillamail.de + - guerrillamail.info + - guerrillamail.net + - guerrillamail.org + - guerrillamailblock.com + - jourrapide.com + - ml.mageia.org + - namecheap.com + - pokemail.net + - rhyta.com + - runbox.com + - sharklasers.com + - spam4.me + - vmani.com + - wowring.ru + - yopmail.com + - zasod.com + +Controller::User: + editable_attrs: + - cn + - sn + - givenName + - mobile + - mailForwardingAddress + - preferredLanguage + uneditable_attrs: + - uid + - uidNumber + - gidNumber + - homeDirectory + - mail + - sshPublicKey + - loginShell + skip_attrs: + - objectClass + - krb5Key + - sambaMungedDial + - sambaPasswordHistory + - userPassword + - sambaLMPassword + - sambaNTPassword + - sambaPwdMustChange + - sambaSID + - sambaPrimaryGroupSID + - sambaAcctFlags + - sambaPwdCanChange + - sambaPwdLastSet + - sambaKickOffTime + - sambaUserWorkstations + - sambaLogonTime + - krb5KeyVersionNumber + - krb5PasswordEnd + - krb5MaxLife + - krb5MaxRenew + - krb5KDCFlags + - shadowLastChange + - roomNumber + - secretary diff --git a/modules/cgit/manifests/init.pp b/modules/cgit/manifests/init.pp new file mode 100644 index 00000000..60dc9bad --- /dev/null +++ b/modules/cgit/manifests/init.pp @@ -0,0 +1,27 @@ +class cgit { + package { 'cgit': } + + file { '/etc/cgitrc': + content => template('cgit/cgitrc'), + notify => Service['apache'], + require => Package['cgit'], + } + + apache::webapp_other { 'cgit': + webapp_file => 'cgit/webapp.conf', + } + + mga_common::local_script { 'cgit.filter.commit-links.sh': + content => template('cgit/filter.commit-links.sh'), + } + + apache::vhost::base { "gitweb.${::domain}": + content => template('cgit/vhost.conf') + } + + apache::vhost::base { "ssl_gitweb.${::domain}": + use_ssl => true, + vhost => "gitweb.${::domain}", + content => template('cgit/vhost.conf') + } +} diff --git a/modules/cgit/templates/cgitrc b/modules/cgit/templates/cgitrc new file mode 100644 index 00000000..1e1a399c --- /dev/null +++ b/modules/cgit/templates/cgitrc @@ -0,0 +1,137 @@ +# +# See cgitrc(5) or /usr/share/doc/cgit-*/cgitrc.5.html for details +# + +# Enable caching of up to 1000 output entries +cache-size=1000 + + +# Specify some default clone urls using macro expansion +clone-url=git://git.mageia.org/$CGIT_REPO_URL ssh://git@git.mageia.org/$CGIT_REPO_URL + +# Specify the css url +css=/cgit-data/cgit.css + + +# Show owner on index page +enable-index-owner=1 + + +# Allow http transport git clone +enable-git-clone=1 + + +# Show extra links for each repository on the index page +enable-index-links=1 + + +# Enable ASCII art commit history graph on the log pages +enable-commit-graph=1 + + +# Show number of affected files per commit on the log pages +enable-log-filecount=1 + + +# Show number of added/removed lines per commit on the log pages +enable-log-linecount=1 + + +# Sort branches by date +branch-sort=age + + +# Add a cgit favicon +#favicon=/favicon.ico + + +# Use a custom logo +logo=//nav.mageia.org/css/mageia-logo-nav-3.png + +# Try to avoid pagination on the mail page (until we have too many software repos) +max-repo-count=200 + +# Enable statistics per week, month and quarter +max-stats=quarter + + +# Set the title and heading of the repository index page +root-title=Mageia git Repositories + + +# Set a subheading for the repository index page +root-desc=A web frontend to the git repositories of the Mageia project + + +# Include some more info about example.com on the index page +#root-readme=/var/www/htdocs/about.html + + +# Allow download of tar.gz, tar.bz2 and zip-files +#snapshots=tar.gz tar.bz2 zip +snapshots=all + + +## +## List of common mimetypes +## + +mimetype.gif=image/gif +mimetype.html=text/html +mimetype.jpg=image/jpeg +mimetype.jpeg=image/jpeg +mimetype.pdf=application/pdf +mimetype.png=image/png +mimetype.svg=image/svg+xml + + +# Highlight source code with python pygments-based highlighter +source-filter=/usr/libexec/cgit/filters/syntax-highlighting.sh + +# Format markdown, restructuredtext, manpages, text files, and html files +# through the right converters +about-filter=/usr/libexec/cgit/filters/about-formatting.sh + +## +## Search for these files in the root of the default branch of repositories +## for coming up with the about page: +## +readme=:README.mga.md +readme=:README.md +readme=:README.rst +readme=:README.html +readme=:README.txt +readme=:README +readme=:INSTALL.md +readme=:INSTALL.rst +readme=:INSTALL.html +readme=:INSTALL.txt +readme=:INSTALL + +# Special Case mainly for initscripts git repo where we cannot write to master +readme=distro/mga:README.md + +## +## List of repositories. +## PS: Any repositories listed when section is unset will not be +## displayed under a section heading +## PPS: This list could be kept in a different file (e.g. '/etc/cgitrepos') +## and included like this: +## include=/etc/cgitrepos +## + +#repo.url=foo +#repo.path=/var/lib/git/foo.git +#repo.desc=the master foo repository +#repo.owner=fooman@example.com +#repo.readme=info/web/about.html + + +commit-filter=/usr/local/bin/cgit.filter.commit-links.sh + +enable-git-config=1 +section-from-path=-1 +case-sensitive-sort=0 +remove-suffix=1 +scan-path=/git +enable-http-clone=0 diff --git a/modules/cgit/templates/filter.commit-links.sh b/modules/cgit/templates/filter.commit-links.sh new file mode 100755 index 00000000..f0f7ee14 --- /dev/null +++ b/modules/cgit/templates/filter.commit-links.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# This script can be used to generate links in commit messages. +# +# To use this script, refer to this file with either the commit-filter or the +# repo.commit-filter options in cgitrc. +# +# The following environment variables can be used to retrieve the configuration +# of the repository for which this script is called: +# CGIT_REPO_URL ( = repo.url setting ) +# CGIT_REPO_NAME ( = repo.name setting ) +# CGIT_REPO_PATH ( = repo.path setting ) +# CGIT_REPO_OWNER ( = repo.owner setting ) +# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting ) +# CGIT_REPO_SECTION ( = section setting ) +# CGIT_REPO_CLONE_URL ( = repo.clone-url setting ) +# + +regex='' + +# This expression generates links to commits referenced by their SHA1. +regex=$regex' +s|\b([0-9a-fA-F]{7,40})\b|<a href="./?id=\1">\1</a>|g' + +# This expression generates links various common bugtrackers. +# When editing this list, remember to edit the same list in +# deployment/mgagit/templates/git-post-receive-hook +regex=$regex' +s|mga#([0-9]+)\b|<a href="https://bugs.mageia.org/\1">mga#\1</a>|g' +regex=$regex' +s|rhbz#([0-9]+)\b|<a href="https://bugzilla.redhat.com/show_bug.cgi?id=\1">rhbz#\1</a>|g' +regex=$regex' +s|fdo#([0-9]+)\b|<a href="https://bugs.freedesktop.org/show_bug.cgi?id=\1">fdo#\1</a>|g' +regex=$regex' +s|bko#([0-9]+)\b|<a href="https://bugs.kde.org/show_bug.cgi?id=\1">bko#\1</a>|g' +regex=$regex' +s|kde#([0-9]+)\b|<a href="https://bugs.kde.org/show_bug.cgi?id=\1">kde#\1</a>|g' +regex=$regex' +s|bgo#([0-9]+)\b|<a href="https://bugzilla.gnome.org/show_bug.cgi?id=\1">bgo#\1</a>|g' +regex=$regex' +s|gnome#([0-9]+)\b|<a href="https://bugzilla.gnome.org/show_bug.cgi?id=\1">gnome#\1</a>|g' +regex=$regex' +s|lp#([0-9]+)\b|<a href="https://launchpad.net/bugs/\1">lp#\1</a>|g' + +sed -re "$regex" diff --git a/modules/cgit/templates/vhost.conf b/modules/cgit/templates/vhost.conf new file mode 100644 index 00000000..5c1d99e7 --- /dev/null +++ b/modules/cgit/templates/vhost.conf @@ -0,0 +1,8 @@ +Alias /cgit-data /usr/share/cgit +Alias /robots.txt /usr/share/cgit/robots.txt +ScriptAliasMatch ^(.*) /var/www/cgi-bin/cgit$1 + +<Directory /usr/share/cgit> + Order allow,deny + Allow from all +</Directory> diff --git a/modules/cgit/templates/webapp.conf b/modules/cgit/templates/webapp.conf new file mode 100644 index 00000000..4e1d8289 --- /dev/null +++ b/modules/cgit/templates/webapp.conf @@ -0,0 +1,3 @@ +# Disable standard cgit configuration +#Alias /cgit-data /usr/share/cgit +#ScriptAlias /cgit /var/www/cgi-bin/cgit diff --git a/modules/dashboard/manifests/init.pp b/modules/dashboard/manifests/init.pp index ff804010..34ef41b3 100644 --- a/modules/dashboard/manifests/init.pp +++ b/modules/dashboard/manifests/init.pp @@ -1,17 +1,17 @@ class dashboard { $dashboard_login = 'dashboard' - $dashboard_home_dir = "/var/lib/$dashboard_login" - $dashboard_dir = "$dashboard_home_dir/dashboard" - $dashboard_bindir = "$dashboard_home_dir/bin" - $dashboard_wwwdir = "/var/www/vhosts/dashboard.$::domain" + $dashboard_home_dir = "/var/lib/${dashboard_login}" + $dashboard_dir = "${dashboard_home_dir}/dashboard" + $dashboard_bindir = "${dashboard_home_dir}/bin" + $dashboard_wwwdir = "/var/www/vhosts/dashboard.${::domain}" user { $dashboard_login: comment => 'dashboard system user', home => $dashboard_home_dir, } - subversion::snapshot { $dashboard_dir: - source => "svn://svn.$::domain/soft/dashboard/", + git::snapshot { $dashboard_dir: + source => "git://git.${::domain}/web/generators/dashboard", } package { 'php-cli': } @@ -26,17 +26,17 @@ class dashboard { ensure => directory, } - file { "$dashboard_bindir/make_report": + file { "${dashboard_bindir}/make_report": mode => '0755', content => template('dashboard/make_report'), } - apache::vhost::base { "dashboard.$::domain": + apache::vhost::base { "dashboard.${::domain}": location => $dashboard_wwwdir, } cron { 'update dashboard': - command => "$dashboard_bindir/make_report", + command => "${dashboard_bindir}/make_report", user => $dashboard_login, hour => '*/2', minute => '15', diff --git a/modules/dashboard/templates/make_report b/modules/dashboard/templates/make_report index 25c2f316..5da59617 100644 --- a/modules/dashboard/templates/make_report +++ b/modules/dashboard/templates/make_report @@ -1,7 +1,7 @@ #!/bin/sh -dashboard_dir='<%= dashboard_dir %>' -dashboard_wwwdir='<%= dashboard_wwwdir %>' +dashboard_dir='<%= @dashboard_dir %>' +dashboard_wwwdir='<%= @dashboard_wwwdir %>' cd "$dashboard_dir" /usr/bin/php ./make_report.php > "$dashboard_wwwdir/index.html" diff --git a/modules/django_application/files/custom_backend.py b/modules/django_application/files/custom_backend.py index 828744fb..5ab35385 100644 --- a/modules/django_application/files/custom_backend.py +++ b/modules/django_application/files/custom_backend.py @@ -1,9 +1,7 @@ -from django_auth_ldap.backend import LDAPBackend,_LDAPUser +from django_auth_ldap.backend import LDAPBackend,_LDAPUser class ForceUidLDAPBackend(LDAPBackend): def ldap_to_django_username(self, username): # force uid if someone give a email return _LDAPUser(self, username=username).attrs['uid'][0] - - diff --git a/modules/django_application/files/django_add_permission_to_group.py b/modules/django_application/files/django_add_permission_to_group.py index 4fa77e8d..69ac7be5 100644 --- a/modules/django_application/files/django_add_permission_to_group.py +++ b/modules/django_application/files/django_add_permission_to_group.py @@ -16,12 +16,12 @@ if app: permissions = permissions.filter(content_type__app_label__exact=app) if len(permissions) > 1: - print "Error, result not unique, please give the application among :" - print ' '.join([p.content_type.app_label for p in permissions]) - sys.exit(1) + print "Error, result not unique, please give the application among :" + print ' '.join([p.content_type.app_label for p in permissions]) + sys.exit(1) elif len(permissions) < 1: - print "Error, wrong codename" - sys.exit(1) + print "Error, wrong codename" + sys.exit(1) group.permissions.add(permissions[0]) group.save() diff --git a/modules/django_application/files/django_create_group.py b/modules/django_application/files/django_create_group.py index 69079f66..b5052217 100644 --- a/modules/django_application/files/django_create_group.py +++ b/modules/django_application/files/django_create_group.py @@ -8,5 +8,3 @@ try: except Group.DoesNotExist: group = Group.objects.create(name=group_name) group.save() - - diff --git a/modules/django_application/manifests/add_permission_to_group.pp b/modules/django_application/manifests/add_permission_to_group.pp index 037ec882..6e0663ed 100644 --- a/modules/django_application/manifests/add_permission_to_group.pp +++ b/modules/django_application/manifests/add_permission_to_group.pp @@ -2,11 +2,10 @@ define django_application::add_permission_to_group( $path, $module, $group, $app='') { - exec { "/usr/local/bin/django_add_permission_to_group.py $group $name $app": + exec { "/usr/local/bin/django_add_permission_to_group.py ${group} ${name} ${app}": user => 'root', - environment => ["DJANGO_SETTINGS_MODULE=$module.settings", - "PYTHONPATH=$path" ], + environment => ["DJANGO_SETTINGS_MODULE=${module}.settings", + "PYTHONPATH=${path}" ], require => Django_application::Script['django_add_permission_to_group.py'] } } - diff --git a/modules/django_application/manifests/create_group.pp b/modules/django_application/manifests/create_group.pp index 26a9a811..1931205f 100644 --- a/modules/django_application/manifests/create_group.pp +++ b/modules/django_application/manifests/create_group.pp @@ -1,8 +1,8 @@ define django_application::create_group($path, $module) { - exec { "/usr/local/bin/django_create_group.py $name": + exec { "/usr/local/bin/django_create_group.py ${name}": user => 'root', - environment => ["DJANGO_SETTINGS_MODULE=$module.settings", - "PYTHONPATH=$path" ], + environment => ["DJANGO_SETTINGS_MODULE=${module}.settings", + "PYTHONPATH=${path}" ], require => Django_application::Script['django_create_group.py'] } } diff --git a/modules/django_application/manifests/init.pp b/modules/django_application/manifests/init.pp index 2f209a54..f56f73ef 100644 --- a/modules/django_application/manifests/init.pp +++ b/modules/django_application/manifests/init.pp @@ -1,5 +1,5 @@ # this class hold the common stuff for all django applications -# as we cannot declare the same ressource twice ( ie, +# as we cannot declare the same resource twice ( ie, # python-psycopg2 for example ) # it is required to place this in a common class class django_application { diff --git a/modules/django_application/manifests/script.pp b/modules/django_application/manifests/script.pp index 96179c96..f414d864 100644 --- a/modules/django_application/manifests/script.pp +++ b/modules/django_application/manifests/script.pp @@ -1,8 +1,8 @@ define django_application::script() { file { $name: - path => "/usr/local/bin/$name", + path => "/usr/local/bin/${name}", mode => '0755', - source => "puppet:///modules/django_application/$name", + source => "puppet:///modules/django_application/${name}", } } diff --git a/modules/draklive/manifests/init.pp b/modules/draklive/manifests/init.pp index 38d44529..ade2527f 100644 --- a/modules/draklive/manifests/init.pp +++ b/modules/draklive/manifests/init.pp @@ -1,44 +1,45 @@ class draklive { $login = 'draklive' $home = '/home/draklive' - $config = "$home/live-config" - $var_data = "$home/var-data" + $config = "${home}/live-config" + $var_data = "${home}/var-data" # TODO merge with bcd - $isomakers_group = 'mga-iso_makers' + $isomakers_group = 'mga-iso_makers' - include sudo + include sudo group { $login: } - + user { $login: home => $home, comment => 'User for creating live ISOs', } - package { 'draklive': } + package { 'drakiso': } sudo::sudoers_config { 'draklive': content => template('draklive/sudoers.draklive') } - file { $var_data: - ensure => directory, - owner => $login, - group => $login, - mode => '0755', - } - - file { '/var/lib/draklive': - ensure => symlink, - target => $var_data, - } - - subversion::snapshot { $config: - source => "svn://svn.$::domain/soft/images-config/draklive/trunk/", + file { $var_data: + ensure => directory, + owner => $login, + group => $login, + mode => '0755', + } + + file { '/var/lib/draklive': + ensure => symlink, + target => $var_data, + } + + git::snapshot { $config: + source => "git://git.${::domain}/software/build-system/draklive-config", + user => $login, } cron { 'build live images': - command => "$config/tools/build_live.sh", + command => "${config}/tools/build_live.sh", user => $login, hour => '4', minute => '30', @@ -48,7 +49,7 @@ class draklive { mode => '0755', source => 'puppet:///modules/draklive/clean-live.sh', } - + cron { 'clean live build data': command => '/usr/local/bin/clean-live.sh', hour => '4', diff --git a/modules/draklive/templates/sudoers.draklive b/modules/draklive/templates/sudoers.draklive index 208d6967..536e4e9f 100644 --- a/modules/draklive/templates/sudoers.draklive +++ b/modules/draklive/templates/sudoers.draklive @@ -1,2 +1,3 @@ -<%= login %> ALL=(root) NOPASSWD: /usr/sbin/draklive -%<%= isomakers_group %> ALL=(<%= login %>) SETENV: NOPASSWD: ALL +<%= @login %> ALL=(root) NOPASSWD: /usr/sbin/draklive +<%= @login %> ALL=(root) NOPASSWD: /usr/bin/draklive2 +%<%= isomakers_group %> ALL=(<%= @login %>) SETENV: NOPASSWD: ALL diff --git a/modules/epoll/manifests/create_db.pp b/modules/epoll/manifests/create_db.pp new file mode 100644 index 00000000..8ef9c0aa --- /dev/null +++ b/modules/epoll/manifests/create_db.pp @@ -0,0 +1,7 @@ +class epoll::create_db () { + postgresql::remote_db_and_user { $epoll::var::db_name: + description => 'Epoll database', + password => $epoll::var::db_password, + } +} +# vim: sw=2 diff --git a/modules/epoll/manifests/init.pp b/modules/epoll/manifests/init.pp index f00d2a3e..fb86f23a 100644 --- a/modules/epoll/manifests/init.pp +++ b/modules/epoll/manifests/init.pp @@ -1,23 +1,15 @@ class epoll { - - $vhost = "epoll.$::domain" + include epoll::var package { 'Epoll': } - apache::vhost::catalyst_app { $vhost: + apache::vhost::catalyst_app { $epoll::var::vhost: script => '/usr/bin/epoll_fastcgi.pl', use_ssl => true, require => Package['Epoll'] } - apache::vhost::redirect_ssl { $vhost: } - - $pgsql_password = extlookup('epoll_pgsql','x') - - postgresql::remote_db_and_user { 'epoll': - description => 'Epoll database', - password => $pgsql_password, - } + apache::vhost::redirect_ssl { $epoll::var::vhost: } file { 'epoll.yml': path => '/etc/epoll.yml', diff --git a/modules/epoll/manifests/var.pp b/modules/epoll/manifests/var.pp new file mode 100644 index 00000000..1ddc342a --- /dev/null +++ b/modules/epoll/manifests/var.pp @@ -0,0 +1,35 @@ +# == Class: epoll::var +# +# epoll configuration +# +# === Parameters +# +# [*vhost*] +# epoll vhost +# +# [*db_hostname*] +# hostname of the database server +# +# [*db_name*] +# name of the database +# +# [*db_user*] +# user to connect to the database +# +# [*db_password*] +# password to connect to the database +# +# [*password*] +# password to create new polls +# + +class epoll::var ( + $vhost = "epoll.${::domain}", + $db_hostname = 'localhost', + $db_name = 'epoll', + $db_user = 'epoll', + $db_password, + $password +) { +} +# vim: sw=2 diff --git a/modules/epoll/templates/epoll.yml b/modules/epoll/templates/epoll.yml index 0ca519c9..d442a41e 100644 --- a/modules/epoll/templates/epoll.yml +++ b/modules/epoll/templates/epoll.yml @@ -2,10 +2,10 @@ name: Vote # db: connection, see libpq documentation # dbname=BASENAME;host=SERVER;user=USER;password=PASS -db: dbname=epoll;host=localhost;user=epoll;password=<%= pgsql_password %> +db: dbname=<%= scope.lookupvar('epoll::var::db_name') %>;host=<%= scope.lookupvar('epoll::var::db_hostname') %>;user=<%= scope.lookupvar('epoll::var::db_user') %>;password=<%= scope.lookupvar('epoll::var::db_password') %> # The smtp serveur to use, default is localhost # smtp: # This change the poll creation behavior, instead ask want confirmation by # mail # it ask for this password (in clear) -# newpollpasswd: +newpollpasswd: <%= scope.lookupvar('epoll::var::password') %> diff --git a/modules/facter/lib/facter/dc_suffix.rb b/modules/facter/lib/facter/dc_suffix.rb index a8526978..c480e3ac 100644 --- a/modules/facter/lib/facter/dc_suffix.rb +++ b/modules/facter/lib/facter/dc_suffix.rb @@ -2,9 +2,9 @@ Facter.add("dc_suffix") do setcode do begin Facter.domain - rescue + rescue Facter.loadfacts() end dc_suffix = 'dc=' + Facter.value('domain').gsub('.',',dc=') end -end +end diff --git a/modules/facter/lib/facter/lib_dir.rb b/modules/facter/lib/facter/lib_dir.rb index fe7d6a31..315d7594 100644 --- a/modules/facter/lib/facter/lib_dir.rb +++ b/modules/facter/lib/facter/lib_dir.rb @@ -2,9 +2,9 @@ Facter.add("lib_dir") do setcode do begin Facter.architecture - rescue + rescue Facter.loadfacts() end - '/usr/lib' + ( Facter.value('architecture') == "x86_64" ? '64' : '') + '/' + '/usr/lib' + ( Facter.value('architecture') == "x86_64" ? '64' : '') end -end +end diff --git a/modules/facter/lib/facter/wildcard_sslcert.rb b/modules/facter/lib/facter/wildcard_sslcert.rb index 1f7c4dd7..093982d9 100644 --- a/modules/facter/lib/facter/wildcard_sslcert.rb +++ b/modules/facter/lib/facter/wildcard_sslcert.rb @@ -1,16 +1,16 @@ Facter.add("wildcard_sslcert") do - setcode do - begin - Facter.domain - rescue - Facter.loadfacts() - end - sslfiles = '/etc/ssl/wildcard.' + Facter.value('domain') - if File.exist?(sslfiles + '.crt') and File.exist?(sslfiles + '.key') \ - and File.exist?(sslfiles + '.pem') - 'true' - else - 'false' - end - end + setcode do + begin + Facter.domain + rescue + Facter.loadfacts() + end + sslfiles = '/etc/ssl/wildcard.' + Facter.value('domain') + if File.exist?(sslfiles + '.crt') and File.exist?(sslfiles + '.key') \ + and File.exist?(sslfiles + '.pem') + 'true' + else + 'false' + end + end end diff --git a/modules/facter/spec/spec_helper.rb b/modules/facter/spec/spec_helper.rb index 81d9f79b..ec3fe615 100644 --- a/modules/facter/spec/spec_helper.rb +++ b/modules/facter/spec/spec_helper.rb @@ -32,4 +32,3 @@ RSpec.configure do |config| to_remove.each {|key| ENV.delete key } end end - diff --git a/modules/facter/spec/unit/lib_dir.rb b/modules/facter/spec/unit/lib_dir.rb index 1d5c4624..50049f19 100644 --- a/modules/facter/spec/unit/lib_dir.rb +++ b/modules/facter/spec/unit/lib_dir.rb @@ -5,14 +5,14 @@ require 'spec_helper' describe "Lib_dir fact" do it "should default to /usr/lib" do Facter.fact(:architecture).stubs(:value).returns("bogus") - Facter.fact(:lib_dir).value.should == "/usr/lib/" + Facter.fact(:lib_dir).value.should == "/usr/lib" end archs = Hash.new # TODO add arm 64 and others archs = { - "i586" => "/usr/lib/", - "x86_64" => "/usr/lib64/", + "i586" => "/usr/lib", + "x86_64" => "/usr/lib64", } archs.each do |arch, dir| it "should be #{dir} on #{arch}" do diff --git a/modules/git/files/apply_git_puppet_config.sh b/modules/git/files/apply_git_puppet_config.sh index 29ede998..1ed6fbf1 100644 --- a/modules/git/files/apply_git_puppet_config.sh +++ b/modules/git/files/apply_git_puppet_config.sh @@ -4,4 +4,4 @@ while read line do # --local is a option for the newer git git config --add $line -done < config.puppet +done < config.puppet diff --git a/modules/git/files/create_git_repo.sh b/modules/git/files/create_git_repo.sh index 1104edbe..144d063b 100644 --- a/modules/git/files/create_git_repo.sh +++ b/modules/git/files/create_git_repo.sh @@ -1,6 +1,6 @@ #!/bin/bash umask 0002 -# http://eagleas.livejournal.com/18907.html +# https://eagleas.livejournal.com/18907.html name="$1" mkdir -p $name cd $name @@ -8,4 +8,3 @@ git --bare init --shared=group chmod g+ws branches info objects refs ( cd objects; chmod g+ws * ) git config receive.denyNonFastForwards true - diff --git a/modules/git/manifests/mirror.pp b/modules/git/manifests/mirror.pp index 0e0c30cd..f7364846 100644 --- a/modules/git/manifests/mirror.pp +++ b/modules/git/manifests/mirror.pp @@ -3,18 +3,18 @@ define git::mirror( $source, $refresh = '*/5') { include git::common - exec { "/usr/bin/git clone --bare $source $name": - alias => "git mirror $name", + exec { "/usr/bin/git clone --mirror ${source} ${name}": + alias => "git mirror ${name}", creates => $name, - before => File["$name/description"], + before => File["${name}/description"], } - file { "$name/description": + file { "${name}/description": content => $description, } - cron { "update $name": - command => "cd $name ; /usr/bin/git fetch -q", + cron { "update ${name}": + command => "cd ${name} ; /usr/bin/git fetch -q", minute => $refresh } } diff --git a/modules/git/manifests/repository.pp b/modules/git/manifests/repository.pp deleted file mode 100644 index 4f4f0615..00000000 --- a/modules/git/manifests/repository.pp +++ /dev/null @@ -1,40 +0,0 @@ -define git::repository($group, - $description = '') { - - include git::server - # http://eagleas.livejournal.com/18907.html - # TODO group permission should be handled here too - exec { "/usr/local/bin/create_git_repo.sh $name": - user => 'root', - group => $group, - creates => $name, - } - - file { "$name/git-daemon-export-ok": - require => Exec["/usr/local/bin/create_git_repo.sh $name"] - } - - file { "$name/description": - content => $description, - require => File["$name/git-daemon-export-ok"] - } - - file { "$name/hooks/post-receive": - mode => '0755', - content => template('git/post-receive'), - require => File["$name/git-daemon-export-ok"] - } - - file { "$name/config.puppet": - require => File["$name/git-daemon-export-ok"], - notify => Exec["/usr/local/bin/apply_git_puppet_config.sh $name"], - content => template('git/config.puppet'), - } - - # $name is not really used, but this prevent duplicate declaration error - exec { "/usr/local/bin/apply_git_puppet_config.sh $name": - cwd => $name, - user => 'root', - refreshonly => true, - } -} diff --git a/modules/git/manifests/server.pp b/modules/git/manifests/server.pp index 155cd9ae..3f07ed9c 100644 --- a/modules/git/manifests/server.pp +++ b/modules/git/manifests/server.pp @@ -7,10 +7,6 @@ class git::server { content => template('git/xinetd') } - file { $git_base_path: - ensure => directory - } - file { '/usr/local/bin/create_git_repo.sh': mode => '0755', source => 'puppet:///modules/git/create_git_repo.sh', @@ -24,16 +20,16 @@ class git::server { # TODO # define common syntax check, see svn - # http://stackoverflow.com/questions/3719883/git-hook-syntax-check + # https://stackoverflow.com/questions/3719883/git-hook-syntax-check # proper policy : fast-forward-only - # ( http://progit.org/book/ch7-4.html ) + # ( https://progit.org/book/ch7-4.html ) # no branch ? # no binary # no big file # no empty commit message # no commit from root - # see http://www.itk.org/Wiki/Git/Hooks - # automated push to another git repo ( see http://noone.org/blog/English/Computer/VCS/Thoughts%20on%20Gitorious%20and%20GitHub%20plus%20a%20useful%20git%20hook.futile + # see https://www.itk.org/Wiki/Git/Hooks + # automated push to another git repo ( see https://noone.org/blog/English/Computer/VCS/Thoughts%20on%20Gitorious%20and%20GitHub%20plus%20a%20useful%20git%20hook.futile # # how do we handle commit permission ? # mail sending diff --git a/modules/git/manifests/snapshot.pp b/modules/git/manifests/snapshot.pp index 8b903700..06473efe 100644 --- a/modules/git/manifests/snapshot.pp +++ b/modules/git/manifests/snapshot.pp @@ -1,22 +1,24 @@ define git::snapshot( $source, $refresh = '*/5', - $user = 'root') { + $user = 'root', + $branch = 'master') { include git::client #TODO # should handle branch -> clone -n + branch + checkout # create a script - # Idealy, should be handled by vcsrepo + # Ideally, should be handled by vcsrepo # https://github.com/bruce/puppet-vcsrepo # once it is merged in puppet - exec { "/usr/bin/git clone $source $name": + exec { "/usr/bin/git clone -b ${branch} ${source} ${name}": creates => $name, user => $user } - cron { "update $name": - # FIXME no -q ? - command => "cd $name && /usr/bin/git pull", - user => $user, - minute => $refresh + if ($refresh != '0') { + cron { "update ${name}": + command => "cd ${name} && /usr/bin/git pull -q && /usr/bin/git submodule --quiet update --init --recursive", + user => $user, + minute => $refresh + } } } diff --git a/modules/git/manifests/svn_repository.pp b/modules/git/manifests/svn_repository.pp index 93ddb792..ea215ce6 100644 --- a/modules/git/manifests/svn_repository.pp +++ b/modules/git/manifests/svn_repository.pp @@ -11,8 +11,8 @@ define git::svn_repository( $source, $options = '' } - exec { "/usr/bin/git svn init $options $source $name": - alias => "git svn $name", + exec { "/usr/bin/git svn init ${options} ${source} ${name}": + alias => "git svn ${name}", creates => $name, } @@ -21,15 +21,15 @@ define git::svn_repository( $source, source => 'puppet:///modules/git/update_git_svn.sh', } - cron { "update $name": + cron { "update ${name}": # done in 2 times, so fetch can fill the repo after init - command => "/usr/local/bin/update_git_svn.sh $name" , + command => "/usr/local/bin/update_git_svn.sh ${name}" , minute => $refresh } - file { "$name/.git/hooks/pre-receive": + file { "${name}/.git/hooks/pre-receive": mode => '0755', content => template('git/pre-receive'), - require => Exec["git svn $name"] + require => Exec["git svn ${name}"] } } diff --git a/modules/git/templates/xinetd b/modules/git/templates/xinetd index 2cbf78e3..654ae2be 100644 --- a/modules/git/templates/xinetd +++ b/modules/git/templates/xinetd @@ -4,10 +4,10 @@ service git type = UNLISTED port = 9418 socket_type = stream - server = <%= lib_dir %>/git-core/git-daemon + server = <%= @lib_dir %>/git-core/git-daemon wait = no user = nobody - server_args = --inetd --verbose --export-all --base-path=<%= git_base_path %> + server_args = --inetd --verbose --export-all --base-path=<%= @git_base_path %> log_on_failure += HOST flags = IPv6 } diff --git a/modules/gitmirror/files/on-the-pull b/modules/gitmirror/files/on-the-pull new file mode 100755 index 00000000..416b75a4 --- /dev/null +++ b/modules/gitmirror/files/on-the-pull @@ -0,0 +1,365 @@ +#!/usr/bin/python3 + +import cgi +import http.server +import os +import pwd +import re +import subprocess +import sys +from optparse import OptionParser +from queue import Queue +from threading import Thread + + +GitUpdaterQueue = Queue(0) + + +# NB The following class and bits for running git commands were "liberated" +# from git_multimail.py + +class CommandError(Exception): + def __init__(self, cmd, retcode): + self.cmd = cmd + self.retcode = retcode + Exception.__init__( + self, + 'Command "%s" failed with retcode %s' % (' '.join(cmd), retcode,) + ) + + +# It is assumed in many places that the encoding is uniformly UTF-8, +# so changing these constants is unsupported. But define them here +# anyway, to make it easier to find (at least most of) the places +# where the encoding is important. +ENCODING = 'UTF-8' + + +# The "git" program (this could be changed to include a full path): +GIT_EXECUTABLE = 'git' + + +# How "git" should be invoked (including global arguments), as a list +# of words. This variable is usually initialized automatically by +# read_git_output() via choose_git_command(), but if a value is set +# here then it will be used unconditionally. +GIT_CMD = None + + +def choose_git_command(): + """Decide how to invoke git, and record the choice in GIT_CMD.""" + + global GIT_CMD + + if GIT_CMD is None: + try: + # Check to see whether the "-c" option is accepted (it was + # only added in Git 1.7.2). We don't actually use the + # output of "git --version", though if we needed more + # specific version information this would be the place to + # do it. + cmd = [GIT_EXECUTABLE, '-c', 'foo.bar=baz', '--version'] + read_output(cmd) + GIT_CMD = [GIT_EXECUTABLE, '-c', f'i18n.logoutputencoding={ENCODING}'] + except CommandError: + GIT_CMD = [GIT_EXECUTABLE] + + +def read_git_output(args, inp=None, keepends=False, **kw): + """Read the output of a Git command.""" + + if GIT_CMD is None: + choose_git_command() + + return read_output(GIT_CMD + args, inp=inp, keepends=keepends, **kw) + + +# NOTE: output is in bytes, not a string +def read_output(cmd, inp=None, keepends=False, **kw): + if inp: + stdin = subprocess.PIPE + else: + stdin = None + p = subprocess.Popen( + cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw + ) + (out, err) = p.communicate(inp) + retcode = p.wait() + if retcode: + raise CommandError(cmd, retcode) + if not keepends: + out = out.rstrip(b'\n\r') + return out + + +def run_git_command(args, **kw): + """Runs a git command, ignoring the output. + """ + + read_git_output(args, **kw) + + +def run_command(args, **kw): + """Runs a git command, ignoring the output. + """ + + read_output(args, **kw) + + +class GitUpdater(Thread): + def __init__(self, server, basedir, repoprefix, branch='master', cmd=''): + Thread.__init__(self) + self.server = server + self.basedir = basedir + self.repoprefix = repoprefix + self.branch = branch + self.cmd = cmd + + def run(self): + while 42: + repo = GitUpdaterQueue.get() + if repo is None: + break + try: + print(f"Got update request for '{repo}'", file=sys.stderr) + clonefolder = os.path.join(self.basedir, repo) + if self.repoprefix: + if not repo.startswith(self.repoprefix): + print(f"Ignoring repo '{repo}' due to invalid prefix", file=sys.stderr) + GitUpdaterQueue.task_done() + continue + clonefolder = os.path.join(self.basedir, repo[len(self.repoprefix):]) + command = [] + treeish = '' + changed = True + if not os.path.exists(clonefolder): + cloneparent = os.path.dirname(clonefolder) + if not os.path.exists(cloneparent): + os.makedirs(cloneparent) + cloneurl = self.server + '/' + repo + command = ['clone'] + if '--mirror' == self.branch: + command.append('--mirror') + command.append(cloneurl) + command.append(clonefolder) + print(f"Cloning repo '{repo}' ('{cloneurl}' -> '{clonefolder}')", file=sys.stderr) + + run_git_command(command) + if not os.path.isdir(clonefolder): + raise Exception(f"Clone folder '{clonefolder}' is not a directory. Cloning failed or file in it's place?") + os.chdir(clonefolder) + if '--mirror' != self.branch and 'master' != self.branch: + command = ['checkout', '-t', 'origin/' + self.branch] + run_git_command(command) + elif os.path.isdir(clonefolder): + os.chdir(clonefolder) + print(f"Updating existing repo '{repo}' ({clonefolder})", file=sys.stderr) + command = ['remote', 'update'] + run_git_command(command) + if '--mirror' != self.branch: + sha1before = read_git_output(['rev-parse', 'refs/heads/' + self.branch]) + sha1after = read_git_output(['rev-parse', 'refs/remotes/origin/' + self.branch]) + if sha1before and sha1after: + if sha1before == sha1after: + changed = False + print(f"Repo '{repo}' update on branch '{self.branch}': No changed detected", file=sys.stderr) + else: + treeish = sha1before.decode(ENCODING) + '..' + sha1after.decode(ENCODING) + print(f"Repo '{repo}' update on branch '{self.branch}': Treeish '{treeish}'", file=sys.stderr) + else: + print(f"Repo '{repo}' update on branch '{self.branch}': Before or after sha1 could not be extracted.", file=sys.stderr) + command = ['update-ref', 'refs/heads/' + self.branch, 'refs/remotes/origin/' + self.branch] + run_git_command(command) + command = ['checkout', '-f', self.branch] + run_git_command(command) + else: + raise Exception(f"Clone folder '{clonefolder}' appears to be a file :s") + + if changed and self.cmd: + # Update the info/web/last-modified file as used by cgit + os.chdir(clonefolder) + command = [self.cmd, repo] + if treeish: + command += [treeish] + run_command(command) + + print(f"Update for '{repo}' complete.", file=sys.stderr) + except Exception as e: + print(f"Error processing repo '{repo}'", file=sys.stderr) + print(str(e), file=sys.stderr) + + GitUpdaterQueue.task_done() + sys.stderr.flush() + + +class TimeoutServer(http.server.HTTPServer): + def get_request(self): + result = self.socket.accept() + result[0].settimeout(10) + return result + + +class PostHandler(http.server.BaseHTTPRequestHandler): + def do_POST(self): + ctype, pdict = cgi.parse_header(self.headers['content-type']) + repo = "" + try: + if ctype != 'x-git/repo': + self.send_response(415) + self.end_headers() + return + + # chunked mode is a legitimate reason there would be no content-length, + # but it's easier to just insist on it + length = int(self.headers['content-length']) if self.headers['content-length'] else 0 + if length < 1: + self.send_response(411) + self.end_headers() + return + if length > 1024: + self.send_response(413) + self.end_headers() + return + repo = self.rfile.read(length).decode(ENCODING) + + if re.match(r"^[-_/a-zA-Z0-9\+\.]+$", repo) is None: + self.send_response(400) + self.end_headers() + return + + GitUpdaterQueue.put(repo) + self.send_response(202) + self.end_headers() + + except Exception as e: + print("Error processing request", file=sys.stderr) + print(str(e), file=sys.stderr) + self.send_response(500) + self.end_headers() + + sys.stderr.flush() + + +def Demote(pidfile, uid, gid): + def result(): + piddir = os.path.dirname(pidfile) + if not os.path.exists(piddir): + os.makedirs(piddir) + fd = open(pidfile, 'w') + fd.write(str(os.getpid())) + fd.close() + + if uid and gid: + os.setgid(gid) + os.setuid(uid) + return result + + +def daemonise(options, serverprefix, basefolder): + pw = None + uid = False + gid = False + if options.user: + pw = pwd.getpwnam(options.user) + uid = pw.pw_uid + gid = pw.pw_gid + else: + pw = pwd.getpwnam(os.getlogin()) + + user = pw.pw_name + dirname = pw.pw_dir + env = { + 'HOME': dirname, + 'LOGNAME': user, + 'PWD': dirname, + 'USER': user, + } + if os.getenv('PATH') is not None: + env['PATH'] = os.getenv('PATH') + if os.getenv('PYTHONPATH') is not None: + env['PYTHONPATH'] = os.getenv('PYTHONPATH') + + args = [os.path.abspath(sys.argv[0])] + args.append('-a') + args.append(options.addr) + args.append('-p') + args.append(str(options.port)) + args.append('-r') + args.append(options.repoprefix) + args.append('-b') + args.append(options.branch) + args.append('-c') + args.append(options.cmd) + args.append(serverprefix) + args.append(basefolder) + + subprocess.Popen( + args, preexec_fn=Demote(options.pidfile, uid, gid), cwd=dirname, env=env + ) + exit(0) + + +def main(): + usage = "usage: %prog [options] <serverprefix> <basefolder>" + description = """Listen for repository names being posted via a simple HTTP interface and clone/update them. +POST data simply via curl: +e.g. curl --header 'Content-Type: x-git/repo' --data 'my/repo/name' http://localhost:8000 +""" + parser = OptionParser(usage=usage, description=description) + parser.add_option("-a", "--addr", + type="string", dest="addr", default="0.0.0.0", + help="The interface address to bind to") + parser.add_option("-p", "--port", + type="int", dest="port", default=8000, + help="The port to bind to") + parser.add_option("-r", "--repo-prefix", + type="string", dest="repoprefix", default="", + help="Only handle repositories with the following prefix. This SHOULD contain a trailing slash if it's a folder but SHOULD NOT include a leading slash") + parser.add_option("-b", "--branch", + type="string", dest="branch", default="--mirror", + help="The branch to track on clone. If you pass '--mirror' (the default) as the branch name we will clone as a bare mirror") + parser.add_option("-c", "--cmd", + type="string", dest="cmd", default="", + help="Third party command to execute after updates. It will execute in the " + "folder of the repo and if we're not in mirror mode, a treeish will be " + "passed as the only argument containing the refs that changed otherwise " + "the command will be run without any arguments") + parser.add_option("-d", "--pid-file", + type="string", dest="pidfile", default="", + help="Daemonise and write pidfile") + parser.add_option("-u", "--user", + type="string", dest="user", default="", + help="Drop privileges to the given user (must be run as root)") + + (options, args) = parser.parse_args() + if len(args) < 2: + parser.error("Both the <serverprefix> and <basefolder> arguments must be supplied.") + if len(args) > 2: + parser.print_usage() + exit(1) + + serverprefix = args[0] + basefolder = args[1] + + if options.pidfile: + daemonise(options, serverprefix, basefolder) + + if options.user: + parser.error("You can only specify a user if you're also deamonising (with a pid file).") + + print("Server started", file=sys.stderr) + sys.stderr.flush() + srvr = TimeoutServer((options.addr, options.port), PostHandler) + updater = GitUpdater(serverprefix, basefolder, options.repoprefix, options.branch, options.cmd) + updater.start() + + try: + srvr.serve_forever() + except KeyboardInterrupt: + srvr.socket.close() + GitUpdaterQueue.put(None) + updater.join() + + +if __name__ == "__main__": + main() diff --git a/modules/gitmirror/files/on-the-pull.init b/modules/gitmirror/files/on-the-pull.init new file mode 100755 index 00000000..cc256a06 --- /dev/null +++ b/modules/gitmirror/files/on-the-pull.init @@ -0,0 +1,67 @@ +#! /bin/bash +# +# on-the-pull Keep git mirrors up-to-date via external triggers +# +# chkconfig: 2345 80 30 +# description: Keep git mirrors up-to-date via external triggers +# +### BEGIN INIT INFO +# Provides: on-the-pull +# Required-Start: $network +# Required-Stop: $network +# Default-Start: 2 3 4 5 +# Short-Description: Keep git mirrors up-to-date via external triggers +# Description: Keep git mirrors up-to-date via external triggers +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +pidfile=/var/run/on-the-pull/on-the-pull.pid +prog=/usr/local/bin/on-the-pull +args="--pid-file=$pidfile --user=git --cmd=/usr/local/bin/gitmirror-sync-metadata git://git.mageia.org /git" + + +start() { + gprintf "Starting On-The-Pull Git Mirror Daemon: " + daemon --check on-the-pull --pidfile $pidfile "$prog $args >>/var/log/on-the-pull.log 2>&1" + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/on-the-pull + return $RETVAL +} + +stop() { + gprintf "Stopping On-The-Pull Git Mirror Daemon: " + killproc -p $pidfile on-the-pull + echo + rm -f /var/lock/subsys/on-the-pull +} + +restart() { + stop + start +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status on-the-pull $pidfile + ;; + restart|reload) + restart + ;; + condrestart) + [ -f /var/lock/subsys/on-the-pull ] && restart || : + ;; + *) + gprintf "Usage: %s {start|stop|status|restart|condrestart}\n" "$(basename $0)" + exit 1 +esac + +exit 0 diff --git a/modules/gitmirror/files/rsync-metadata.sh b/modules/gitmirror/files/rsync-metadata.sh new file mode 100755 index 00000000..03a0fe41 --- /dev/null +++ b/modules/gitmirror/files/rsync-metadata.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +REPO="$1" +GITROOT="/git" +RSYNCROOT="rsync://duvel.mageia.org/git" + +if [ ! -d "$GITROOT/$REPO" ]; then + echo "No repository found $REPO" >&2 + exit 1 +fi + +/usr/bin/rsync -a --include="description" --include="info" --include="info/web" --include="info/web/last-modified" --exclude="*" "$RSYNCROOT/$REPO/" "$GITROOT/$REPO/" +/usr/bin/rsync -a "$RSYNCROOT/$REPO/config" "$GITROOT/$REPO/config.upstream" + +OWNER=$(git config --file "$GITROOT/$REPO/config.upstream" gitweb.owner) +DESC=$(git config --file "$GITROOT/$REPO/config.upstream" gitweb.description) +rm -f "$GITROOT/$REPO/config.upstream" + +CUROWNER=$(git config --file "$GITROOT/$REPO/config" gitweb.owner) +if [ "$CUROWNER" != "$OWNER" ]; then + git config --file "$GITROOT/$REPO/config" gitweb.owner "$OWNER" +fi + +CURDESC=$(git config --file "$GITROOT/$REPO/config" gitweb.description) +if [ "$CURDESC" != "$DESC" ]; then + git config --file "$GITROOT/$REPO/config" gitweb.description "$DESC" +fi diff --git a/modules/gitmirror/manifests/init.pp b/modules/gitmirror/manifests/init.pp new file mode 100644 index 00000000..c1dcd894 --- /dev/null +++ b/modules/gitmirror/manifests/init.pp @@ -0,0 +1,48 @@ +class gitmirror { + + $git_dir = '/git' + $git_login = 'git' + $git_homedir = "/var/lib/${git_login}" + $git_rundir = '/var/run/on-the-pull' + + group { $git_login: + ensure => present, + } + + user { $git_login: + ensure => present, + home => $git_homedir, + } + + file { $git_dir: + ensure => directory, + owner => $git_login, + group => $git_login, + mode => '0755', + } + + file { $git_rundir: + ensure => directory, + mode => '0755', + } + + mga_common::local_script { 'on-the-pull': + source => 'puppet:///modules/gitmirror/on-the-pull', + } + + file { '/etc/init.d/on-the-pull': + source => 'puppet:///modules/gitmirror/on-the-pull.init', + mode => '0755', + } + + service { 'on-the-pull': + require => [ + Mga_common::Local_script["on-the-pull"], + File['/etc/init.d/on-the-pull'], + ], + } + + mga_common::local_script { 'gitmirror-sync-metadata': + source => 'puppet:///modules/gitmirror/rsync-metadata.sh', + } +} diff --git a/modules/gitweb/manifests/init.pp b/modules/gitweb/manifests/init.pp index 59e74657..d7c07b22 100644 --- a/modules/gitweb/manifests/init.pp +++ b/modules/gitweb/manifests/init.pp @@ -15,12 +15,18 @@ class gitweb { webapp_file => 'gitweb/webapp.conf', } - mga-common::local_script { 'gitweb.wrapper.sh': + mga_common::local_script { 'gitweb.wrapper.sh': content => template('gitweb/wrapper.sh'), notify => Service['apache'], } - apache::vhost::base { "gitweb.$::domain": + $vhost = "gitweb.${::domain}" + apache::vhost::base { $vhost: content => template('gitweb/vhost.conf') } + apache::vhost::base { "ssl_${vhost}": + vhost => $vhost, + use_ssl => true, + content => template('gitweb/vhost.conf'), + } } diff --git a/modules/gitweb/templates/gitweb.conf b/modules/gitweb/templates/gitweb.conf index 5216077c..688844a8 100644 --- a/modules/gitweb/templates/gitweb.conf +++ b/modules/gitweb/templates/gitweb.conf @@ -121,5 +121,3 @@ our $site_name = "Mageia Git"; # To enable system wide have in /etc/gitweb.conf # $feature{'forks'}{'default'} = [1]; # Project specific override is not supported. - - diff --git a/modules/gitweb/templates/webapp.conf b/modules/gitweb/templates/webapp.conf index 54c85a29..a4d13624 100644 --- a/modules/gitweb/templates/webapp.conf +++ b/modules/gitweb/templates/webapp.conf @@ -6,4 +6,3 @@ Order allow,deny Allow from all </Directory> - diff --git a/modules/gitweb/templates/wrapper.sh b/modules/gitweb/templates/wrapper.sh index c8fdcb6d..4303007b 100644 --- a/modules/gitweb/templates/wrapper.sh +++ b/modules/gitweb/templates/wrapper.sh @@ -2,4 +2,3 @@ export FCGI_SOCKET_PATH=/tmp/gitweb.socket /usr/share/gitweb/gitweb.cgi --fastcgi - diff --git a/modules/gnupg/manifests/client.pp b/modules/gnupg/manifests/client.pp index a032b323..301e569a 100644 --- a/modules/gnupg/manifests/client.pp +++ b/modules/gnupg/manifests/client.pp @@ -1,9 +1,15 @@ class gnupg::client { +if versioncmp($::lsbdistrelease, '7') < 0 { package {['gnupg', 'rng-utils']: } +} else { + package {['gnupg2', + 'rng-utils']: + } +} - mga-common::local_script { 'create_gnupg_keys.sh': + mga_common::local_script { 'create_gnupg_keys.sh': content => template('gnupg/create_gnupg_keys.sh') } } diff --git a/modules/gnupg/manifests/keys.pp b/modules/gnupg/manifests/keys.pp index 948619a2..b99ed393 100644 --- a/modules/gnupg/manifests/keys.pp +++ b/modules/gnupg/manifests/keys.pp @@ -1,5 +1,5 @@ # debian recommend SHA2, with 4096 - # http://wiki.debian.org/Keysigning + # https://wiki.debian.org/Keysigning # as they are heavy users of gpg, I will tend # to follow them # however, for testing purpose, 4096 is too strong, @@ -14,8 +14,8 @@ define gnupg::keys($email, $keydir = '/var/lib/signbot/keys') { include gnupg::client - file { "$name.batch": - path => "$batchdir/$name.batch", + file { "${name}.batch": + path => "${batchdir}/${name}.batch", content => template('gnupg/batch') } @@ -30,9 +30,9 @@ define gnupg::keys($email, owner => $login, } - exec { "/usr/local/bin/create_gnupg_keys.sh $batchdir/$name.batch $keydir $batchdir/$name.done": + exec { "/usr/local/bin/create_gnupg_keys.sh ${batchdir}/${name}.batch ${keydir} ${batchdir}/${name}.done": user => $login, - creates => "$batchdir/$name.done", - require => [File[$keydir], File["$batchdir/$name.batch"], Package['rng-utils']], + creates => "${batchdir}/${name}.done", + require => [File[$keydir], File["${batchdir}/${name}.batch"], Package['rng-utils']], } } diff --git a/modules/gnupg/templates/batch b/modules/gnupg/templates/batch index 4dff44eb..d55bdd52 100644 --- a/modules/gnupg/templates/batch +++ b/modules/gnupg/templates/batch @@ -1,9 +1,8 @@ %echo Generating a standard key -Key-Type: <%= key_type %> -Key-Length: <%= key_length %> -Name-Real: <%= key_name %> -Name-Email: <%= email %> -Expire-Date: <%= expire_date %> +Key-Type: <%= @key_type %> +Key-Length: <%= @key_length %> +Name-Real: <%= @key_name %> +Name-Email: <%= @email %> +Expire-Date: <%= @expire_date %> %commit %echo done - diff --git a/modules/icecream/manifests/client.pp b/modules/icecream/manifests/client.pp index d58a5e65..5364d87d 100644 --- a/modules/icecream/manifests/client.pp +++ b/modules/icecream/manifests/client.pp @@ -1,4 +1,4 @@ -define icecream::client($host => '') { +define icecream::client($host = '') { include icecream::client_common file { '/etc/sysconfig/icecream': content => template('icecream/sysconfig'), diff --git a/modules/icecream/templates/sysconfig b/modules/icecream/templates/sysconfig index a3ae80c8..8a5bc92c 100644 --- a/modules/icecream/templates/sysconfig +++ b/modules/icecream/templates/sysconfig @@ -12,7 +12,7 @@ ICECREAM_NICE_LEVEL="5" # ## Type: string ## Path: Applications/icecream -## Defaut: /var/log/iceccd +## Default: /var/log/iceccd # # icecream daemon log file # @@ -21,7 +21,7 @@ ICECREAM_LOG_FILE="/var/log/icecream.log" # ## Type: string ## Path: Applications/icecream -## Defaut: no +## Default: no # # Start also the scheduler? # @@ -30,7 +30,7 @@ ICECREAM_RUN_SCHEDULER="no" # ## Type: string ## Path: Applications/icecream -## Defaut: /var/log/icecc_scheduler +## Default: /var/log/icecc_scheduler # # icecream scheduler log file # @@ -39,7 +39,7 @@ ICECREAM_SCHEDULER_LOG_FILE="/var/log/scheduler.log" # ## Type: string ## Path: Applications/icecream -## Defaut: "" +## Default: "" # # Identification for the network the scheduler and daemon run on. # You can have several distinct icecream networks in the same LAN @@ -50,17 +50,17 @@ ICECREAM_NETNAME="" # ## Type: string ## Path: Applications/icecream -## Defaut: "" +## Default: "" # # If the daemon can't find the scheduler by broadcast (e.g. because # of a firewall) you can specify it. # -ICECREAM_SCHEDULER_HOST="<%= host %>" +ICECREAM_SCHEDULER_HOST="<%= @host %>" # ## Type: string ## Path: Applications/icecream -## Defaut: "" +## Default: "" ## Type: integer # # You can overwrite here the number of jobs to run in parallel. Per diff --git a/modules/ii/manifests/init.pp b/modules/ii/manifests/init.pp index 8a63f130..2947c75d 100644 --- a/modules/ii/manifests/init.pp +++ b/modules/ii/manifests/init.pp @@ -15,23 +15,23 @@ class ii { $nick = $name include ii::base - # a custom wrappper is needed since ii do not fork in the + # a custom wrapper is needed since ii does not fork in the # background, and bash is not able to properly do it - mga-common::local_script { "ii_$nick": + mga_common::local_script { "ii_${nick}": content => template('ii/ii_wrapper.pl'), require => Class['ii::base'], } service { 'ii': provider => base, - start => "/usr/local/bin/ii_$nick", - require => Local_script["ii_$nick"], + start => "/usr/local/bin/ii_${nick}", + require => Mga_common::Local_script["ii_${nick}"], } - exec { "join channel $nick": - command => "echo '/j $channel' > /var/lib/ii/$nick/$server/in", + exec { "join channel ${nick}": + command => "echo '/j ${channel}' > /var/lib/ii/${nick}/${server}/in", user => 'nobody', - creates => "/var/lib/ii/$nick/$server/$channel/in", + creates => "/var/lib/ii/${nick}/${server}/${channel}/in", require => Service['ii'], } } diff --git a/modules/ii/templates/ii_wrapper.pl b/modules/ii/templates/ii_wrapper.pl index 5e5cc65e..68128314 100644 --- a/modules/ii/templates/ii_wrapper.pl +++ b/modules/ii/templates/ii_wrapper.pl @@ -3,8 +3,8 @@ use warnings; use strict; use POSIX; use Proc::Daemon; -my $nick = "<%= nick %>"; -my $server = "<%= server %>"; +my $nick = "<%= @nick %>"; +my $server = "<%= @server %>"; Proc::Daemon::Init(); diff --git a/modules/irkerd/manifests/init.pp b/modules/irkerd/manifests/init.pp new file mode 100644 index 00000000..adffc452 --- /dev/null +++ b/modules/irkerd/manifests/init.pp @@ -0,0 +1,9 @@ +class irkerd { + package { 'irker': + ensure => installed, + } + + service { 'irkerd': + ensure => running, + } +} diff --git a/modules/libvirtd/files/network_add.py b/modules/libvirtd/files/network_add.py index ab40bf0e..4ed63109 100644 --- a/modules/libvirtd/files/network_add.py +++ b/modules/libvirtd/files/network_add.py @@ -1,9 +1,9 @@ -#!/usr/bin/python +#!/usr/bin/python3 import libvirt import os import IPy -# bridge_name +# bridge_name # forward -> nat/ route # forward-dev @@ -59,4 +59,3 @@ network_xml = """ c=libvirt.open("qemu:///system") c.networkDefineXML(network_xml) - diff --git a/modules/libvirtd/files/storage_add.py b/modules/libvirtd/files/storage_add.py index 5d95922d..10369e36 100644 --- a/modules/libvirtd/files/storage_add.py +++ b/modules/libvirtd/files/storage_add.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import libvirt import sys @@ -25,4 +25,3 @@ storage_xml = """ c=libvirt.open("qemu:///system") c.storagePoolDefineXML(storage_xml,0) - diff --git a/modules/libvirtd/manifests/init.pp b/modules/libvirtd/manifests/init.pp index 7dcf5fc4..f0cbb887 100644 --- a/modules/libvirtd/manifests/init.pp +++ b/modules/libvirtd/manifests/init.pp @@ -6,14 +6,12 @@ class libvirtd { # iptables -> for dhcp, message error was quite puzzling # python-* => needed for helper script package {['libvirt-utils', - 'dnsmasq-base', + 'dnsmasq', 'netcat-openbsd', 'iptables', - 'python-libvirt', - 'python-IPy']: - + 'python3-libvirt', + 'python3-IPy']: } - service { 'libvirtd': require => Package['libvirt-utils'], } @@ -40,32 +38,37 @@ class libvirtd { class kvm inherits base { # pull cyrus-sasl, should be checked package { 'qemu': } - } - # see http://wiki.libvirt.org/page/SSHPolicyKitSetup + # see https://wiki.libvirt.org/page/SSHPolicyKitSetup define group_access() { # to pull polkit and create the directory include libvirtd::base - file { "/etc/polkit-1/localauthority/50-local.d/50-$name-libvirt-remote-access.pkla": + file { "/etc/polkit-1/localauthority/50-local.d/50-${name}-libvirt-remote-access.pkla": content => template('libvirtd/50-template-libvirt-remote-access.pkla'), require => Package['libvirt-utils'], } + # give access to /dev/kvm to people allowed to use libvirt + file { '/dev/kvm': + group => $name, + owner => 'root', + mode => '0660', + } } define storage($path, $autostart = true) { include libvirtd::base - exec { "/usr/local/bin/storage_add.py $name $path": - creates => "/etc/libvirt/storage/$name.xml", + exec { "/usr/local/bin/storage_add.py ${name} ${path}": + creates => "/etc/libvirt/storage/${name}.xml", require => [File['/usr/local/bin/storage_add.py'], - Package['python-libvirt'] ] + Package['python3-libvirt'] ] } #TODO use API of libvirt - file { "/etc/libvirt/storage/autostart/$name.xml": - ensure => $autostart ? { - true => "/etc/libvirt/storage/$name.xml", + file { "/etc/libvirt/storage/autostart/${name}.xml": + ensure => $autostart ? { + true => "/etc/libvirt/storage/${name}.xml", false => absent }, require => Package['libvirt-utils'], @@ -82,22 +85,22 @@ class libvirtd { $vm_type = 'qemu') { exec { '/usr/local/bin/network_add.py': - environment => ["BRIDGE_NAME=$bridge_name", - "FORWARD=$forward", - "FORWARD_DEV=$forward_dev", - "NETWORK=$network", - "TFTP_ROOT=$tftp_root", - "DISABLE_PXE=\"$disable_pxe\""], - - creates => "/etc/libvirt/$vm_type/networks/$name.xml", - require => [File['/usr/local/bin/network_add.py'], - Package['python-IPy'], Package["python-libvirt"] ] + environment => ["BRIDGE_NAME=${bridge_name}", + "FORWARD=${forward}", + "FORWARD_DEV=${forward_dev}", + "NETWORK=${network}", + "TFTP_ROOT=${tftp_root}", + "DISABLE_PXE=\"${disable_pxe}\""], + + creates => "/etc/libvirt/${vm_type}/networks/${name}.xml", + require => [File['/usr/local/bin/network_add.py'], + Package['python3-IPy'], Package['python3-libvirt'] ] } #TODO use API of libvirt - file { "/etc/libvirt/$vm_type/networks/autostart/$name.xml": - ensure => $autostart ? { - true => "/etc/libvirt/$vm_type/networks/$name.xml", + file { "/etc/libvirt/${vm_type}/networks/autostart/${name}.xml": + ensure => $autostart ? { + true => "/etc/libvirt/${vm_type}/networks/${name}.xml", false => absent }, require => Package['libvirt-utils'], diff --git a/modules/libvirtd/templates/50-template-libvirt-remote-access.pkla b/modules/libvirtd/templates/50-template-libvirt-remote-access.pkla index 201e89a0..8806e3cb 100644 --- a/modules/libvirtd/templates/50-template-libvirt-remote-access.pkla +++ b/modules/libvirtd/templates/50-template-libvirt-remote-access.pkla @@ -1,5 +1,5 @@ [Remote libvirt SSH access] -Identity=unix-user:root;unix-group:<%= name %> +Identity=unix-user:root;unix-group:<%= @name %> Action=org.libvirt.unix.manage ResultAny=yes ResultInactive=yes diff --git a/modules/mediawiki/files/init_wiki.php b/modules/mediawiki/files/init_wiki.php index a0e3a520..da1d46f5 100644 --- a/modules/mediawiki/files/init_wiki.php +++ b/modules/mediawiki/files/init_wiki.php @@ -15,12 +15,10 @@ require_once("$mw_root/includes/GlobalFunctions.php"); include("$wiki_root/LocalSettings.php"); $dbclass = 'Database'.ucfirst($wgDBtype); -$dbc = new $dbclass; - -$wgDatabase = $dbc->newFromParams($wgDBserver, - $wgDBuser, - $wgDBpassword, $wgDBname, 1); - +$wgDatabase = new $dbclass($wgDBserver, + $wgDBuser, + $wgDBpassword, $wgDBname, 1); + $wgDatabase->initial_setup($wgDBpassword, $wgDBname); $wgDatabase->setup_database(); diff --git a/modules/mediawiki/files/robots.txt b/modules/mediawiki/files/robots.txt new file mode 100644 index 00000000..a58c6199 --- /dev/null +++ b/modules/mediawiki/files/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Disallow: /mw-*/index.php? +Disallow: /*/Special: +Crawl-delay: 30 diff --git a/modules/mediawiki/manifests/base.pp b/modules/mediawiki/manifests/base.pp index 52600ac1..76c8625b 100644 --- a/modules/mediawiki/manifests/base.pp +++ b/modules/mediawiki/manifests/base.pp @@ -3,17 +3,27 @@ class mediawiki::base { $vhost = $mediawiki::config::vhost $root = $mediawiki::config::root - package { ['mediawiki-minimal','mediawiki-ldapauthentication']: } + package { ['mediawiki','mediawiki-ldapauthentication']: } file { $mediawiki::config::root: ensure => directory, } - file { '/usr/local/bin/init_wiki.php': - mode => '0755', - source => 'puppet:///modules/mediawiki/init_wiki.php', + $wiki_root = $mediawiki::config::root + $robotsfile = "$wiki_root/robots.txt" + file { $robotsfile: + ensure => present, + mode => '0644', + owner => root, + group => root, + source => 'puppet:///modules/mediawiki/robots.txt', } +# file { '/usr/local/bin/init_wiki.php': +# mode => '0755', +# source => 'puppet:///modules/mediawiki/init_wiki.php', +# } + $user = 'mediawiki' postgresql::remote_user { $user: @@ -25,7 +35,7 @@ class mediawiki::base { if $vhost { apache::vhost::redirect_ssl { $vhost: } - apache::vhost::base { "ssl_$vhost": + apache::vhost::base { "ssl_${vhost}": location => $root, use_ssl => true, vhost => $vhost, diff --git a/modules/mediawiki/manifests/config.pp b/modules/mediawiki/manifests/config.pp index 1375ea0b..0c54cdf6 100644 --- a/modules/mediawiki/manifests/config.pp +++ b/modules/mediawiki/manifests/config.pp @@ -1,9 +1,9 @@ # the class is just here to handle global configuration # a smart variation of the methods exposed on -# http://puppetlabs.com/blog/the-problem-with-separating-data-from-puppet-code/ +# https://puppetlabs.com/blog/the-problem-with-separating-data-from-puppet-code/ class mediawiki::config( $pgsql_password, $secretkey, $ldap_password, - $vhost = "wiki.$::domain", + $vhost = "wiki.${::domain}", $root = '/srv/wiki/') {} diff --git a/modules/mediawiki/manifests/instance.pp b/modules/mediawiki/manifests/instance.pp index 301c9809..c6906449 100644 --- a/modules/mediawiki/manifests/instance.pp +++ b/modules/mediawiki/manifests/instance.pp @@ -6,49 +6,95 @@ define mediawiki::instance( $title, $path = $name $lang = $name - $wiki_root = "$mediawiki::base::root/$path" - $db_name = "mediawiki_$name" + $wiki_root = "${mediawiki::base::root}/${path}" + $db_name = "mediawiki_${name}" $db_user = $mediawiki::base::user $db_password = $mediawiki::config::pgsql_password $secret_key = $mediawiki::config::secretkey $ldap_password = $mediawiki::config::ldap_password + $includedir = "/usr/share/mediawiki/includes" + $maintenancedir = "/usr/share/mediawiki/maintenance" + $vendordir = "/usr/share/mediawiki/vendor" + $resourcesdir = "/usr/share/mediawiki/resources" + $extensionsdir = "/usr/share/mediawiki/extensions" file { $wiki_root: ensure => directory } - file { "$wiki_root/skins": + file { "${wiki_root}/skins": ensure => link, target => $skinsdir, require => File[$wiki_root], } + file { "${wiki_root}/includes": + ensure => link, + target => $includedir, + require => File[$wiki_root], + } - exec { "wikicreate $name": - command => "mediawiki-create $wiki_root", - cwd => $mediawiki::base::root, - require => [File[$wiki_root],Package['mediawiki-minimal']], - creates => "$wiki_root/index.php", + file { "${wiki_root}/maintenance": + ensure => link, + target => $maintenancedir, + require => File[$wiki_root], + } + + file { "${wiki_root}/vendor": + ensure => link, + target => $vendordir, + require => File[$wiki_root], + } + + file { "${wiki_root}/resources": + ensure => link, + target => $resourcesdir, + require => File[$wiki_root], } - postgresql::remote_database { $db_name: - user => $db_user, - callback_notify => Exec["deploy_db $name"], + file { "${wiki_root}/extensions": + ensure => link, + target => $extensionsdir, + require => File[$wiki_root], } - exec { "deploy_db $name": - command => "php /usr/local/bin/init_wiki.php $wiki_root", - refreshonly => true, - onlyif => "/usr/bin/test -d $wiki_root/config", + file { "${wiki_root}/cache": + ensure => directory, + owner => apache, + mode => '0755', } - file { "$wiki_root/LocalSettings.php": + file { "${wiki_root}/tmp": + ensure => directory, + owner => apache, + mode => '0755', + } + + exec { "wikicreate ${name}": + command => "mediawiki-create ${wiki_root}", + cwd => $mediawiki::base::root, + require => [File[$wiki_root],Package['mediawiki']], + creates => "${wiki_root}/index.php", + } + +# postgresql::remote_database { $db_name: +# user => $db_user, +# callback_notify => Exec["deploy_db ${name}"], +# } +# +# exec { "deploy_db ${name}": +# command => "php /usr/local/bin/init_wiki.php ${wiki_root}", +# refreshonly => true, +# onlyif => "/usr/bin/test -d ${wiki_root}/config", +# } + + file { "${wiki_root}/LocalSettings.php": owner => 'apache', mode => '0600', content => template('mediawiki/LocalSettings.php'), # if LocalSettings is created first, the wikicreate script # do not create a confg directory, and so it doesn't # trigger deploy_db exec - require => Exec["wikicreate $name"], + require => Exec["wikicreate ${name}"], } } diff --git a/modules/mediawiki/templates/LocalSettings.php b/modules/mediawiki/templates/LocalSettings.php index 3e0b7bd3..c340dfd9 100644 --- a/modules/mediawiki/templates/LocalSettings.php +++ b/modules/mediawiki/templates/LocalSettings.php @@ -7,105 +7,121 @@ # file, not there. # # Further documentation for configuration settings may be found at: -# http://www.mediawiki.org/wiki/Manual:Configuration_settings +# https://www.mediawiki.org/wiki/Manual:Configuration_settings +# Protect against web entry +if ( !defined( 'MEDIAWIKI' ) ) { + exit; +} + +## Installation path (should default to this value, but define for clarity) $IP = '/usr/share/mediawiki'; -if (! isset($DIR)) $DIR = getcwd(); +## Include path necessary to load LDAP module $path = array( $IP, "$IP/includes", "$IP/languages" ); set_include_path( implode( PATH_SEPARATOR, $path ) . PATH_SEPARATOR . get_include_path() ); -require_once( "$IP/includes/DefaultSettings.php" ); - -if ( $wgCommandLineMode ) { - if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { - die( "This script must be run from the command line\n" ); - } -} ## Uncomment this to disable output compression # $wgDisableOutputCompression = true; -$wgSitename = "<%= title %>"; +$wgSitename = "<%= @title %>"; +# $wgMetaNamespace = ""; # Defaults to $wgSitename ## The URL base path to the directory containing the wiki; ## defaults for all runtime URL paths are based off of this. -## For more information on customizing the URLs please see: -## http://www.mediawiki.org/wiki/Manual:Short_URL -$wgScriptPath = "/<%= path %>"; -$wgScriptExtension = ".php"; +## For more information on customizing the URLs +## (like /w/index.php/Page_title to /wiki/Page_title) please see: +## https://www.mediawiki.org/wiki/Manual:Short_URL +$wgScriptPath = "/<%= @path %>"; + +## The protocol and server name to use in fully-qualified URLs +$wgServer = "https://wiki.mageia.org"; + +## The URL path to static resources (images, scripts, etc.) +$wgResourceBasePath = $wgScriptPath; ## The relative URL path to the skins directory -$wgStylePath = "$wgScriptPath/skins"; +$wgStylePath = "$wgScriptPath/skins"; ## The relative URL path to the logo. Make sure you change this from the default, ## or else you'll overwrite your logo when you upgrade! -$wgLogo = "$wgStylePath/common/images/wiki.png"; +$wgLogo = "$wgStylePath/common/images/wiki_mga.png"; ## UPO means: this is also a user preference option -$wgEnableEmail = true; -$wgEnableUserEmail = true; # UPO +$wgEnableEmail = true; +$wgEnableUserEmail = true; # UPO -$wgEmergencyContact = "root@<%= domain %>"; -$wgPasswordSender = "root@<%= domain %>"; +$wgEmergencyContact = "root@<%= @domain %>"; +$wgPasswordSender = "wiki_noreply@ml.<%= @domain %>"; $wgEnotifUserTalk = true; # UPO $wgEnotifWatchlist = true; # UPO $wgEmailAuthentication = true; ## Database settings -$wgDBtype = "postgres"; -$wgDBserver = "pgsql.<%= domain %>"; -$wgDBname = "<%= db_name %>"; -$wgDBuser = "<%= db_user %>"; -$wgDBpassword = "<%= db_password %>"; +$wgDBtype = "postgres"; +$wgDBserver = "pg.<%= @domain %>"; +$wgDBname = "<%= @db_name %>"; +$wgDBuser = "<%= @db_user %>"; +$wgDBpassword = "<%= @db_password %>"; # Postgres specific settings -$wgDBport = "5432"; -$wgDBmwschema = "mediawiki"; -$wgDBts2schema = "public"; +$wgDBport = "5432"; +$wgDBmwschema = "mediawiki"; +$wgDBts2schema = "public"; ## Shared memory settings $wgMainCacheType = CACHE_NONE; -$wgMemCachedServers = array(); +$wgMemCachedServers = []; ## To enable image uploads, make sure the 'images' directory ## is writable, then set this to true: -$wgEnableUploads = false; -# use gd, as convert do not work for big image +$wgEnableUploads = true; +# use gd, as convert do not work for big image # see https://bugs.mageia.org/show_bug.cgi?id=3202 -$wgUseImageMagick = false; +$wgUseImageMagick = true; #$wgImageMagickConvertCommand = "/usr/bin/convert"; +# InstantCommons allows wiki to use images from https://commons.wikimedia.org +$wgUseInstantCommons = false; + ## If you use ImageMagick (or any other shell command) on a ## Linux server, this will need to be set to the name of an ## available UTF-8 locale $wgShellLocale = "en_US.UTF-8"; -## If you want to use image uploads under safe mode, -## create the directories images/archive, images/thumb and -## images/temp, and make them all writable. Then uncomment -## this, if it's not already uncommented: -# $wgHashedUploadDirectory = false; - -## If you have the appropriate support software installed -## you can enable inline LaTeX equations: -$wgUseTeX = false; - ## Set $wgCacheDirectory to a writable directory on the web server ## to make your wiki go slightly faster. The directory should not -## be publically accessible from the web. -#$wgCacheDirectory = "$IP/cache"; +## be publicly accessible from the web. +# This seems actually mandatory to get the Vector skin to work properly +# https://serverfault.com/a/744059 +# FIXME: Dehardcode that path (maybe via ${wiki_root} if exposed?) +$wgCacheDirectory = "/srv/wiki/<%= @path %>/cache"; -$wgLocalInterwiki = strtolower( $wgSitename ); +$wgUploadDirectory = "/srv/wiki/<%= @path %>/images"; -$wgLanguageCode = "<%= lang %>"; +# This seems mandatory to get the Vector skin to work properly +# https://phabricator.wikimedia.org/T119934 +# FIXME: Dehardcode that path (maybe via ${wiki_root} if exposed?) +$wgTmpDirectory = "/srv/wiki/<%= @path %>/tmp"; -$wgSecretKey = "<%= secret_key %>"; +# Array of interwiki prefixes for current wiki. +$wgLocalInterwikis = array( strtolower( $wgSitename ) ); -## Default skin: you can change the default skin. Use the internal symbolic -## names, ie 'vector', 'monobook': -$wgDefaultSkin = 'modern'; +# Site language code, should be one of the list in ./languages/data/Names.php +$wgLanguageCode = "<%= @lang %>"; + +$wgSecretKey = "<%= @secret_key %>"; + +# Changing this will log out all existing sessions. +$wgAuthenticationTokenVersion = "1"; + +# Site upgrade key. Must be set to a string (default provided) to turn on the +# web installer while LocalSettings.php is in place +# FIXME: This should be set to a secure value: +# https://www.mediawiki.org/wiki/Manual:$wgUpgradeKey +# $wgUpgradeKey = ""; ## For attaching licensing metadata to pages, and displaying an ## appropriate copyright notice / icon. GNU Free Documentation @@ -113,17 +129,41 @@ $wgDefaultSkin = 'modern'; $wgEnableCreativeCommonsRdf = true; # TODO add a proper page $wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright -$wgRightsUrl = "http://creativecommons.org/licenses/by-sa/3.0/"; -$wgRightsText = "Creative Common - Attibution - ShareAlike 3.0"; +$wgRightsUrl = "https://creativecommons.org/licenses/by-sa/3.0/"; +$wgRightsText = "Creative Commons - Attribution-ShareAlike 3.0 Unported"; # TODO get the icon to host it on our server -$wgRightsIcon = "http://i.creativecommons.org/l/by-sa/3.0/88x31.png"; -# $wgRightsCode = "gfdl1_3"; # Not yet used +$wgRightsIcon = "https://licensebuttons.net/l/by-sa/3.0/88x31.png"; +# Path to the GNU diff3 utility. Used for conflict resolution. $wgDiff3 = "/usr/bin/diff3"; -# When you make changes to this configuration file, this will make -# sure that cached pages are cleared. -$wgCacheEpoch = max( $wgCacheEpoch, gmdate( 'YmdHis', @filemtime( __FILE__ ) ) ); +## Default skin: you can change the default skin. Use the internal symbolic +## names, ie 'vector', 'monobook': +$wgDefaultSkin = 'vector'; + +# Enabled skins. +# The following skins were automatically enabled: +wfLoadSkin( 'MonoBook' ); +wfLoadSkin( 'Vector' ); + + +# End of automatically generated settings. +# Add more configuration options below. + + +# Setting this to true will invalidate all cached pages whenever +# LocalSettings.php is changed. +$wgInvalidateCacheOnLocalSettingsChange = true; + +# FIXME: Obsoleted, to be replaced by $wgPasswordPolicy +# https://www.mediawiki.org/wiki/Manual:$wgPasswordPolicy +$wgMinimalPasswordLength = 1; + +# Give more details on errors +$wgShowExceptionDetails = true; + + +## LDAP setup require_once 'extensions/LdapAuthentication/LdapAuthentication.php'; $wgAuth = new LdapAuthenticationPlugin(); @@ -132,39 +172,37 @@ $wgAuth = new LdapAuthenticationPlugin(); # $wgLDAPDebug = 10; # $wgDebugLogGroups["ldap"] = "/tmp/wiki_ldap.log"; # -# $wgDebugLogFile = "/tmp/wiki.log"; +$wgDebugLogFile = "/tmp/wiki.log"; # $wgLDAPUseLocal = false; -$wgLDAPDomainNames = array( 'ldap'); +$wgLDAPDomainNames = array( 'ldap' ); + +# TODO make it workable with more than one server +$wgLDAPServerNames = array( 'ldap' => 'ldap.<%= @domain %>' ); + +$wgLDAPSearchStrings = array( 'ldap' => 'uid=USER-NAME,ou=People,<%= @dc_suffix %>' ); -#TODO make it workable with more than one server -$wgLDAPServerNames = array( 'ldap' => 'ldap.<%= domain %>' ); - -$wgLDAPSearchStrings = array( 'ldap' => 'uid=USER-NAME,ou=People,<%= dc_suffix %>'); +$wgLDAPEncryptionType = array( 'ldap' => 'tls' ); -$wgLDAPEncryptionType = array( 'ldap' => 'tls'); +$wgLDAPBaseDNs = array( 'ldap' => '<%= @dc_suffix %>' ); +$wgLDAPUserBaseDNs = array( 'ldap' => 'ou=People,<%= @dc_suffix %>' ); +$wgLDAPGroupBaseDNs = array ( 'ldap' => 'ou=Group,<%= @dc_suffix %>' ); -$wgLDAPBaseDNs = array( 'ldap' => '<%= dc_suffix %>'); -$wgLDAPUserBaseDNs = array( 'ldap' => 'ou=People,<%= dc_suffix %>'); -$wgLDAPGroupBaseDNs = array ( 'ldap' => 'ou=Group,<%= dc_suffix %>' ); +$wgLDAPProxyAgent = array( 'ldap' => 'cn=mediawiki-alamut,ou=System Accounts,<%= @dc_suffix %>' ); -$wgLDAPProxyAgent = array( 'ldap' => 'cn=mediawiki-alamut,ou=System Accounts,<%= dc_suffix %>'); - -$wgLDAPProxyAgentPassword = array( 'ldap' => '<%= ldap_password %>' ); +$wgLDAPProxyAgentPassword = array( 'ldap' => '<%= @ldap_password %>' ); -$wgLDAPUseLDAPGroups = array( "ldap" => true ); -$wgLDAPGroupNameAttribute = array( "ldap" => "cn" ); +$wgLDAPUseLDAPGroups = array( 'ldap' => true ); +$wgLDAPGroupNameAttribute = array( 'ldap' => 'cn' ); $wgLDAPGroupUseFullDN = array( 'ldap' => true ); $wgLDAPLowerCaseUsername = array( 'ldap' => true ); $wgLDAPGroupObjectclass = array( 'ldap' => 'posixGroup' ); $wgLDAPGroupAttribute = array( 'ldap' => 'member' ); -$wgLDAPLowerCaseUsername = array( "ldap" => true ); - -$wgLDAPPreferences = array( "ldap" => array( "email"=>"mail","realname"=>"cn","nickname"=>"uid","language"=>"preferredlanguage") ); +$wgLDAPLowerCaseUsername = array( 'ldap' => true ); -$wgMinimalPasswordLength = 1; +$wgLDAPPreferences = array( 'ldap' => array( 'email'=>'mail','realname'=>'cn','nickname'=>'uid','language'=>'preferredlanguage') ); -<%= wiki_settings %> +<%= @wiki_settings %> diff --git a/modules/mediawiki/templates/wiki_vhost.conf b/modules/mediawiki/templates/wiki_vhost.conf index 3fe038c3..1ae3492d 100644 --- a/modules/mediawiki/templates/wiki_vhost.conf +++ b/modules/mediawiki/templates/wiki_vhost.conf @@ -1,9 +1,9 @@ # heavily used by the wiki farm stuff -<Directory <%= root %>> +<Directory <%= @root %>> Options +FollowSymLinks </Directory> -<Directory <%= root %>/images> +<Directory <%= @root %>/images> SetHandler default-handler </Directory> diff --git a/modules/mga-advisories/manifests/init.pp b/modules/mga-advisories/manifests/init.pp new file mode 100644 index 00000000..1937bb62 --- /dev/null +++ b/modules/mga-advisories/manifests/init.pp @@ -0,0 +1,98 @@ +class mga-advisories( + $advisories_svn = "svn://svn.${::domain}/svn/advisories", + $vhost +){ + $mgaadv_login = 'mga-advisories' + $mgaadv_homedir = "/var/lib/${mgaadv_login}" + $vhostdir = "${mgaadv_homedir}/vhost" + $advisories_dir = "${mgaadv_homedir}/advisories" + $status_dir = "${mgaadv_homedir}/status" + $update_script = '/usr/local/bin/update_mga-advisories' + $move_script = '/root/tmp/mgatools-new/mga-move-pkg' + $move_wrapper_script = '/usr/local/bin/mga-adv-move-pkg' + + group { $mgaadv_login: + ensure => present, + } + + user { $mgaadv_login: + ensure => present, + home => $mgaadv_homedir, + managehome => true, + gid => $mgaadv_login, + } + + package { 'mga-advisories': + ensure => installed, + } + + file {'/etc/mga-advisories.conf': + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mga-advisories/mga-advisories.conf'), + require => Package['mga-advisories'], + } + + file { [ $vhostdir, $status_dir ]: + ensure => directory, + owner => $mgaadv_login, + group => $mgaadv_login, + mode => '0755', + } + + $vhost_aliases = { + "/static" => '/usr/share/mga-advisories/static', + } + apache::vhost::base { $vhost: + location => $vhostdir, + aliases => $vhost_aliases, + require => File[$vhostdir], + } + + apache::vhost::base { "ssl_${vhost}": + use_ssl => true, + vhost => $vhost, + aliases => $vhost_aliases, + location => $vhostdir, + require => File[$vhostdir], + } + + subversion::snapshot { $advisories_dir: + source => $advisories_svn, + user => $mgaadv_login, + refresh => '0', + require => User[$mgaadv_login], + } + + file { $update_script: + ensure => present, + owner => root, + group => root, + mode => '0755', + content => template('mga-advisories/update_script'), + } + + file { $move_wrapper_script: + ensure => present, + owner => root, + group => root, + mode => '0755', + content => template('mga-advisories/adv-move-pkg'), + } + + sudo::sudoers_config { 'mga-adv-move-pkg': + content => template('mga-advisories/sudoers.adv-move-pkg') + } + + # Disable for now... we may re-instate once it's been a little more tested. + #cron { $update_script: + # command => $update_script, + # user => $mgaadv_login, + # hour => '*', + # minute => '10', + # require => Subversion::Snapshot[$advisories_dir], + #} +} +# vim: sw=2 diff --git a/modules/mga-advisories/templates/adv-move-pkg b/modules/mga-advisories/templates/adv-move-pkg new file mode 100644 index 00000000..71e1880e --- /dev/null +++ b/modules/mga-advisories/templates/adv-move-pkg @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$USER" != "<%= @mgaadv_login %>" ]; then + echo "This script must be run as the <%= @mgaadv_login %> user." >&2 + exit 1 +fi + +exec sudo <%= @move_script %> "$@" diff --git a/modules/mga-advisories/templates/mga-advisories.conf b/modules/mga-advisories/templates/mga-advisories.conf new file mode 100644 index 00000000..4dab1543 --- /dev/null +++ b/modules/mga-advisories/templates/mga-advisories.conf @@ -0,0 +1,14 @@ +mode: site +send_adv_mail: yes +move_pkg_cmd: <%= @move_wrapper_script %> +send_report_mail: yes +out_dir: <%= @vhostdir %> +advisories_dir: <%= @advisories_dir %> +status_dir: <%= @status_dir %> +adv_mail_to: updates-announce@ml.mageia.org +adv_mail_from: Mageia Updates <buildsystem-daemon@mageia.org> +report_mail_to: qa-reports@ml.mageia.org +report_mail_from: Mageia Advisories <buildsystem-daemon@mageia.org> +bugzilla_url: https://bugs.mageia.org/ +bugzilla_login: bot +bugzilla_password: file:///var/lib/git/.gitzilla-password diff --git a/modules/mga-advisories/templates/sudoers.adv-move-pkg b/modules/mga-advisories/templates/sudoers.adv-move-pkg new file mode 100644 index 00000000..5d9618a9 --- /dev/null +++ b/modules/mga-advisories/templates/sudoers.adv-move-pkg @@ -0,0 +1 @@ +<%= @mgaadv_login %> ALL=(root) NOPASSWD:<%= @move_script %> * diff --git a/modules/mga-advisories/templates/update_script b/modules/mga-advisories/templates/update_script new file mode 100644 index 00000000..71d8d1d4 --- /dev/null +++ b/modules/mga-advisories/templates/update_script @@ -0,0 +1,16 @@ +#!/bin/sh +set -e + +if [ "$UID" = "0" ]; then + echo "Re-running as '<%= @mgaadv_login %>' user." >&2 + exec /bin/su -c <%= @update_script %> - <%= @mgaadv_login %> +fi + +if [ "$USER" != "<%= @mgaadv_login %>" ]; then + echo "This script must be run as the <%= @mgaadv_login %> user." >&2 + exit 1 +fi + +cd <%= @advisories_dir %> +svn up +exec /usr/bin/mgaadv process diff --git a/modules/mga-common/manifests/local_script.pp b/modules/mga-common/manifests/local_script.pp deleted file mode 100644 index 0b8f4514..00000000 --- a/modules/mga-common/manifests/local_script.pp +++ /dev/null @@ -1,11 +0,0 @@ -define mga-common::local_script($content, - $owner = 'root', - $group = 'root', - $mode = '0755') { - file { "/usr/local/bin/$name": - owner => $owner, - group => $group, - mode => $mode, - content => $content, - } -} diff --git a/modules/mga-mirrors/files/check_mirrors_status b/modules/mga-mirrors/files/check_mirrors_status new file mode 100755 index 00000000..9c00ac8d --- /dev/null +++ b/modules/mga-mirrors/files/check_mirrors_status @@ -0,0 +1,271 @@ +#!/usr/bin/ruby + +require 'date' +require 'net/http' +require 'optparse' +require 'thread' +require 'uri' + +def get_dates(base, archs_per_distro, optional=true) + r = {} + begin + r['base'] = get_timestamp(base) + rescue Net::OpenTimeout, Timeout::Error, ArgumentError, NoMethodError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::ECONNRESET, IOError, OpenSSL::SSL::SSLError => e + end + + archs_per_distro.each{|d, archs| + r[d] = {} + archs.each{|a| + begin + r[d][a] = get_date(base, d, a) + rescue Net::OpenTimeout, Timeout::Error, ArgumentError, NoMethodError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::ECONNRESET, IOError, OpenSSL::SSL::SSLError => e + if !optional then + STDERR.puts "Failed to fetch #{version_url(base, d, a)}" + raise + end + end + } + } + r +end + +def get_mirrors + # TODO Get it from the DB + mirrors = [] + url = nil + tier1 = false + fetch_url("https://mirrors.mageia.org/").each_line{|l| + if l =~ /rsync.mageia.org/ then + tier1 = true + next + end + if l=~ /<\/tr>/ && !url.nil? then + if tier1 then + mirrors.prepend url + tier1 = false + else + mirrors.append url + end + url = nil + next + end + next unless l =~ /https?:.*>http/ + # No need to check twice mirrors available in http + https + if !url.nil? && url =~ /https:/ && l =~ /https:\/\// + # Skip http:// if https:// already seen for current mirror + # If the are in the other order http one will just be replaced + next + end + url = l.sub(/<a href="(http[^"]*)".*\n/, '\1') + url += "/" unless url =~ /\/$/ + } + mirrors +end + +def fetch_url(url, redirect_limit = 3) + return if redirect_limit < 0 + if url =~ /^\// then + open(url){|f| + return f.read + } + else + uri = URI.parse(url) + http = Net::HTTP.new(uri.host, uri.port) + http.open_timeout = 30 + http.read_timeout = 30 + if uri.scheme == 'https' then + http.use_ssl = true + end + # Ruby 1.8.7 doesn't set a default User-Agent which causes at + # least one mirror to return 403 + response = http.get(uri.path, {'User-Agent' => 'check_mirrors'}) + case response + when Net::HTTPSuccess then + return response.body + when Net::HTTPRedirection then + location = response['location'] + # Make location absolute if it was not + if location =~ /:\/\// then + fetch_url(location, redirect_limit - 1) + else + uri.path = location + fetch_url(uri.to_s, redirect_limit - 1) + end + end + end +end + +def timestamp_url(url) + "#{url}mageia_timestamp" +end + +def get_timestamp(url) + ti = fetch_url(timestamp_url(url)).to_i + if ti == 0 then + return nil + end + return DateTime.strptime(ti.to_s, '%s') +end + +def parse_version(version) + date = version.sub(/.* (........ ..:..)$/, '\1').rstrip + DateTime.strptime(date, '%Y%m%d %H:%M') +end + +def version_url(url, distrib, arch) + "#{url}distrib/#{distrib}/#{arch}/VERSION" +end + +def get_date(url, distrib, arch) + return parse_version(fetch_url(version_url(url, distrib, arch))) +end + +def format_age(ref_time, time) + return " <td class='broken'>X</td>" unless ref_time and time + + diff = ref_time - time + cls = 'broken' + if diff == 0 then + cls = 'ok' + elsif diff < 0.5 then + cls = 'almost' + elsif diff < 2 then + cls = 'bad' + end + if cls == 'ok' then + return " <td class='#{cls}'> </td>" + else + return " <td class='#{cls}'>#{time.strftime("%F %R")}</td>" + end +end + +def print_output(archs_per_distro, mirrors, ref_times, times) + puts "<html><head><title>Mageia Mirror Status #{Time.now.utc.strftime("%F")}</title> +<link rel=\"icon\" type=\"image/png\" href=\"//www.mageia.org/g/favicon.png\"> +<style> +td.broken {background-color:#FF0033;} +td.bad {background-color:#FF9933;} +td.almost {background-color:#CCFF66;} +td.ok {background-color:#00FF66;} + +td {text-align:center;} +td.name {text-align:left;} + +td.sep {width:12px;} +table.legend td {padding:4px;} + +th {background-color:#EEEEEE;} +</style> +</head> +<body>" + puts "Last checked on #{Time.now.utc.strftime("%F %R %Z")}<br/>" + puts "<table class='legend'><tr><td class='ok'>Up to date</td><td class='almost'>Less than 12h old</td><td class='bad'>Less than 2 days old</td><td class='broken'>Old or broken</td></tr></table>" + puts "<table><thead>" + puts "<tr><td/>" + puts "<td/><th>Base directory</th>" + archs_per_distro.each{|d, archs| + nb_arches = archs.size + puts " <td/><th colspan='#{nb_arches}'>#{d}</th>" + } + puts "</tr>" + puts "<tr><td/><td/><td/>" + archs_per_distro.each{|d, archs| + puts " <td class='sep' />" + archs.each{|a| + puts " <th>#{a}</th>" + } + } + puts "</tr></thead>" + puts "<tbody>" + puts "<tr><td class='name'>Reference</td>" + puts " <td class='sep' />" + puts " <td>#{!ref_times['base'].nil? ? ref_times['base'].strftime("%F %R") : "?"}</td>" + archs_per_distro.each{|d, archs| + puts " <td class='sep' />" + archs.each{|a| + puts " <td>#{ref_times[d][a].strftime("%F %R")}</td>" + } + } + puts "</tr>" + + mirrors.each{|u| + puts "<tr><td class='name'><a href='#{u}'>#{u}</a></td>" + puts " <td class='sep' />" + puts format_age(ref_times['base'], times[u]['base']) + archs_per_distro.each{|d, archs| + puts " <td class='sep' />" + archs.each{|a| + puts format_age(ref_times[d][a], times[u][d][a]) + } + } + puts "</tr>" + } + puts "</tbody></table>" + puts "</body></html>" +end + + + +# Defaults +ref = 'http://repository.mageia.org/' +archs_per_distro = { + 'cauldron' => ['i686', 'x86_64', 'armv7hl', 'aarch64'], + '9' => ['i586', 'x86_64', 'armv7hl', 'aarch64'] +} +parallel = 8 + +OptionParser.new {|opts| + opts.banner = "Usage: #{$0} [options]" + opts.on("--repository URL", + "Reference repository. Default: #{ref}") { + |url| ref = url + } + opts.on("--parallel n", Integer, + "Max number of parallel connections. Default: #{parallel}") { + |n| $parallel = n + } + opts.on("--output file", + "Write output into given file. Default to STDOUT") { + |f| $stdout.reopen(f, "w") + } +}.parse! + +# Get dates from the reference repository, and fail if some requested distros +# or archs are missing +ref_times = get_dates(ref, archs_per_distro, false) + +# Get the list of mirror URLs to check +mirrors = get_mirrors + +workqueue = Queue.new +times = {} + +# Create all the thread and have them loop on the work queue +threads = (1..parallel).map{|n| + Thread.new { + loop do + u = workqueue.pop + break if u == :exit + times[u] = get_dates(u, archs_per_distro) + end + } +} + +# Push all mirrors into the queue +mirrors.each{|u| + workqueue << u +} + +# Get all the threads to exit after all the work is done +parallel.times{|i| + workqueue << :exit +} + +# Wait for the threads to exit +threads.each{|t| + t.join +} + +# Generate output +print_output(archs_per_distro, mirrors, ref_times, times) + diff --git a/modules/mga-mirrors/manifests/init.pp b/modules/mga-mirrors/manifests/init.pp index ce55538a..4b8b5552 100644 --- a/modules/mga-mirrors/manifests/init.pp +++ b/modules/mga-mirrors/manifests/init.pp @@ -1,12 +1,26 @@ class mga-mirrors { - $vhost = "mirrors.$::domain" + $vhost = "mirrors.${::domain}" + $mirrors_dir = '/var/www/mirrors' package { 'mga-mirrors': } apache::vhost::catalyst_app { $vhost: script => '/usr/bin/mga_mirrors_fastcgi.pl', require => Package['mga-mirrors'], + aliases => { + '/status' => '/var/www/mirrors/status.html', + } + } + + apache::vhost::catalyst_app { "ssl_${vhost}": + script => '/usr/bin/mga_mirrors_fastcgi.pl', + require => Package['mga-mirrors'], + vhost => $vhost, + use_ssl => true, + aliases => { + '/status' => '/var/www/mirrors/status.html', + }, } $pgsql_password = extlookup('mga_mirror_pgsql','x') @@ -23,8 +37,18 @@ class mga-mirrors { require => Package['mga-mirrors'] } - file { '/etc/cron.d/mga_mirrors': + file { '/etc/cron.d/check_mga_mirrors': content => template('mga-mirrors/cron-mga_mirrors'), require => Package['mga-mirrors'] } + + file { $mirrors_dir: + ensure => directory, + owner => 'nobody', + } + + file { '/usr/local/bin/check_mirrors_status': + mode => '0755', + source => 'puppet:///modules/mga-mirrors/check_mirrors_status', + } } diff --git a/modules/mga-mirrors/templates/cron-mga_mirrors b/modules/mga-mirrors/templates/cron-mga_mirrors index 0f9410a8..7236be04 100644 --- a/modules/mga-mirrors/templates/cron-mga_mirrors +++ b/modules/mga-mirrors/templates/cron-mga_mirrors @@ -1,2 +1,2 @@ MAILTO=root -0 * * * * apache /usr/bin/check_mirror > /dev/null 2>&1 +*/20 * * * * nobody /usr/local/bin/check_mirrors_status --output /var/www/mirrors/status.html.tmp && mv -f /var/www/mirrors/status.html.tmp /var/www/mirrors/status.html diff --git a/modules/mga-mirrors/templates/mga-mirrors.ini b/modules/mga-mirrors/templates/mga-mirrors.ini index ce7ee911..b438edd1 100644 --- a/modules/mga-mirrors/templates/mga-mirrors.ini +++ b/modules/mga-mirrors/templates/mga-mirrors.ini @@ -1,4 +1,4 @@ [db] -pgconn=host=pgsql.<%= domain %>;dbname=mirrors +pgconn=host=pg.<%= @domain %>;dbname=mirrors user=mirrors -password=<%= pgsql_password %> +password=<%= @pgsql_password %> diff --git a/modules/mga-treasurer/manifests/init.pp b/modules/mga-treasurer/manifests/init.pp new file mode 100644 index 00000000..d092e982 --- /dev/null +++ b/modules/mga-treasurer/manifests/init.pp @@ -0,0 +1,91 @@ +class mga-treasurer( + $grisbi_git = "git://git.${::domain}/org/accounts", + $grisbi_filename = 'mageia-accounts.gsb', + $vhost, + $vhostdir +){ + $mgatres_login = 'mga-treasurer' + $mgatres_homedir = "/var/lib/${mgatres_login}" + $grisbi_dir = "${mgatres_homedir}/grisbi" + $grisbi_path = "${grisbi_dir}/${grisbi_filename}" + + $update_script = '/usr/local/bin/update_mga-treasurer' + + group { $mgatres_login: + ensure => present, + } + + user { $mgatres_login: + ensure => present, + comment => 'mga-treasurer user', + home => $mgatres_homedir, + managehome => true, + gid => $mgatres_login, + } + + package { 'mga-treasurer': + ensure => installed, + } + + file {'/etc/mga-treasurer.conf': + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mga-treasurer/mga-treasurer.conf'), + require => Package['mga-treasurer'], + } + + file { $vhostdir: + ensure => directory, + owner => $mgatres_login, + group => $mgatres_login, + mode => '0755', + } + + apache::vhost::base { $vhost: + location => $vhostdir, + aliases => { + "/${grisbi_filename}" => $grisbi_path, + "/static" => '/usr/share/mga-treasurer/static', + }, + content => template('mga-treasurer/vhost_mga-treasurer.conf'), + require => File[$vhostdir], + } + + apache::vhost::base { "ssl_${vhost}": + use_ssl => true, + vhost => $vhost, + location => $vhostdir, + aliases => { + "/${grisbi_filename}" => $grisbi_path, + "/static" => '/usr/share/mga-treasurer/static', + }, + content => template('mga-treasurer/vhost_mga-treasurer.conf'), + require => File[$vhostdir], + } + + file { $update_script: + ensure => present, + owner => root, + group => root, + mode => '0755', + content => template('mga-treasurer/update_script'), + } + + git::snapshot { $grisbi_dir: + source => $grisbi_git, + user => $mgatres_login, + refresh => '0', + require => User[$mgatres_login], + } + + cron { $update_script: + command => $update_script, + user => $mgatres_login, + hour => '*/2', + minute => '10', + require => Git::Snapshot[$grisbi_dir], + } +} +# vim: sw=2 diff --git a/modules/mga-treasurer/templates/mga-treasurer.conf b/modules/mga-treasurer/templates/mga-treasurer.conf new file mode 100644 index 00000000..75ac180f --- /dev/null +++ b/modules/mga-treasurer/templates/mga-treasurer.conf @@ -0,0 +1,2 @@ +grisbi_file: <%= @grisbi_path %> +out_dir: <%= @vhostdir %> diff --git a/modules/mga-treasurer/templates/update_script b/modules/mga-treasurer/templates/update_script new file mode 100644 index 00000000..30fab72d --- /dev/null +++ b/modules/mga-treasurer/templates/update_script @@ -0,0 +1,6 @@ +#!/bin/sh +set -e + +cd <%= @grisbi_dir %> +git pull +exec /usr/bin/mktreasurer diff --git a/modules/mga-treasurer/templates/vhost_mga-treasurer.conf b/modules/mga-treasurer/templates/vhost_mga-treasurer.conf new file mode 100644 index 00000000..763cd87d --- /dev/null +++ b/modules/mga-treasurer/templates/vhost_mga-treasurer.conf @@ -0,0 +1,3 @@ +<FilesMatch "\.json$"> + Header set Access-Control-Allow-Origin "*" +</FilesMatch> diff --git a/modules/mga_common/lib/puppet/parser/functions/group_members.rb b/modules/mga_common/lib/puppet/parser/functions/group_members.rb new file mode 100644 index 00000000..ea275be2 --- /dev/null +++ b/modules/mga_common/lib/puppet/parser/functions/group_members.rb @@ -0,0 +1,14 @@ +# group_members($group) +# -> return a array with the login of the group members + +module Puppet::Parser::Functions + newfunction(:group_members, :type => :rvalue) do |args| + group = args[0] + `getent group`.each_line do |l| + if l =~ /^#{group}:/ then + return l.chomp.split(':')[3].split(',') + end + end + raise ArgumentError, "can't find group for #{group}" + end +end diff --git a/modules/mga_common/lib/puppet/parser/functions/hash_keys.rb b/modules/mga_common/lib/puppet/parser/functions/hash_keys.rb new file mode 100644 index 00000000..3a926bee --- /dev/null +++ b/modules/mga_common/lib/puppet/parser/functions/hash_keys.rb @@ -0,0 +1,10 @@ +module Puppet::Parser::Functions + newfunction(:hash_keys, :type => :rvalue) do |args| + unless args[0].is_a?(Hash) + Puppet.warning "hash_keys takes one argument, the input hash" + nil + else + args[0].keys + end + end +end diff --git a/modules/mga_common/lib/puppet/parser/functions/hash_merge.rb b/modules/mga_common/lib/puppet/parser/functions/hash_merge.rb new file mode 100644 index 00000000..375bffa4 --- /dev/null +++ b/modules/mga_common/lib/puppet/parser/functions/hash_merge.rb @@ -0,0 +1,11 @@ +module Puppet::Parser::Functions + newfunction(:hash_merge, :type => :rvalue) do |args| + unless args[0].is_a?(Hash) and args[1].is_a?(Hash) + Puppet.warning "hash_merge takes two arguments" + nil + else + print "hash_merge\n" + args[0].merge(args[1]) + end + end +end diff --git a/modules/mga_common/lib/puppet/parser/functions/str_join.rb b/modules/mga_common/lib/puppet/parser/functions/str_join.rb new file mode 100644 index 00000000..c881c37d --- /dev/null +++ b/modules/mga_common/lib/puppet/parser/functions/str_join.rb @@ -0,0 +1,11 @@ +# str_join($array, $sep) +# -> return a string created by converting each element of the array to +# a string, separated by $sep + +module Puppet::Parser::Functions + newfunction(:str_join, :type => :rvalue) do |args| + array = args[0] + sep = args[1] + return array.join(sep) + end +end diff --git a/modules/mga_common/manifests/local_script.pp b/modules/mga_common/manifests/local_script.pp new file mode 100644 index 00000000..3272786b --- /dev/null +++ b/modules/mga_common/manifests/local_script.pp @@ -0,0 +1,22 @@ +define mga_common::local_script( + $content = undef, + $source = undef, + $owner = 'root', + $group = 'root', + $mode = '0755') { + $filename = "/usr/local/bin/${name}" + file { $filename: + owner => $owner, + group => $group, + mode => $mode, + } + if ($source == undef) { + File[$filename] { + content => $content, + } + } else { + File[$filename] { + source => $source, + } + } +} diff --git a/modules/mga_common/manifests/var/perl.pp b/modules/mga_common/manifests/var/perl.pp new file mode 100644 index 00000000..47ff54be --- /dev/null +++ b/modules/mga_common/manifests/var/perl.pp @@ -0,0 +1,3 @@ +class mga_common::var::perl( + $site_perl_dir = '/usr/lib/perl5/site_perl' +) {} diff --git a/modules/mgapeople/manifests/init.pp b/modules/mgapeople/manifests/init.pp new file mode 100644 index 00000000..7c40ab9c --- /dev/null +++ b/modules/mgapeople/manifests/init.pp @@ -0,0 +1,77 @@ +class mgapeople( + $site_name = "people.${::domain}", + $groupbase = 'ou=Group,dc=mageia,dc=org', + $maintdburl = undef, + $ldap_server, + $binddn, + $bindpw, + $vhost, + $vhostdir +){ + $mgapeople_login = 'mgapeople' + $bindpw_file = '/etc/mgapeople.ldapsecret' + + group { $mgapeople_login: + ensure => present, + } + + user { $mgapeople_login: + ensure => present, + comment => 'mgapeople user', + home => "/var/lib/${mgapeople_login}", + managehome => true, + gid => $mgapeople_login, + } + + file { $bindpw_file: + ensure => present, + owner => $mgapeople_login, + group => $mgapeople_login, + mode => '0600', + content => $bindpw, + } + + package { 'mgapeople': + ensure => installed, + } + + file {'/etc/mgapeople.conf': + ensure => present, + owner => root, + group => root, + mode => '0644', + content => template('mgapeople/mgapeople.conf'), + require => Package['mgapeople'], + } + + file { $vhostdir: + ensure => directory, + owner => $mgapeople_login, + group => $mgapeople_login, + mode => '0755', + } + + $vhost_aliases = { + '/static' => '/usr/share/mgapeople/static', + } + apache::vhost::base { $vhost: + location => $vhostdir, + require => File[$vhostdir], + aliases => $vhost_aliases, + } + apache::vhost::base { "ssl_${vhost}": + vhost => $vhost, + use_ssl => true, + location => $vhostdir, + require => File[$vhostdir], + aliases => $vhost_aliases, + } + + cron { '/usr/bin/mkpeople': + command => '/usr/bin/mkpeople', + user => $mgapeople_login, + hour => '*/2', + minute => '10', + } +} +# vim: sw=2 diff --git a/modules/mgapeople/templates/mgapeople.conf b/modules/mgapeople/templates/mgapeople.conf new file mode 100644 index 00000000..5bc7b21b --- /dev/null +++ b/modules/mgapeople/templates/mgapeople.conf @@ -0,0 +1,17 @@ +ldapserver: <%= @ldap_server %> +binddn: <%= @binddn %> +bindpwfile: <%= @bindpw_file %> +groupbase: <%= @groupbase %> +output_dir: <%= @vhostdir %> +output_format: + - html + - txt +tmpl_dir: /usr/share/mgapeople/tmpl +<%- if @maintdburl -%> +maintdburl: <%= @maintdburl %> +<%- end -%> +sitename: <%= @site_name %> +staticdir_url: //people.mageia.org/static +links_protocol: https:// +package_url: https://svnweb.mageia.org/packages/cauldron/ +package_url_suffix: /current/ diff --git a/modules/mgasoft/manifests/init.pp b/modules/mgasoft/manifests/init.pp index 68c54ba7..70431701 100644 --- a/modules/mgasoft/manifests/init.pp +++ b/modules/mgasoft/manifests/init.pp @@ -1,5 +1,5 @@ class mgasoft( - $anonsvn_soft = 'svn://svn.mageia.org/svn/soft', + $anonsvn_soft = "svn://svn.${::domain}/svn/soft", $pubinfodir = '/var/lib/mgasoft/infos', $pubmirrordir = '/distrib/mirror/software', $svn_soft_publish = 'file:///svn/soft_publish', @@ -8,9 +8,8 @@ class mgasoft( group { $mgasoft_login: } user { $mgasoft_login: - comment => 'System user to publish software', managehome => true, - home => "/var/lib/$mgasoft_login", + home => "/var/lib/${mgasoft_login}", gid => $mgasoft_login, require => Group[$mgasoft_login], } diff --git a/modules/mgasoft/templates/mgasoft.conf b/modules/mgasoft/templates/mgasoft.conf index eaf6e416..81cce013 100644 --- a/modules/mgasoft/templates/mgasoft.conf +++ b/modules/mgasoft/templates/mgasoft.conf @@ -1,5 +1,5 @@ svn_soft=svn+ssh://svn.mageia.org/svn/soft -anonsvn_soft=<%= anonsvn_soft %> -svn_soft_publish=<%= svn_soft_publish %> -pubinfodir=<%= pubinfodir %> -pubmirrordir=<%= pubmirrordir %> +anonsvn_soft=<%= @anonsvn_soft %> +svn_soft_publish=<%= @svn_soft_publish %> +pubinfodir=<%= @pubinfodir %> +pubmirrordir=<%= @pubmirrordir %> diff --git a/modules/mirror/manifests/base.pp b/modules/mirror/manifests/base.pp index 7470547d..db48f808 100644 --- a/modules/mirror/manifests/base.pp +++ b/modules/mirror/manifests/base.pp @@ -10,7 +10,6 @@ class mirror::base { group { 'mirror': } user { 'mirror': - comment => 'System user use to run mirror scripts', gid => 'mirror', } } diff --git a/modules/mirror/manifests/mageia.pp b/modules/mirror/manifests/mageia.pp index 4b39ccb8..c14a09bb 100644 --- a/modules/mirror/manifests/mageia.pp +++ b/modules/mirror/manifests/mageia.pp @@ -1,7 +1,7 @@ class mirror::mageia { include mirror::base mirrordir { 'mageia': - remoteurl => "rsync://rsync.$::domain/mageia", + remoteurl => "rsync://rsync.${::domain}/mageia", localdir => '/distrib/mageia', } } diff --git a/modules/mirror/manifests/main.pp b/modules/mirror/manifests/main.pp index 2fef6800..f368038d 100644 --- a/modules/mirror/manifests/main.pp +++ b/modules/mirror/manifests/main.pp @@ -1,7 +1,7 @@ # For main Mageia mirror class mirror::main { include mirror::base - mga-common::local_script { 'update_timestamp': + mga_common::local_script { 'update_timestamp': content => template('mirror/update_timestamp') } @@ -9,6 +9,6 @@ class mirror::main { user => 'mirror', minute => '*/10', command => '/usr/local/bin/update_timestamp', - require => [Local_script['update_timestamp'], User['mirror']], + require => [Mga_common::Local_script['update_timestamp'], User['mirror']], } } diff --git a/modules/mirror/manifests/mirrordir.pp b/modules/mirror/manifests/mirrordir.pp index 49367116..2100bc6c 100644 --- a/modules/mirror/manifests/mirrordir.pp +++ b/modules/mirror/manifests/mirrordir.pp @@ -2,7 +2,7 @@ define mirror::mirrordir ($remoteurl, $localdir, $rsync_options='-avH --delete') { include mirror::base - $lockfile = "$mirror::base::locksdir/$name" + $lockfile = "${mirror::base::locksdir}/${name}" file { $localdir: ensure => directory, @@ -10,14 +10,14 @@ define mirror::mirrordir ($remoteurl, group => 'mirror', } - mga-common::local_script { "mirror_$name": + mga_common::local_script { "mirror_${name}": content => template('mirror/mirrordir'), } - cron { "mirror_$name": + cron { "mirror_${name}": user => mirror, minute => '*/10', - command => "/usr/local/bin/mirror_$name", - require => Local_script["mirror_$name"], + command => "/usr/local/bin/mirror_${name}", + require => Mga_common::Local_script["mirror_${name}"], } } diff --git a/modules/mirror/templates/mirrordir b/modules/mirror/templates/mirrordir index 53655aa0..9cf09650 100644 --- a/modules/mirror/templates/mirrordir +++ b/modules/mirror/templates/mirrordir @@ -1,9 +1,9 @@ #!/bin/sh -remoteurl="<%= remoteurl%>" -localdir="<%= localdir %>" -rsync_options="<%= rsync_options %>" -lockfile="<%= lockfile %>" +remoteurl="<%= @remoteurl%>" +localdir="<%= @localdir %>" +rsync_options="<%= @rsync_options %>" +lockfile="<%= @lockfile %>" if [ -f "$lockfile" ]; then # show error message when run from command line @@ -13,4 +13,3 @@ fi echo "sync in progress since $(date)" > "$lockfile" /usr/bin/rsync $rsync_options "$remoteurl" "$localdir" rm -f "$lockfile" - diff --git a/modules/mirror/templates/update_timestamp b/modules/mirror/templates/update_timestamp index a037d10d..1f7711c6 100644 --- a/modules/mirror/templates/update_timestamp +++ b/modules/mirror/templates/update_timestamp @@ -2,4 +2,4 @@ # $id$ -date +%s%n%c > /distrib/mirror/mageia_timestamp +LC_ALL=C.UTF-8 date -u '+%s%n%c %Z' > /distrib/mirror/mageia_timestamp diff --git a/modules/mirror_cleaner/files/orphans_cleaner.pl b/modules/mirror_cleaner/files/orphans_cleaner.pl index f1af3dee..73e08912 100755 --- a/modules/mirror_cleaner/files/orphans_cleaner.pl +++ b/modules/mirror_cleaner/files/orphans_cleaner.pl @@ -10,7 +10,7 @@ use File::Basename; use File::Copy; use File::Path qw(make_path); -my @arches = ('i586','x86_64'); +my @arches = ('i586','x86_64', 'aarch64'); my @sections = ('core','nonfree','tainted'); my @medias = ('backports', 'backports_testing', 'release', 'updates', 'updates_testing'); my $move_delay = 60*60*24*14; @@ -34,11 +34,11 @@ foreach my $a ( @arches ) { $binary_hdlist = "$rpm_path/media_info/hdlist.cz"; $source_hdlist = "$srpm_path/media_info/hdlist.cz"; - next if not -f $source_hdlist; - next if not -f $binary_hdlist; + next if not -f $source_hdlist; + next if not -f $binary_hdlist; - next if stat($source_hdlist)->size() <= 64; - next if stat($binary_hdlist)->size() <= 64; + next if stat($source_hdlist)->size() <= 64; + next if stat($binary_hdlist)->size() <= 64; open(my $hdfh, "zcat '$binary_hdlist' 2>/dev/null |") or die "Can't open $_"; while (my $hdr = stream2header($hdfh)) { @@ -60,15 +60,15 @@ foreach my $a ( @arches ) { # Be safe, maybe hdlists were not in sync next if -f "$srpm_path/$s"; foreach my $rpm ( @{$hash{$s}} ) { - $rpm = "$rpm_path/$rpm"; - # sometimes, packages are removed without hdlist to be updated - next if not -f "$rpm"; - if (time() > $move_delay + stat("$rpm")->ctime()) { - ( $dest_rpm = $rpm ) =~ s/$path/$dest_path/; - my $dir = dirname $dest_rpm; - make_path $dir if not -d $dir; - move($rpm, $dest_rpm) - } + $rpm = "$rpm_path/$rpm"; + # sometimes, packages are removed without hdlist to be updated + next if not -f "$rpm"; + if (time() > $move_delay + stat("$rpm")->ctime()) { + ( $dest_rpm = $rpm ) =~ s/$path/$dest_path/; + my $dir = dirname $dest_rpm; + make_path $dir if not -d $dir; + move($rpm, $dest_rpm) + } } } } diff --git a/modules/mirror_cleaner/manifests/orphans.pp b/modules/mirror_cleaner/manifests/orphans.pp index 135fc822..90be9a8c 100644 --- a/modules/mirror_cleaner/manifests/orphans.pp +++ b/modules/mirror_cleaner/manifests/orphans.pp @@ -7,12 +7,16 @@ define mirror_cleaner::orphans($base) { ensure => directory } - cron { "clean orphans $name": - command => "/usr/local/bin/orphans_cleaner.pl $base/$name $orphan_dir", - hour => 5, - minute => 30, - user => root, - } +# Disable cleaning as the ruby version is smarter and this one tends to break things +# It should probably be deleted +# +# cron { "clean orphans ${name}": +# command => "/usr/local/bin/orphans_cleaner.pl ${base}/${name} ${orphan_dir}", +# hour => 5, +# minute => 30, +# weekday => 1, +# user => root, +# } tidy { $orphan_dir: type => 'ctime', diff --git a/modules/mirrorbrain/manifests/init.pp b/modules/mirrorbrain/manifests/init.pp new file mode 100644 index 00000000..f7f74ead --- /dev/null +++ b/modules/mirrorbrain/manifests/init.pp @@ -0,0 +1,154 @@ +class mirrorbrain { + + $mb_user = 'mirrorbrain' + $mb_home = "/var/lib/${mb_user}" + $mb_repo = "${mb_home}/mirror" + $mb_vhost = "dl.${::domain}" + + $mb_pgsql_pw = extlookup('mirrorbrain_pgsql','x') + + group { $mb_user: + ensure => present + } + + user { $mb_user: + ensure => present, + home => $mb_home + } + + file { $mb_home: + ensure => directory, + owner => $mb_user, + group => $mb_user, + mode => '0751' + } + + file { $mb_repo: + ensure => directory, + owner => $mb_user, + group => $mb_user, + mode => '0755' + } + + package {['mirrorbrain', + 'mirrorbrain-scanner', + 'mirrorbrain-tools', + 'apache-mod_mirrorbrain', + 'apache-mod_dbd']: } + + + postgresql::remote_db_and_user { 'mirrorbrain': + description => 'Mirrorbrain database', + password => $mb_pgsql_pw, + } + + file { '/etc/httpd/conf/geoip.conf': + owner => 'root', + group => 'root', + mode => '0644', + content => template('mirrorbrain/geoip.conf') + } + + file { '/etc/httpd/conf/modules.d/11-mirrorbrain.conf': + owner => 'root', + group => 'root', + mode => '0644', + content => template('mirrorbrain/mod_mirrorbrain.conf') + } + + file { '/etc/mirrorbrain.conf': + owner => 'root', + group => "$mb_user", + mode => '0640', + content => template('mirrorbrain/mirrorbrain.conf') + } + + apache::vhost::base { "${mb_vhost}": + vhost => "${mb_vhost}", + location => "${mb_repo}" + } + + apache::vhost::base { "ssl_${mb_vhost}": + vhost => "${mb_vhost}", + use_ssl => true, + location => "${mb_repo}" + } + + apache::webapp_other { 'mirrorbrain': + webapp_file => 'mirrorbrain/webapp.conf', + } + + # Update GeoIP db + cron { 'MirrorBrain: weekly GeoIP update': + command => 'sleep $(($RANDOM/1024)); /usr/bin/geoip-lite-update', + user => 'root', + minute => 30, + hour => 3, + weekday => 0 + } + + # distrib tree + # mga 1-4 are frozen, so only one manual run has been done + # distrib/5 still active + cron { 'MirrorBrain: Sync Mga 5 every 4 hours ': + command => "/usr/bin/null-rsync rsync.mageia.org::mageia/distrib/5 ${mb_repo}/distrib/", + user => "$mb_user", + minute => '15', + hour => '*/4', + } + + # distrib/cauldron + cron { 'MirrorBrain: Sync Cauldron every 1 hours ': + command => "/usr/bin/null-rsync rsync.mageia.org::mageia/distrib/cauldron ${mb_repo}/distrib/", + user => "$mb_user", + minute => '0', + hour => '*/1', + } + + # iso tree + cron { 'MirrorBrain: Sync iso tree every 1 day ': + command => "/usr/bin/null-rsync rsync.mageia.org::mageia/iso ${mb_repo}/", + user => "$mb_user", + hour => '2', + minute => '30', + } + + # people tree + cron { 'MirrorBrain: Sync people tree every 1 day ': + command => "/usr/bin/null-rsync rsync.mageia.org::mageia/people ${mb_repo}/", + user => "$mb_user", + hour => '3', + minute => '45', + } + + # software tree + cron { 'MirrorBrain: Sync software tree every 1 day ': + command => "/usr/bin/null-rsync rsync.mageia.org::mageia/software ${mb_repo}/", + user => "$mb_user", + hour => '4', + minute => '45', + } + + # Mirror online check + cron { 'MirrorBrain: mirror online status check every 5 minute': + command => '/usr/bin/mirrorprobe', + user => "$mb_user", + minute => 5 + } + + # Mirror scanning + cron { 'MirrorBrain: mirror scanning every 30 minute': + command => '/usr/bin/mb scan --quiet --jobs 4 --all', + user => "$mb_user", + minute => 30 + } + + # Mirror database cleanup + cron { 'MirrorBrain: mirror database cleanup every 1 week': + command => '/usr/bin/mb db vacuum', + user => "$mb_user", + minute => 45, + hour => 5, + weekday => 1 + } +} diff --git a/modules/mirrorbrain/templates/geoip.conf b/modules/mirrorbrain/templates/geoip.conf new file mode 100644 index 00000000..1f71a67d --- /dev/null +++ b/modules/mirrorbrain/templates/geoip.conf @@ -0,0 +1,5 @@ +<IfModule mod_geoip.c> + GeoIPEnable On + GeoIPDBFile /var/lib/GeoIP/GeoLiteCity.dat.updated + GeoIPOutput Env +</IfModule> diff --git a/modules/mirrorbrain/templates/mirrorbrain.conf b/modules/mirrorbrain/templates/mirrorbrain.conf new file mode 100644 index 00000000..94bef340 --- /dev/null +++ b/modules/mirrorbrain/templates/mirrorbrain.conf @@ -0,0 +1,14 @@ +[general] +instances = main + +[main] +dbuser = mirrorbrain +dbpass = <%= @mb_pgsql_pw %> +dbdriver = postgresql +dbhost = pgsql.<%= @domain %> +# optional: dbport = ... +dbname = mirrorbrain + +[mirrorprobe] +# logfile = /var/log/mirrorbrain/mirrorprobe.log +# loglevel = INFO diff --git a/modules/mirrorbrain/templates/mod_mirrorbrain.conf b/modules/mirrorbrain/templates/mod_mirrorbrain.conf new file mode 100644 index 00000000..9b67d7fe --- /dev/null +++ b/modules/mirrorbrain/templates/mod_mirrorbrain.conf @@ -0,0 +1,3 @@ +LoadModule form_module modules/mod_form.so +LoadModule mirrorbrain_module modules/mod_mirrorbrain.so + diff --git a/modules/mirrorbrain/templates/webapp.conf b/modules/mirrorbrain/templates/webapp.conf new file mode 100644 index 00000000..9606be64 --- /dev/null +++ b/modules/mirrorbrain/templates/webapp.conf @@ -0,0 +1,16 @@ +<Directory /var/lib/mirrorbrain/mirror> + MirrorBrainEngine On + MirrorBrainDebug Off + FormGET On + MirrorBrainHandleHEADRequestLocally Off + MirrorBrainFallback na us https://mirrors.kernel.org/mageia/ + MirrorBrainFallback eu fr http://ftp.free.fr/mirrors/mageia.org/ + MirrorBrainFallback eu se https://ftp.acc.umu.se/mirror/mageia/ + MirrorBrainMinSize 0 + #MirrorBrainExcludeUserAgent rpm/4.4.2* + #MirrorBrainExcludeUserAgent *APT-HTTP* + #MirrorBrainExcludeMimeType application/pgp-keys + DirectoryIndex disable + Options +FollowSymLinks +Indexes + Require all granted +</Directory> diff --git a/modules/mysql/manifests/init.pp b/modules/mysql/manifests/init.pp index 28a5109f..1d180778 100644 --- a/modules/mysql/manifests/init.pp +++ b/modules/mysql/manifests/init.pp @@ -1,23 +1,24 @@ class mysql { class server { - package { "mysql": } + package {['mariadb', + 'mariadb-obsolete']: } - service { mysqld: - alias => mysql, - subscribe => Package['mysql'], + service { 'mysqld': + alias => mysql, + subscribe => Package['mariadb'], } - + # file { "/etc/my.cnf": -# +# # } } - - define database() { - exec { "mysqladmin create $name": - user => root, - # not sure if /dev/null is needed - unless => "mysqlshow $name" - } + + define database() { + exec { "mysqladmin create ${name}": + user => root, + # not sure if /dev/null is needed + unless => "mysqlshow ${name}" + } } # define user($password) { # diff --git a/modules/ntp/manifests/init.pp b/modules/ntp/manifests/init.pp index a647925f..f75310e7 100644 --- a/modules/ntp/manifests/init.pp +++ b/modules/ntp/manifests/init.pp @@ -1,12 +1,17 @@ class ntp { - package { 'ntp': } +if versioncmp($::lsbdistrelease, '9') < 0 { + $ntppkg = 'ntp' +} else { + $ntppkg = 'ntpsec' +} + package { $ntppkg: } service { 'ntpd': - subscribe => [Package['ntp'], File['/etc/ntp.conf']], + subscribe => [Package[$ntppkg], File['/etc/ntp.conf']], } file { '/etc/ntp.conf': - require => Package['ntp'], + require => Package[$ntppkg], content => template('ntp/ntp.conf'), } } diff --git a/modules/ntp/templates/ntp.conf b/modules/ntp/templates/ntp.conf index 3f9582d7..72f233c0 100644 --- a/modules/ntp/templates/ntp.conf +++ b/modules/ntp/templates/ntp.conf @@ -25,6 +25,12 @@ driftfile /var/lib/ntp/drift multicastclient # listen on default 224.0.1.1 broadcastdelay 0.008 +# https://www.kb.cert.org/vuls/id/348126 +restrict default nomodify notrap nopeer noquery +restrict -6 default nomodify notrap nopeer noquery +# https://isc.sans.edu/forums/diary/NTP+reflection+attack/17300 +disable monitor + # # Keys file. If you want to diddle your server at run time, make a # keys file (mode 600 for sure) and define the key number to be diff --git a/modules/opendkim/Gemfile b/modules/opendkim/Gemfile new file mode 100644 index 00000000..68ba397d --- /dev/null +++ b/modules/opendkim/Gemfile @@ -0,0 +1,19 @@ +source 'https://rubygems.org' + +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3'] +gem 'puppet', puppetversion +gem 'puppetlabs_spec_helper', '>= 0.1.0' +gem 'facter', '>= 1.7.0' + +gem 'puppet-lint', '>= 0.3.2' +gem 'rspec-puppet' +gem "metadata-json-lint" +gem 'beaker-rspec' +gem "travis" +gem "travis-lint" +gem "puppet-blacksmith" +gem "guard-rake" + +gem 'test-kitchen', '>= 1.4.0' +gem 'kitchen-docker', '>= 2.1.0' +gem 'kitchen-puppet', '>= 0.0.27' diff --git a/modules/opendkim/LICENSE b/modules/opendkim/LICENSE new file mode 100644 index 00000000..8f71f43f --- /dev/null +++ b/modules/opendkim/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/modules/opendkim/Modulefile b/modules/opendkim/Modulefile new file mode 100644 index 00000000..7790c510 --- /dev/null +++ b/modules/opendkim/Modulefile @@ -0,0 +1,8 @@ + name "bi4o4ek-opendkim" + version "0.0.7" + author "Vladimir Bykanov" + summary "Configures OpenDKIM" + license "Apache-2.0" + source "https://github.com/bi4o4ek/puppet-opendkim" + project_page "https://github.com/bi4o4ek/puppet-opendkim" + diff --git a/modules/opendkim/Puppetfile b/modules/opendkim/Puppetfile new file mode 100644 index 00000000..177adf16 --- /dev/null +++ b/modules/opendkim/Puppetfile @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +#^syntax detection + +forge "https://forgeapi.puppetlabs.com" + +# use dependencies defined in metadata.json +metadata diff --git a/modules/opendkim/README.md b/modules/opendkim/README.md new file mode 100644 index 00000000..13c40bde --- /dev/null +++ b/modules/opendkim/README.md @@ -0,0 +1,98 @@ +[](https://travis-ci.org/bi4o4ek/puppet-opendkim) + +# opendkim + +#### Table of Contents + +1. [Overview](#overview) +2. [Module Description](#module-description) +3. [Setup - The basics of getting started with opendkim](#setup) + * [Beginning with opendkim](#beginning-with-opendkim) + * [Add domains for signing](#add-domains-for-signing) + * [Add allowed hosts](#add-allowed-hosts) +4. [Usage - Configuration options and additional functionality](#usage) +5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [Development - Guide for contributing to the module](#development) + +## Overview + +The opendkim module allows you to set up mail signing and manage DKIM services with minimal effort. + +## Module Description + +OpenDKIM is a widely-used DKIM service, and this module provides a simplified way of creating configurations to manage your infrastructure. +This includes the ability to configure and manage a range of different domain, as well as a streamlined way to install and configure OpenDKIM service. + +## Setup + +### What opendkim affects + +* configuration files and directories (created and written to) +* package/service/configuration files for OpenDKIM +* signing domains list +* trusted hosts list + +### Beginning with opendkim + +To install OpenDKIM with the default parameters + + include opendkim + +### Add domains for signing + + opendkim::domain{['example.com', 'example.org']:} + + +### Add allowed hosts + + opendkim::trusted{['10.0.0.0/8', '203.0.113.0/24']:} + +## Usage + +For example. +There is internal ip 10.3.3.80 and external ip 203.0.113.100 on our mail-relay host with OpenDKIM. +This host signs all mails for domains example.com and example.org. + + # Postfix-relay + class{ 'postfix::server': + inet_interfaces => '10.3.3.80, localhost', + mynetworks => '10.0.0.0/8, 203.0.113.0/24', + smtpd_recipient_restrictions => 'permit_mynetworks, reject_unauth_destination', + smtpd_client_restrictions => 'permit_mynetworks, reject', + mydestination => '$myhostname', + myhostname => 'relay-site.example.com', + smtpd_banner => 'Hello', + extra_main_parameters => { + smtp_bind_address => '203.0.113.100', + smtpd_milters => 'inet:127.0.0.1:8891', + non_smtpd_milters => '$smtpd_milters', + milter_default_action => 'accept', + milter_protocol => '2', + }, + } + + # OpenDKIM + include opendkim + opendkim::domain{['example.com', 'example.org']:} + opendkim::trusted{['10.0.0.0/8', '203.0.113.0/24']:} + +After puppet-run you need to copy contents of /etc/opendkim/keys/example.com/relay-site.txt and paste into corresponding DNS-zone as TXT. +Then repeat this action for example.org + +Puppet module for postfix in this example is [thias/postfix](https://forge.puppetlabs.com/thias/postfix) v0.3.3 +## Reference + +Puppetlabs are working on automating this section. + +## Limitations + +This module is tested on: +* CentOS 6 +* Ubuntu 12.04 +* Ubuntu 14.04 + +## Development + +Fork me on github and make pull request. + diff --git a/modules/opendkim/Rakefile b/modules/opendkim/Rakefile new file mode 100644 index 00000000..312b2952 --- /dev/null +++ b/modules/opendkim/Rakefile @@ -0,0 +1,12 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' + +PuppetLint.configuration.fail_on_warnings = true +PuppetLint.configuration.send('relative') +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send('disable_class_inherits_from_params_class') +PuppetLint.configuration.send('disable_documentation') +PuppetLint.configuration.send('disable_single_quote_string_with_variables') +PuppetLint.configuration.send('disable_only_variable_string') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] diff --git a/modules/opendkim/manifests/domain.pp b/modules/opendkim/manifests/domain.pp new file mode 100644 index 00000000..c708ad08 --- /dev/null +++ b/modules/opendkim/manifests/domain.pp @@ -0,0 +1,46 @@ +define opendkim::domain ( + $domain = $name, + $selector = $hostname, + $pathkeys = '/etc/opendkim/keys', + $keytable = 'KeyTable', + $signing_table = 'SigningTable', +) { + # $pathConf and $pathKeys must be without trailing '/'. + # For example, '/etc/opendkim/keys' + + Exec { path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/' ] } + + # Create directory for domain + file { "${pathkeys}/${domain}": + ensure => directory, + owner => $opendkim::owner, + group => $opendkim::group, + mode => '0755', + notify => Service[$opendkim::service_name], + require => Package[$opendkim::package_name], + } + + # Generate dkim-keys + exec { "opendkim-genkey -D ${pathkeys}/${domain}/ -d ${domain} -s ${selector}": + unless => "/usr/bin/test -f ${pathkeys}/${domain}/${selector}.private && /usr/bin/test -f ${pathkeys}/${domain}/${selector}.txt", + user => $opendkim::owner, + notify => Service[$opendkim::service_name], + require => [ Package[$opendkim::package_name], File["${pathkeys}/${domain}"], ], + } + + # Add line into KeyTable + file_line { "${opendkim::pathconf}/${keytable}_${domain}": + path => "${opendkim::pathconf}/${keytable}", + line => "${selector}._domainkey.${domain} ${domain}:${selector}:${pathkeys}/${domain}/${selector}.private", + notify => Service[$opendkim::service_name], + require => Package[$opendkim::package_name], + } + + # Add line into SigningTable + file_line { "${opendkim::pathconf}/${signing_table}_${domain}": + path => "${opendkim::pathconf}/${signing_table}", + line => "*@${domain} ${selector}._domainkey.${domain}", + notify => Service[$opendkim::service_name], + require => Package[$opendkim::package_name], + } +} diff --git a/modules/opendkim/manifests/init.pp b/modules/opendkim/manifests/init.pp new file mode 100644 index 00000000..6e45345a --- /dev/null +++ b/modules/opendkim/manifests/init.pp @@ -0,0 +1,105 @@ +# == Class: opendkim +# +# === Examples +# +# class { 'opendkim':} +# +# === Authors +# +# Vladimir Bykanov <vladimir@bykanov.ru> +# +# === Copyright +# +# Copyright 2015 Vladimir Bykanov +# +class opendkim ( + $autorestart = 'Yes', + $autorestart_rate = '10/1h', + $log_why = 'Yes', + $syslog = 'Yes', + $syslog_success = 'Yes', + $mode = 's', + $canonicalization = 'relaxed/simple', + $external_ignore_list = 'refile:/etc/opendkim/TrustedHosts', + $internal_hosts = 'refile:/etc/opendkim/TrustedHosts', + $keytable = 'refile:/etc/opendkim/KeyTable', + $signing_table = 'refile:/etc/opendkim/SigningTable', + $signature_algorithm = 'rsa-sha256', + $socket = 'inet:8891@localhost', + $pidfile = '/var/run/opendkim/opendkim.pid', + $umask = '022', + $userid = 'opendkim:opendkim', + $temporary_directory = '/var/tmp', + $package_name = 'opendkim', + $service_name = 'opendkim', + $pathconf = '/etc/opendkim', + $owner = 'opendkim', + $group = 'opendkim', +) { + + package { $package_name: + ensure => present, + } + + case $::operatingsystem { + /^(Debian|Ubuntu)$/: { + package { 'opendkim-tools': + ensure => present, + } + # Debian/Ubuntu doesn't ship this directory in its package + file { $pathconf: + ensure => directory, + owner => 'root', + group => 'opendkim', + mode => '0755', + require => Package[$package_name], + } + file { "${pathconf}/keys": + ensure => directory, + owner => 'opendkim', + group => 'opendkim', + mode => '0750', + require => Package[$package_name], + } + file { "${pathconf}/KeyTable": + ensure => present, + owner => 'opendkim', + group => 'opendkim', + mode => '0640', + require => Package[$package_name], + } + file { "${pathconf}/SigningTable": + ensure => present, + owner => 'opendkim', + group => 'opendkim', + mode => '0640', + require => Package[$package_name], + } + file { "${pathconf}/TrustedHosts": + ensure => present, + owner => 'opendkim', + group => 'opendkim', + mode => '0644', + require => Package[$package_name], + } + } + default: {} + } + + file {'/etc/opendkim.conf': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('opendkim/opendkim.conf'), + notify => Service[$service_name], + require => Package[$package_name], + } + + service { $service_name: + ensure => running, + enable => true, + require => Package[$package_name], + } +} + diff --git a/modules/opendkim/manifests/trusted.pp b/modules/opendkim/manifests/trusted.pp new file mode 100644 index 00000000..dcf0f8b8 --- /dev/null +++ b/modules/opendkim/manifests/trusted.pp @@ -0,0 +1,13 @@ +define opendkim::trusted ( + $host = $name, + $trusted_hosts = 'TrustedHosts', + +) { + # Add line into KeyTable + file_line { "${opendkim::pathconf}/${trusted_hosts}_${host}": + path => "${opendkim::pathconf}/${trusted_hosts}", + line => $host, + notify => Service[$opendkim::service_name], + require => Package[$opendkim::package_name], + } +} diff --git a/modules/opendkim/metadata.json b/modules/opendkim/metadata.json new file mode 100644 index 00000000..81b2f70d --- /dev/null +++ b/modules/opendkim/metadata.json @@ -0,0 +1,60 @@ +{ + "name": "bi4o4ek-opendkim", + "version": "0.0.7", + "author": "Vladimir Bykanov", + "summary": "Configures OpenDKIM", + "license": "Apache-2.0", + "source": "https://github.com/bi4o4ek/puppet-opendkim", + "project_page": "https://github.com/bi4o4ek/puppet-opendkim", + "issues_url": "https://github.com/bi4o4ek/puppet-opendkim/issues", + "operatingsystem_support": [ + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "Mageia", + "operatingsystemrelease": [ + "7", + "8", + "9" + ] + } + ], + "dependencies": [ + { + } + ], + "description": "UNKNOWN", + "types": [ + + ], + "checksums": { + "Gemfile": "19456e851851a3bd7aa6729108429dde", + "LICENSE": "fa818a259cbed7ce8bc2a22d35a464fc", + "Modulefile": "9a3b46c73c1ae7309fe2d35c5e6fa549", + "Puppetfile": "607001b25e4f9d020b2ce4444174a654", + "README.md": "0764cc9bb9de221c97bce2664ba99657", + "Rakefile": "a162d9397ed53fa8fa49c57609feedcb", + "manifests/domain.pp": "61f78cbd4376e58a7b26f1298f38804b", + "manifests/init.pp": "4987dcd9ebc88e7ea0de3b74c9af6d9c", + "manifests/trusted.pp": "bcc132622e2c2e39bcbc3116c7788c8b", + "spec/classes/init_spec.rb": "0451831b29191c21b2cdc045c94a2243", + "spec/classes/opendkim_spec.rb": "9f06a3f005344875a0fb5753ab43cb34", + "spec/spec_helper.rb": "0db89c9a486df193c0e40095422e19dc", + "templates/opendkim.conf": "047e76e4c2a0a15754101f2da32ab2fe", + "tests/init.pp": "8c9ab8c85cd89dae1ad97cbe949a7e6e" + } +} diff --git a/modules/opendkim/spec/classes/init_spec.rb b/modules/opendkim/spec/classes/init_spec.rb new file mode 100644 index 00000000..5ce0a75d --- /dev/null +++ b/modules/opendkim/spec/classes/init_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' +describe 'opendkim' do + + context 'with defaults for all parameters' do + it { should contain_class('opendkim') } + end +end diff --git a/modules/opendkim/spec/classes/opendkim_spec.rb b/modules/opendkim/spec/classes/opendkim_spec.rb new file mode 100644 index 00000000..1901c1c0 --- /dev/null +++ b/modules/opendkim/spec/classes/opendkim_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe 'opendkim', :type => :class do + + describe "Opendkim class with no parameters, basic test" do + let(:params) { { } } + + it { + should contain_package('opendkim') + should contain_service('opendkim') + } + end +end diff --git a/modules/opendkim/spec/spec_helper.rb b/modules/opendkim/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/modules/opendkim/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/modules/opendkim/templates/opendkim.conf b/modules/opendkim/templates/opendkim.conf new file mode 100644 index 00000000..5dc61aa6 --- /dev/null +++ b/modules/opendkim/templates/opendkim.conf @@ -0,0 +1,52 @@ +<%- if @autorestart -%> +AutoRestart <%= @autorestart %> +<%- end -%> +<%- if @autorestart_rate -%> +AutoRestartRate <%= @autorestart_rate %> +<%- end -%> +<%- if @log_why -%> +LogWhy <%= @log_why %> +<%- end -%> +<%- if @syslog -%> +Syslog <%= @syslog %> +<%- end -%> +<%- if @syslog_success -%> +SyslogSuccess <%= @syslog_success %> +<%- end -%> +<%- if @mode -%> +Mode <%= @mode %> +<%- end -%> +<%- if @canonicalization -%> +Canonicalization <%= @canonicalization %> +<%- end -%> +<%- if @external_ignore_list -%> +ExternalIgnoreList <%= @external_ignore_list %> +<%- end -%> +<%- if @internal_hosts -%> +InternalHosts <%= @internal_hosts %> +<%- end -%> +<%- if @keytable -%> +KeyTable <%= @keytable %> +<%- end -%> +<%- if @signing_table -%> +SigningTable <%= @signing_table %> +<%- end -%> +<%- if @signature_algorithm -%> +SignatureAlgorithm <%= @signature_algorithm %> +<%- end -%> +<%- if @socket -%> +Socket <%= @socket %> +<%- end -%> +<%- if @pidfile -%> +PidFile <%= @pidfile %> +<%- end -%> +<%- if @umask -%> +UMask <%= @umask %> +<%- end -%> +<%- if @userid -%> +UserID <%= @userid %> +<%- end -%> +<%- if @temporary_directory -%> +TemporaryDirectory <%= @temporary_directory %> +<%- end -%> + diff --git a/modules/opendkim/tests/init.pp b/modules/opendkim/tests/init.pp new file mode 100644 index 00000000..ff3d3b06 --- /dev/null +++ b/modules/opendkim/tests/init.pp @@ -0,0 +1,15 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +Class['epel'] -> Class['opendkim'] + +include epel +include opendkim diff --git a/modules/openldap/lib/puppet/parser/functions/get_ldap_servers.rb b/modules/openldap/lib/puppet/parser/functions/get_ldap_servers.rb index 204da558..0d620926 100644 --- a/modules/openldap/lib/puppet/parser/functions/get_ldap_servers.rb +++ b/modules/openldap/lib/puppet/parser/functions/get_ldap_servers.rb @@ -1,11 +1,11 @@ # return a list of all ldap servers declared module Puppet::Parser::Functions - newfunction(:get_ldap_servers, :type => :rvalue) do |args| + newfunction(:get_ldap_servers, :type => :rvalue) do |args| Puppet::Parser::Functions.autoloader.loadall res = ["master"] - - function_list_exported_ressources(['Openldap::Exported_slave']).each { |i| - res << "slave-#{i}" + + function_list_exported_ressources(['Openldap::Exported_slave']).each { |i| + res << "slave-#{i}" } res.map! { |x| "ldap-#{x}." + lookupvar("domain") } return res diff --git a/modules/openldap/manifests/config.pp b/modules/openldap/manifests/config.pp index 6f364ffc..336f8a23 100644 --- a/modules/openldap/manifests/config.pp +++ b/modules/openldap/manifests/config.pp @@ -2,6 +2,6 @@ define openldap::config($content) { file { $name: require => Package['openldap-servers'], content => $content, - notify => Exec['/etc/init.d/ldap check'], + notify => Exec["slaptest"], } } diff --git a/modules/openldap/manifests/init.pp b/modules/openldap/manifests/init.pp index 35455d1a..34a214a2 100644 --- a/modules/openldap/manifests/init.pp +++ b/modules/openldap/manifests/init.pp @@ -1,21 +1,23 @@ class openldap { + include openldap::var + package { 'openldap-servers': } - service { 'ldap': + service { $openldap::var::service: subscribe => Package['openldap-servers'], - require => Openssl::Self_signed_cert["ldap.$::domain"], + require => Openssl::Self_signed_cert["ldap.${::domain}"], } - exec { '/etc/init.d/ldap check': + exec { "slaptest": refreshonly => true, - notify => Service['ldap'], + notify => Service[$openldap::var::service], } file { '/etc/ssl/openldap/': ensure => directory, } - openssl::self_signed_cert{ "ldap.$::domain": + openssl::self_signed_cert{ "ldap.${::domain}": directory => '/etc/ssl/openldap/', } @@ -26,5 +28,7 @@ class openldap { content => ''; '/etc/sysconfig/ldap': content => ''; + '/etc/sysconfig/slapd': + content => ''; } } diff --git a/modules/openldap/manifests/master.pp b/modules/openldap/manifests/master.pp index 730feb19..53122628 100644 --- a/modules/openldap/manifests/master.pp +++ b/modules/openldap/manifests/master.pp @@ -1,4 +1,6 @@ class openldap::master inherits openldap { + include openldap::var + Openldap::Config['/etc/openldap/mandriva-dit-access.conf'] { content => template('openldap/mandriva-dit-access.conf'), } @@ -10,7 +12,7 @@ class openldap::master inherits openldap { group => 'ldap', owner => 'ldap', require => Package['openldap-servers'], - before => Service['ldap'], + before => Service[$openldap::var::service], } Openldap::Config['/etc/openldap/slapd.conf'] { @@ -21,12 +23,20 @@ class openldap::master inherits openldap { content => template('openldap/ldap.sysconfig'), } + Openldap::Config['/etc/sysconfig/slapd'] { + content => template('openldap/slapd.sysconfig'), + } + + host { "ldap.${::domain}": + ip => '127.0.0.1', + } + if $::environment == 'test' { # if we are in a test vm, we need to fill the directory # with data package { 'openldap-clients': } - mga-common::local_script { 'init_ldap.sh': + mga_common::local_script { 'init_ldap.sh': content => template('openldap/init_ldap.sh'), require => Package['openldap-clients'], } @@ -34,7 +44,7 @@ class openldap::master inherits openldap { exec { 'init_ldap.sh': # taken arbitrary among all possible files creates => '/var/lib/ldap/objectClass.bdb', - require => Local_script['init_ldap.sh'], + require => Mga_common::Local_script['init_ldap.sh'], } } } diff --git a/modules/openldap/manifests/slave.pp b/modules/openldap/manifests/slave.pp index a3559ef8..ba0cfb9d 100644 --- a/modules/openldap/manifests/slave.pp +++ b/modules/openldap/manifests/slave.pp @@ -2,7 +2,7 @@ class openldap::slave($rid) inherits openldap { @@openldap::exported_slave { $rid: } - $sync_password = extlookup("ldap_syncuser-$::hostname",'x') + $sync_password = extlookup("ldap_syncuser-${::hostname}",'x') # same access rights as master Openldap::Config['/etc/openldap/mandriva-dit-access.conf'] { @@ -16,4 +16,8 @@ class openldap::slave($rid) inherits openldap { Openldap::Config['/etc/sysconfig/ldap'] { content => template('openldap/ldap.sysconfig'), } + + Openldap::Config['/etc/sysconfig/slapd'] { + content => template('openldap/slapd-slave.sysconfig'), + } } diff --git a/modules/openldap/manifests/slave_instance.pp b/modules/openldap/manifests/slave_instance.pp index a12771a3..fbf998c6 100644 --- a/modules/openldap/manifests/slave_instance.pp +++ b/modules/openldap/manifests/slave_instance.pp @@ -1,10 +1,8 @@ # TODO create the user for sync in ldap -# this define is mainly syntaxic sugar +# this define is mainly syntactic sugar define openldap::slave_instance($rid) { include openldap class { 'openldap::slave': rid => $rid, } } - - diff --git a/modules/openldap/manifests/var.pp b/modules/openldap/manifests/var.pp new file mode 100644 index 00000000..d6947eb8 --- /dev/null +++ b/modules/openldap/manifests/var.pp @@ -0,0 +1,3 @@ +class openldap::var { + $service = 'slapd' +} diff --git a/modules/openldap/templates/init_ldap.sh b/modules/openldap/templates/init_ldap.sh index a596cfe7..dfcaf236 100644 --- a/modules/openldap/templates/init_ldap.sh +++ b/modules/openldap/templates/init_ldap.sh @@ -28,7 +28,7 @@ end -%> <% # FIXME automatically get the list of servers -for g in ['valstar','alamut'] %> +for g in ['duvel','alamut'] %> dn: cn=<%= g%>.<%= domain %>,ou=Hosts,<%= dc_suffix %> objectClass: device objectClass: simpleSecurityObject diff --git a/modules/openldap/templates/mandriva-dit-access.conf b/modules/openldap/templates/mandriva-dit-access.conf index 68a2c7f8..361d956b 100644 --- a/modules/openldap/templates/mandriva-dit-access.conf +++ b/modules/openldap/templates/mandriva-dit-access.conf @@ -66,7 +66,7 @@ access to dn.subtree="<%= dc_suffix %>" by self write by * none # password history attribute -# pwdHistory is read-only, but ACL is simplier with it here +# pwdHistory is read-only, but ACL is simpler with it here access to dn.subtree="<%= dc_suffix %>" attrs=sambaPasswordHistory,pwdHistory by self read @@ -113,7 +113,7 @@ access to dn.subtree="ou=People,<%= dc_suffix %>" # let the user change some of his/her attributes access to dn.subtree="ou=People,<%= dc_suffix %>" - attrs=cn,sn,givenName,carLicense,homePhone,homePostalAddress,mobile,pager,telephoneNumber,mail,preferredLanguage,sshPublicKey + attrs=cn,sn,givenName,carLicense,drink,homePhone,homePostalAddress,mobile,pager,telephoneNumber,mail,preferredLanguage,sshPublicKey by self write by users read @@ -193,4 +193,3 @@ access to dn.sub="ou=KDEConfig,<%= dc_suffix %>" # last one access to dn.subtree="<%= dc_suffix %>" attrs=entry,uid,cn by users read - diff --git a/modules/openldap/templates/slapd-slave.sysconfig b/modules/openldap/templates/slapd-slave.sysconfig new file mode 100644 index 00000000..9bff24ff --- /dev/null +++ b/modules/openldap/templates/slapd-slave.sysconfig @@ -0,0 +1,38 @@ +# debug level for slapd +SLAPDSYSLOGLEVEL="0" +SLAPDSYSLOGLOCALUSER="local4" + +# SLAPD URL list +SLAPDURLLIST="ldap:/// ldaps:/// ldapi:///" + +# Config file to use for slapd +#SLAPDCONF=/etc/openldap/slapd.conf + +# Which user to run as +#LDAPUSER=ldap +#LDAPGROUP=ldap + +# Should file permissions on database files be fixed at startup. Default is yes +# FIXPERMS=no + +# Whether database recovery should be run before starting slapd in start +# (not strictly be necessary in 2.3). Default is no +# AUTORECOVER=yes + +# At what intervals to run ldap-hot-db-backup from cron, which will +# do hot database backups for all bdb/hdb databases, and archive +# unnecessary transaction logs, one of hourly,daily,weekly,monthly,yearly +# Default is daily +# Slave does not need a backup +RUN_DB_BACKUP=never + +# How many days to keep archived transaction logs for. This should be just +# greater than the backup interval on these files. Default is 7 +# KEEP_ARCHIVES_DAYS=7 + +# How many files slapd should be able to have open. By default, the process +# will inherit the default per-process limit (usually 1024), which may +# not be enough, so ulimit -n is run with the value in MAXFILES (which +# defaults to 1024 as well). 4096 is the maximum OpenLDAP will use without +# recompiling. +# MAXFILES=4096 diff --git a/modules/openldap/templates/slapd.conf b/modules/openldap/templates/slapd.conf index 9451d6cd..d82fe088 100644 --- a/modules/openldap/templates/slapd.conf +++ b/modules/openldap/templates/slapd.conf @@ -30,6 +30,11 @@ pidfile /var/run/ldap/slapd.pid argsfile /var/run/ldap/slapd.args modulepath <%= lib_dir %>/openldap +<% if @hostname == 'duvel' then %> +moduleload back_bdb.la +<% else %> +moduleload back_mdb.la +<% end %> moduleload back_monitor.la moduleload syncprov.la moduleload ppolicy.la @@ -59,17 +64,25 @@ access to dn.subtree="cn=Monitor" by group.exact="cn=LDAP Admins,ou=System Groups,<%= dc_suffix %>" read by * none +<% if @hostname == 'duvel' then %> database bdb +<% else %> +database mdb +# mdb defaults to 10MB max DB, so we need to hardcode some better value :( +maxsize 500000000 +<% end %> suffix "<%= dc_suffix %>" directory /var/lib/ldap rootdn "cn=manager,<%= dc_suffix %>" checkpoint 256 5 +<% if @hostname == 'duvel' then %> # 32Mbytes, can hold about 10k posixAccount entries dbconfig set_cachesize 0 33554432 1 dbconfig set_lg_bsize 2097152 cachesize 1000 idlcachesize 3000 +<% end %> index objectClass eq index uidNumber,gidNumber,memberuid,member,owner eq @@ -104,7 +117,7 @@ dynlist-attrset groupOfURLs memberURL member overlay constraint -constraint_attribute sshPublicKey regex "^ssh-(rsa|dss) [[:graph:]]+ [[:graph:]]+$" +constraint_attribute sshPublicKey regex "^ssh-(rsa|dss|ed25519) [[:graph:]]+ [[:graph:]]+$" # uncomment if you want to automatically update group # memberships when an user is removed from the tree diff --git a/modules/openldap/templates/slapd.syncrepl.conf b/modules/openldap/templates/slapd.syncrepl.conf index d9aa4cfe..2bfe7d50 100644 --- a/modules/openldap/templates/slapd.syncrepl.conf +++ b/modules/openldap/templates/slapd.syncrepl.conf @@ -6,6 +6,6 @@ syncrepl rid=<%= rid %> bindmethod=simple binddn="cn=syncuser-<%= hostname%>,ou=System Accounts,<%= dc_suffix %>" credentials=<%= sync_password %> - -updateref ldaps://ldap-master.<%= domain %>:636 + tls_reqcert=never +updateref ldaps://ldap-master.<%= domain %>:636 diff --git a/modules/openldap/templates/slapd.sysconfig b/modules/openldap/templates/slapd.sysconfig new file mode 100644 index 00000000..e6ae2e05 --- /dev/null +++ b/modules/openldap/templates/slapd.sysconfig @@ -0,0 +1,37 @@ +# debug level for slapd +SLAPDSYSLOGLEVEL="0" +SLAPDSYSLOGLOCALUSER="local4" + +# SLAPD URL list +SLAPDURLLIST="ldap:/// ldaps:/// ldapi:///" + +# Config file to use for slapd +#SLAPDCONF=/etc/openldap/slapd.conf + +# Which user to run as +#LDAPUSER=ldap +#LDAPGROUP=ldap + +# Should file permissions on database files be fixed at startup. Default is yes +# FIXPERMS=no + +# Whether database recovery should be run before starting slapd in start +# (not strictly be necessary in 2.3). Default is no +# AUTORECOVER=yes + +# At what intervals to run ldap-hot-db-backup from cron, which will +# do hot database backups for all bdb/hdb databases, and archive +# unnecessary transaction logs, one of hourly,daily,weekly,monthly,yearly +# Default is daily +# RUN_DB_BACKUP=daily + +# How many days to keep archived transaction logs for. This should be just +# greater than the backup interval on these files. Default is 7 +# KEEP_ARCHIVES_DAYS=7 + +# How many files slapd should be able to have open. By default, the process +# will inherit the default per-process limit (usually 1024), which may +# not be enough, so ulimit -n is run with the value in MAXFILES (which +# defaults to 1024 as well). 4096 is the maximum OpenLDAP will use without +# recompiling. +# MAXFILES=4096 diff --git a/modules/openldap/templates/slapd.test.conf b/modules/openldap/templates/slapd.test.conf index 355efb8e..8befa55a 100644 --- a/modules/openldap/templates/slapd.test.conf +++ b/modules/openldap/templates/slapd.test.conf @@ -7,4 +7,3 @@ authz-regexp "gidNumber=0\\\+uidNumber=0,cn=peercred,cn=external,cn=auth" "cn=manager,dc=test_ldap" # force ssl security ssf=56 - diff --git a/modules/openssh/manifests/pubkeys_directory.pp b/modules/openssh/manifests/pubkeys_directory.pp deleted file mode 100644 index cbcaeb88..00000000 --- a/modules/openssh/manifests/pubkeys_directory.pp +++ /dev/null @@ -1,17 +0,0 @@ -class openssh::pubkeys_directory { - $pubkeys_directory = '/var/lib/pubkeys' - file { $pubkeys_directory: - ensure => directory, - } - - file { "$pubkeys_directory/root": - ensure => directory, - mode => '0700', - } - - file { "$pubkeys_directory/root/authorized_keys": - ensure => link, - target => '/root/.ssh/authorized_keys', - mode => '0700', - } -} diff --git a/modules/openssh/manifests/server.pp b/modules/openssh/manifests/server.pp index ce60646b..c45268d2 100644 --- a/modules/openssh/manifests/server.pp +++ b/modules/openssh/manifests/server.pp @@ -1,6 +1,7 @@ class openssh::server { # some trick to manage sftp server, who is arch dependent on mdv - $path_to_sftp = "$::lib_dir/ssh/" + # TODO: the path changed on Mageia 6 to /usr/libexec/openssh/sftp-server + $path_to_sftp = "${::lib_dir}/ssh/" package { 'openssh-server': } diff --git a/modules/openssh/manifests/ssh_keys_from_ldap.pp b/modules/openssh/manifests/ssh_keys_from_ldap.pp index d35f4d2a..9ea6c139 100644 --- a/modules/openssh/manifests/ssh_keys_from_ldap.pp +++ b/modules/openssh/manifests/ssh_keys_from_ldap.pp @@ -1,32 +1,20 @@ -class openssh::ssh_keys_from_ldap($symlink_users = [], - $config = '') inherits server { - # root account authorized_keys will be symlinked - # if you want to add symlink on other accounts, use $symlink_users parameter - - File ['/etc/ssh/sshd_config'] { - content => template('openssh/sshd_config','openssh/sshd_config_ldap') - } - - package { 'python-ldap': } - - include openssh::pubkeys_directory - $pubkeys_directory = $openssh::pubkeys_directory::pubkeys_directory - - symlink_user { $symlink_users: } +class openssh::ssh_keys_from_ldap inherits server { + package { 'python3-ldap': } $ldap_pwfile = '/etc/ldap.secret' + $nslcd_conf_file = '/etc/nslcd.conf' $ldap_servers = get_ldap_servers() - mga-common::local_script { 'ldap-sshkey2file.py': + mga_common::local_script { 'ldap-sshkey2file.py': content => template('openssh/ldap-sshkey2file.py'), - require => Package['python-ldap'] + require => Package['python3-ldap'] } cron { 'sshkey2file': - command => '/usr/local/bin/ldap-sshkey2file.py', + command => '/bin/bash -c "/usr/local/bin/ldap-sshkey2file.py && ( [[ -f /usr/bin/mgagit && -d /var/lib/git/.gitolite ]] && /bin/su -c \'/usr/bin/mgagit glrun\' - git ) ||:"', hour => '*', minute => '*/10', user => 'root', environment => 'MAILTO=root', - require => Local_script['ldap-sshkey2file.py'], + require => Mga_common::Local_script['ldap-sshkey2file.py'], } } diff --git a/modules/openssh/manifests/symlink_user.pp b/modules/openssh/manifests/symlink_user.pp deleted file mode 100644 index f2e107b1..00000000 --- a/modules/openssh/manifests/symlink_user.pp +++ /dev/null @@ -1,19 +0,0 @@ -define openssh::symlink_user() { - include openssh::pubkeys_directory - $pubkeys_directory = $openssh::pubkeys_directory::pubkeys_directory - file { "$pubkeys_directory/$name": - ensure => directory, - owner => $name, - group => $name, - mode => '0700', - } - - file { "$pubkeys_directory/$name/authorized_keys": - # FIXME : fragile approximation for $HOME - ensure => link, - target => "/home/$name/.ssh/authorized_keys", - mode => '0700', - } -} - - diff --git a/modules/openssh/templates/ldap-sshkey2file.py b/modules/openssh/templates/ldap-sshkey2file.py index eb8456ab..934e2865 100755 --- a/modules/openssh/templates/ldap-sshkey2file.py +++ b/modules/openssh/templates/ldap-sshkey2file.py @@ -1,96 +1,194 @@ -#!/usr/bin/python +#!/usr/bin/python3 -import sys +import argparse import os import random +import shutil +import sys +import tempfile +import textwrap +from typing import Iterable try: import ldap -except ImportError, e: - print "Please install python-ldap before running this program" +except ImportError: + print("Please install python-ldap before running this program") sys.exit(1) -basedn="<%= dc_suffix %>" -peopledn="ou=people,%s" % basedn +basedn = "<%= @dc_suffix %>" +peopledn = f"ou=people,{basedn}" <%- ldap_servers.map! { |l| "'ldaps://#{l}'" } -%> -uris=[<%= ldap_servers.join(", ") %>] +uris = [<%= ldap_servers.join(", ") %>] random.shuffle(uris) uri = " ".join(uris) -timeout=5 -binddn="cn=<%= fqdn %>,ou=Hosts,%s" % basedn -pwfile="<%= ldap_pwfile %>" +timeout = 5 +binddn = f"cn=<%= @fqdn %>,ou=Hosts,{basedn}" +ldap_secret_file = "<%= @ldap_pwfile %>" +nslcd_conf_file = "<%= @nslcd_conf_file %>" # filter out disabled accounts also # too bad uidNumber doesn't support >= filters -filter="(&(objectClass=inetOrgPerson)(objectClass=ldapPublicKey)(objectClass=posixAccount)(sshPublicKey=*))" -keypathprefix="<%= pubkeys_directory %>" - -def usage(): - print "%s" % sys.argv[0] - print - print "Will fetch all enabled user accounts under %s" % peopledn - print "with ssh keys in them and write each one to" - print "%s/<login>/authorized_keys" % keypathprefix - print - print "This script is intented to be run from cron as root" - print - -def get_pw(pwfile): +objfilter = "(&(objectClass=inetOrgPerson)(objectClass=ldapPublicKey)(objectClass=posixAccount)(sshPublicKey=*))" +keypathprefix = "/home" + +parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(f'''\ + Will fetch all enabled user accounts under {peopledn} + with ssh keys in them and write each one to + {keypathprefix}/<login>/.ssh/authorized_keys + + It will return failure when no keys are updated and success + when one or more keys have changed. + + This script is intended to be run from cron as root; + ''')) +parser.add_argument('-n', '--dry-run', action='store_true') +parser.add_argument('-v', '--verbose', action='store_true') +args = parser.parse_args() + + +def get_bindpw() -> str: try: - f = open(pwfile, 'r') - except IOError, e: - print "Error while reading password file, aborting" - print e - sys.exit(1) - pw = f.readline().strip() - f.close() - return pw + return get_nslcd_bindpw(nslcd_conf_file) + except: + pass -def write_keys(keys, user, uid, gid): try: - os.makedirs("%s/%s" % (keypathprefix,user), 0700) + return get_ldap_secret(ldap_secret_file) except: pass - keyfile = "%s/%s/authorized_keys" % (keypathprefix,user) - f = open(keyfile, 'w') + + print("Error while reading password file, aborting") + sys.exit(1) + + +def get_nslcd_bindpw(pwfile: str) -> str: + try: + with open(pwfile, 'r') as f: + pwfield = "bindpw" + for line in f: + ls = line.strip().split() + if len(ls) == 2 and ls[0] == pwfield: + return ls[1] + except IOError as e: + print("Error while reading nslcd file " + pwfile) + print(e) + raise + + print("No " + pwfield + " field found in nslcd file " + pwfile) + raise Exception() + + +def get_ldap_secret(pwfile: str) -> str: + try: + with open(pwfile, 'r') as f: + pw = f.readline().strip() + except IOError as e: + print("Error while reading password file " + pwfile) + print(e) + raise + return pw + + +def write_keys(keys: Iterable[bytes], user: bytes, uid: int, gid: int) -> bool: + userdir = f"{keypathprefix}/{user.decode('utf-8')}" + keyfile = f"{userdir}/.ssh/authorized_keys" + + fromldap = "" for key in keys: - f.write(key.strip() + "\n") - f.close() - os.chmod(keyfile, 0600) + fromldap += key.decode("utf-8").strip() + "\n" + + fromfile = "" + try: + with open(keyfile, 'r') as f: + fromfile = f.read() + except FileNotFoundError: + pass + + if fromldap == fromfile: + return False + + if args.dry_run: + print(f"Would write {keyfile}") + return True + + if args.verbose: + print(f"Writing {keyfile}") + + if not os.path.isdir(userdir): + shutil.copytree('/etc/skel', userdir) + os.chown(userdir, uid, gid) + for root, dirs, files in os.walk(userdir): + for d in dirs: + os.chown(os.path.join(root, d), uid, gid) + for f in files: + os.chown(os.path.join(root, f), uid, gid) + + try: + os.makedirs(f"{userdir}/.ssh", 0o700) + except FileExistsError: + pass + os.chmod(f"{userdir}/.ssh", 0o700) + os.chown(f"{userdir}/.ssh", uid, gid) + + with tempfile.NamedTemporaryFile( + prefix='ldap-sshkey2file-', mode='w', delete=False) as tmpfile: + tmpfile.write(fromldap) + os.chmod(tmpfile.name, 0o600) + os.chown(tmpfile.name, uid, gid) + shutil.move(tmpfile.name, keyfile) + # Hmm, apparently shutil.move does not preserve user/group so let's reapply + # them. I still like doing it before as this should be more "atomic" + # if it actually worked, so it's "good practice", even if shutil.move sucks os.chown(keyfile, uid, gid) - os.chmod("%s/%s" % (keypathprefix,user), 0700) - os.chown("%s/%s" % (keypathprefix,user), uid, gid) + os.chmod(keyfile, 0o600) + return True -if len(sys.argv) != 1: - usage() - sys.exit(1) -bindpw = get_pw(pwfile) +bindpw = get_bindpw() +changed = False try: ld = ldap.initialize(uri) ld.set_option(ldap.OPT_NETWORK_TIMEOUT, timeout) if uri.startswith("ldap:/"): ld.start_tls_s() ld.bind_s(binddn, bindpw) - res = ld.search_s(peopledn, ldap.SCOPE_ONELEVEL, filter, ['uid','sshPublicKey','uidNumber','gidNumber']) + res = ld.search_s(peopledn, ldap.SCOPE_ONELEVEL, objfilter, + ['uid', 'sshPublicKey', 'uidNumber', 'gidNumber']) try: - os.makedirs(keypathprefix, 0701) - except: + os.makedirs(keypathprefix, 0o701) + except FileExistsError: pass + + if args.verbose: + print("Found users:", + ", ".join(sorted([x[1]['uid'][0].decode('utf-8') for x in res]))) + for result in res: dn, entry = result # skip possible system users - if int(entry['uidNumber'][0]) < 500: + if 'uidNumber' not in entry or int(entry['uidNumber'][0]) < 500: continue - write_keys(entry['sshPublicKey'], entry['uid'][0], int(entry['uidNumber'][0]), int(entry['gidNumber'][0])) + if write_keys(entry['sshPublicKey'], entry['uid'][0], + int(entry['uidNumber'][0]), int(entry['gidNumber'][0])): + changed = True + ld.unbind_s() -except Exception, e: - print "Error" +except Exception: + print("Error") raise -sys.exit(0) +if changed: + if args.verbose: + print("SSH keys changed") + sys.exit(0) + +if args.verbose: + print("No changes in SSH keys") +sys.exit(1) # vim:ts=4:sw=4:et:ai:si diff --git a/modules/openssh/templates/sshd_config b/modules/openssh/templates/sshd_config index 27eee0f1..56ddd725 100644 --- a/modules/openssh/templates/sshd_config +++ b/modules/openssh/templates/sshd_config @@ -18,11 +18,10 @@ # The default requires explicit activation of protocol 1 #Protocol 2 -# HostKey for protocol version 1 -HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 HostKey /etc/ssh/ssh_host_rsa_key -HostKey /etc/ssh/ssh_host_dsa_key +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key # Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 1h @@ -57,11 +56,11 @@ PermitRootLogin without-password #IgnoreRhosts yes # To disable tunneled clear text passwords, change to no here! -#PasswordAuthentication yes +PasswordAuthentication no #PermitEmptyPasswords no # Change to no to disable s/key passwords -#ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no # Kerberos options #KerberosAuthentication no @@ -82,7 +81,7 @@ PermitRootLogin without-password # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. -UsePAM yes +UsePAM no # Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES @@ -99,7 +98,6 @@ X11Forwarding yes #PrintLastLog yes #TCPKeepAlive yes #UseLogin no -UsePrivilegeSeparation yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 @@ -114,10 +112,15 @@ UsePrivilegeSeparation yes #Banner none # override default of no subsystems -Subsystem sftp <%= path_to_sftp %>/sftp-server +Subsystem sftp /usr/libexec/openssh/sftp-server # Example of overriding settings on a per-user basis #Match User anoncvs # X11Forwarding no # AllowTcpForwarding no # ForceCommand cvs server +<% if @hostname == 'duvel' then %> +# git command is already forced to "gitolite <username>" in /var/lib/git/.ssh/authorized_keys +Match User *,!schedbot,!root,!git Group *,!mga-sysadmin,!mga-unrestricted_shell_access + ForceCommand /usr/local/bin/sv_membersh.pl -c "$SSH_ORIGINAL_COMMAND" +<% end %> diff --git a/modules/openssh/templates/sshd_config_ldap b/modules/openssh/templates/sshd_config_ldap deleted file mode 100644 index 31b29e21..00000000 --- a/modules/openssh/templates/sshd_config_ldap +++ /dev/null @@ -1,3 +0,0 @@ - -AuthorizedKeysFile /var/lib/pubkeys/%u/authorized_keys - diff --git a/modules/openssl/manifests/init.pp b/modules/openssl/manifests/init.pp index bf05d35e..b8c4d91e 100644 --- a/modules/openssl/manifests/init.pp +++ b/modules/openssl/manifests/init.pp @@ -6,10 +6,10 @@ class openssl { define self_signed_cert($directory = '/etc/certs') { include openssl::base - $pem_file = "$name.pem" - exec { "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout $pem_file -out $pem_file -subj '/CN=$name'": + $pem_file = "${name}.pem" + exec { "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${pem_file} -out ${pem_file} -subj '/CN=${name}'": cwd => $directory, - creates => "$directory/$name.pem", + creates => "${directory}/${name}.pem", require => Package['openssl'] } } @@ -21,17 +21,17 @@ class openssl { $mode = '0600') { include openssl::base - $crt_file = "$filename.crt" - $key_file = "$filename.key" - exec { "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout $key_file -out $crt_file -subj '/CN=$name'": + $crt_file = "${filename}.crt" + $key_file = "${filename}.key" + exec { "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${key_file} -out ${crt_file} -subj '/CN=${name}'": cwd => $directory, - creates => "$directory/$key_file", + creates => "${directory}/${key_file}", require => Package['openssl'], - before => [File["$directory/$key_file"], - File["$directory/$crt_file"]] + before => [File["${directory}/${key_file}"], + File["${directory}/${crt_file}"]] } - file { ["$directory/$key_file","$directory/$crt_file"]: + file { ["${directory}/${key_file}","${directory}/${crt_file}"]: owner => $owner, group => $group, mode => $mode, diff --git a/modules/pam/manifests/base.pp b/modules/pam/manifests/base.pp index df913101..e29c8555 100644 --- a/modules/pam/manifests/base.pp +++ b/modules/pam/manifests/base.pp @@ -1,5 +1,13 @@ class pam::base { - package { ['pam_ldap','nss_ldap','nscd']: } + include pam::multiple_ldap_access + package { ['nscd', 'nss-pam-ldapd']: } + + # This needs configuration or it generates an error every hour. + # If it's ever enabled, make sure restrict permissions on + # /var/db/passwd.db and /var/db/group.db at the same time. + package { 'nss_updatedb': + ensure => 'absent', + } service { 'nscd': require => Package['nscd'], diff --git a/modules/pam/manifests/multiple_ldap_access.pp b/modules/pam/manifests/multiple_ldap_access.pp index ecda7018..1c5a391f 100644 --- a/modules/pam/manifests/multiple_ldap_access.pp +++ b/modules/pam/manifests/multiple_ldap_access.pp @@ -1,4 +1,13 @@ -define pam::multiple_ldap_access($access_classes, $restricted_shell = false) { +class pam::multiple_ldap_access($access_classes, $restricted_shell = false) { + include stdlib + + $default_access_classes = [ 'mga-sysadmin', 'mga-unrestricted_shell_access' ] + if empty($access_classes) { + $allowed_access_classes = $default_access_classes + } else { + $allowed_access_classes = concat($default_access_classes, $access_classes) + } + if $restricted_shell { include restrictshell } diff --git a/modules/pam/templates/ldap.conf b/modules/pam/templates/ldap.conf index a1d751cf..235a6aac 100644 --- a/modules/pam/templates/ldap.conf +++ b/modules/pam/templates/ldap.conf @@ -15,8 +15,10 @@ nss_map_attribute uniqueMember member sudoers_base ou=sudoers,<%= dc_suffix %> #sudoers_debug 2 -<% if restricted_shell %> +<%- +restricted_shell = scope.lookupvar('pam::multiple_ldap_access::restricted_shell') +if restricted_shell +-%> # for restricted access nss_override_attribute_value loginShell /usr/local/bin/sv_membersh.pl <% end %> - diff --git a/modules/pam/templates/nsswitch.conf b/modules/pam/templates/nsswitch.conf index fdd32996..bfd042c1 100644 --- a/modules/pam/templates/nsswitch.conf +++ b/modules/pam/templates/nsswitch.conf @@ -13,4 +13,3 @@ netgroup: files ldap publickey: files automount: files aliases: files - diff --git a/modules/pam/templates/openldap.ldap.conf b/modules/pam/templates/openldap.ldap.conf index 812538be..cd6ee640 100644 --- a/modules/pam/templates/openldap.ldap.conf +++ b/modules/pam/templates/openldap.ldap.conf @@ -18,9 +18,8 @@ TLS_REQCERT allow # Use the default self-signed cert generated by openldap-server postinstall # by default #TLS_CACERT /etc/pki/tls/certs/ldap.pem -#TLS_CACERT /etc/ssl/openldap/ldap.mageia.org.pem +#TLS_CACERT /etc/ssl/openldap/ldap.<%= domain %>.pem # If requiring support for certificates signed by all CAs (noting risks # pam_ldap if doing DNS-based suffix lookup etc. #TLS_CACERTDIR /etc/pki/tls/rootcerts - diff --git a/modules/pam/templates/system-auth b/modules/pam/templates/system-auth index 4df9555e..37d1da7d 100644 --- a/modules/pam/templates/system-auth +++ b/modules/pam/templates/system-auth @@ -11,8 +11,9 @@ auth required pam_deny.so account sufficient pam_localuser.so # not sure if the following bring something useful account required pam_ldap.so -<%- if access_classes -%> -<%- access_classes.each { |ldap_group| -%> +<%- allowed_access_classes = scope.lookupvar('pam::multiple_ldap_access::allowed_access_classes') -%> +<%- if allowed_access_classes -%> +<%- allowed_access_classes.each { |ldap_group| -%> account sufficient pam_succeed_if.so quiet user ingroup <%= ldap_group %> <%- } -%> <%- end -%> @@ -32,4 +33,3 @@ session optional pam_mkhomedir.so session required pam_limits.so session required pam_unix.so session optional pam_ldap.so - diff --git a/modules/phpbb/files/phpbb_apply_config.pl b/modules/phpbb/files/phpbb_apply_config.pl index 5bd094e4..a58df24e 100644 --- a/modules/phpbb/files/phpbb_apply_config.pl +++ b/modules/phpbb/files/phpbb_apply_config.pl @@ -16,7 +16,7 @@ my $dbh = DBI->connect("dbi:Pg:","","", { my $table = "phpbb_config"; # FIXME add rollback if there is a problem -# http://docstore.mik.ua/orelly/linux/dbi/ch06_03.htm +# https://docstore.mik.ua/orelly/linux/dbi/ch06_03.htm my $update = $dbh->prepare("UPDATE $table SET config_value = ?, is_dynamic = ? WHERE config_name = ?"); my $insert = $dbh->prepare("INSERT INTO $table ( config_value, is_dynamic, config_name ) VALUES ( ? , ? , ? )"); diff --git a/modules/phpbb/files/robots.txt b/modules/phpbb/files/robots.txt new file mode 100644 index 00000000..1c335a73 --- /dev/null +++ b/modules/phpbb/files/robots.txt @@ -0,0 +1,7 @@ +User-agent: * +Disallow: /*/faq.php? +Disallow: /*/memberlist.php? +Disallow: /*/posting.php? +Disallow: /*/search.php? +Disallow: /*/ucp.php? +Crawl-delay: 30 diff --git a/modules/phpbb/manifests/base.pp b/modules/phpbb/manifests/base.pp index 115c4592..9f676cb4 100644 --- a/modules/phpbb/manifests/base.pp +++ b/modules/phpbb/manifests/base.pp @@ -9,7 +9,6 @@ class phpbb::base { 'php-xml', 'php-zlib', 'php-ftp', - 'php-apc', 'php-magickwand', 'php-pgsql', 'php-ldap']: } @@ -30,14 +29,23 @@ class phpbb::base { ensure => directory, } + $robotsfile = "$forums_dir/robots.txt" + file { $robotsfile: + ensure => present, + mode => '0644', + owner => root, + group => root, + source => 'puppet:///modules/phpbb/robots.txt', + } + # TODO check that everything is locked down - apache::vhost::base { "forums.$::domain": + apache::vhost::base { "forums.${::domain}": content => template('phpbb/forums_vhost.conf'), } - apache::vhost::base { "ssl_forums.$::domain": + apache::vhost::base { "ssl_forums.${::domain}": use_ssl => true, - vhost => "forums.$::domain", + vhost => "forums.${::domain}", content => template('phpbb/forums_vhost.conf'), } diff --git a/modules/phpbb/manifests/config.pp b/modules/phpbb/manifests/config.pp index 52bd5419..553b0f74 100644 --- a/modules/phpbb/manifests/config.pp +++ b/modules/phpbb/manifests/config.pp @@ -1,12 +1,12 @@ define phpbb::config($key, $value, $database) { - exec { "phpbb_apply $name": - command => "/usr/local/bin/phpbb_apply_config.pl $key", + exec { "phpbb_apply ${name}": + command => "/usr/local/bin/phpbb_apply_config.pl ${key}", user => 'root', - environment => ["PGDATABASE=$database", - "PGUSER=$phpbb::base::user", - "PGPASSWORD=$phpbb::base::pgsql_password", - "PGHOST=pgsql.$::domain", - "VALUE=$value"], + environment => ["PGDATABASE=${database}", + "PGUSER=${phpbb::base::user}", + "PGPASSWORD=${phpbb::base::pgsql_password}", + "PGHOST=pgsql.${::domain}", + "VALUE=${value}"], require => File['/usr/local/bin/phpbb_apply_config.pl'], } } diff --git a/modules/phpbb/manifests/instance.pp b/modules/phpbb/manifests/instance.pp index d260ff7b..e300d9e0 100644 --- a/modules/phpbb/manifests/instance.pp +++ b/modules/phpbb/manifests/instance.pp @@ -2,27 +2,27 @@ define phpbb::instance() { include phpbb::base $lang = $name - $database = "${phpbb::base::db}_$lang" + $database = "${phpbb::base::db}_${lang}" $user = $phpbb::base::user $pgsql_password = $phpbb::base::pgsql_password $forums_dir = $phpbb::base::forums_dir include git::client - exec { "git_clone $lang": - command =>"git clone git://git.$::domain/forum/ $lang", + exec { "git_clone ${lang}": + command =>"git clone git://git.${::domain}/web/forums/ ${lang}", cwd => $forums_dir, - creates => "$forums_dir/$lang", + creates => "${forums_dir}/${lang}", require => File[$forums_dir], - notify => Exec["rm_install $lang"], + notify => Exec["rm_install ${lang}"], } # remove this or the forum will not work ( 'board disabled' ) - # maybe it would be better to move this elsehwere, I + # maybe it would be better to move this elsewhere, I # am not sure ( and in any case, that's still in git ) - exec { "rm_install $lang": - command => "rm -Rf $forums_dir/$lang/phpBB/install", - onlyif => "test -d $forums_dir/$lang/phpBB/install", + exec { "rm_install ${lang}": + command => "rm -Rf ${forums_dir}/${lang}/phpBB/install", + onlyif => "test -d ${forums_dir}/${lang}/phpBB/install", } # list found by reading ./install/install_install.php @@ -33,15 +33,15 @@ define phpbb::instance() { 'files', 'store' ] - $dir_names = regsubst($writable_dirs,'^',"$forums_dir/$lang/phpBB/") + $dir_names = regsubst($writable_dirs,'^',"${forums_dir}/${lang}/phpBB/") file { $dir_names: ensure => directory, owner => 'apache', - require => Exec["git_clone $lang"], + require => Exec["git_clone ${lang}"], } - file { "$forums_dir/$lang/phpBB/config.php": + file { "${forums_dir}/${lang}/phpBB/config.php": content => template('phpbb/config.php'), } @@ -56,25 +56,25 @@ define phpbb::instance() { $ldap_password = extlookup( 'phpbb_ldap','x') phpbb::config { - "ldap_user/$lang": - key => 'ldap_user', value => "cn=phpbb-$::hostname,ou=System Accounts,$::dc_suffix"; - "ldap_server/$lang": - key => 'ldap_server', value => "ldaps://ldap.$::domain ldaps://ldap-slave-1.$::domain"; - "ldap_password/$lang": + "ldap_user/${lang}": + key => 'ldap_user', value => "cn=phpbb-${::hostname},ou=System Accounts,${::dc_suffix}"; + "ldap_server/${lang}": + key => 'ldap_server', value => "ldaps://ldap.${::domain} ldaps://ldap-slave-1.${::domain}"; + "ldap_password/${lang}": key => 'ldap_password', value => $ldap_password; - "ldap_base_dn/$lang": - key => 'ldap_base_dn', value => "ou=People,$::dc_suffix"; - "auth_method/$lang": + "ldap_base_dn/${lang}": + key => 'ldap_base_dn', value => "ou=People,${::dc_suffix}"; + "auth_method/${lang}": key => 'auth_method', value => 'ldap'; - "ldap_mail/$lang": + "ldap_mail/${lang}": key => 'ldap_mail', value => 'mail'; - "ldap_uid/$lang": + "ldap_uid/${lang}": key => 'ldap_uid', value => 'uid'; - "cookie_domain/$lang": - key => 'cookie_domain', value => "forums.$::domain"; - "server_name/$lang": - key => 'server_name', value => "forums.$::domain"; - "default_lang/$lang": + "cookie_domain/${lang}": + key => 'cookie_domain', value => "forums.${::domain}"; + "server_name/${lang}": + key => 'server_name', value => "forums.${::domain}"; + "default_lang/${lang}": key => 'default_lang', value => $lang; } } diff --git a/modules/phpbb/manifests/locale_db.pp b/modules/phpbb/manifests/locale_db.pp index 8111f18f..70116962 100644 --- a/modules/phpbb/manifests/locale_db.pp +++ b/modules/phpbb/manifests/locale_db.pp @@ -1,7 +1,8 @@ +# FIXME: In puppet >3.0 word 'tag' is reserved, so it have to be renamed define phpbb::locale_db($tag = 'default', $user = $phpbb::base::user) { postgresql::database { $name: - description => "$lang db for phpbb forum", + description => "${lang} db for phpbb forum", user => $user, tag => $tag, # this break due to the way it is remotely declared diff --git a/modules/phpbb/manifests/redirection_instance.pp b/modules/phpbb/manifests/redirection_instance.pp index 48446d3e..332eac53 100644 --- a/modules/phpbb/manifests/redirection_instance.pp +++ b/modules/phpbb/manifests/redirection_instance.pp @@ -1,7 +1,7 @@ define phpbb::redirection_instance($url) { $lang = $name - file { "/etc/httpd/conf/vhosts.d/forums.d/redirect_$name.conf": + file { "/etc/httpd/conf/vhosts.d/forums.d/redirect_${name}.conf": content => template('phpbb/forums_redirect.conf'), - notify => Exec['service httpd configtest'], + notify => Exec['apachectl configtest'], } } diff --git a/modules/phpbb/templates/config.php b/modules/phpbb/templates/config.php index 95bf1f2a..5d878235 100644 --- a/modules/phpbb/templates/config.php +++ b/modules/phpbb/templates/config.php @@ -2,7 +2,7 @@ // phpBB 3.0.x auto-generated configuration file // // Do not change anything in this file! $dbms = 'postgres'; -$dbhost = 'pgsql.<%= domain %>'; +$dbhost = 'pg.<%= domain %>'; $dbport = ''; $dbname = '<%= database %>'; $dbuser = '<%= user %>'; diff --git a/modules/phpbb/templates/forums_vhost.conf b/modules/phpbb/templates/forums_vhost.conf index 2c715485..440dad1f 100644 --- a/modules/phpbb/templates/forums_vhost.conf +++ b/modules/phpbb/templates/forums_vhost.conf @@ -1,19 +1,32 @@ # TODO redirect based on language settings # and the presence of the forum - + # for locale redirection Include conf/vhosts.d/forums.d/*.conf + # Prevent including forum site in tier iframe + Header set X-Frame-Options DENY + # using Redirect create a loop, so we use mod_rewrite here RewriteEngine On RewriteRule ^/$ /en/ [R] RewriteRule ^/(..)$ /$1/ [R] + Alias /robots.txt <%= forums_dir %>/robots.txt + AliasMatch ^/(..)/(.*) <%= forums_dir %>/$1/phpBB/$2 <Directory ~ "<%= forums_dir %>/.*/phpBB/"> + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order Allow,Deny Allow from all + </IfModule> </Directory> <%- @@ -35,8 +48,15 @@ forbidden = ['install', for f in forbidden -%> <Directory <%= forums_dir %>/.*/phpBB/<%= f %>/ > - Order Allow,Deny + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all denied + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order Deny,Allow Deny from all + </IfModule> </Directory> <%- end -%> diff --git a/modules/planet/manifests/init.pp b/modules/planet/manifests/init.pp index 2fbfab85..8aacd5cc 100644 --- a/modules/planet/manifests/init.pp +++ b/modules/planet/manifests/init.pp @@ -6,18 +6,24 @@ class planet { home => '/var/lib/planet', } - $vhost = "planet.$::domain" - $location = "/var/www/vhosts/$vhost" - + $vhost = "planet.${::domain}" + $location = "/var/www/vhosts/${vhost}" + include apache::mod::php - include apache::mod::deflate apache::vhost::base { $vhost: location => $location, content => template('planet/planet_vhosts.conf') } - local_script { 'deploy_new-planet.sh': + apache::vhost::base { "ssl_${vhost}": + use_ssl => true, + vhost => $vhost, + location => $location, + content => template('planet/planet_vhosts.conf') + } + + mga_common::local_script { 'deploy_new-planet.sh': content => template('planet/deploy_new-planet.sh') } @@ -25,27 +31,27 @@ class planet { ensure => directory, } - file { "$location/index.php": + file { "${location}/index.php": content => template('planet/index.php') } - package { ['php-iconv']: } + package { ['php-iconv']: } class files_backup inherits base { - file { "/var/lib/planet/backup": + file { '/var/lib/planet/backup': ensure => directory, } - local_script { "backup_planet-files.sh": - content => template("blog/backup_planet-files.sh") + mga_common::local_script { 'backup_planet-files.sh': + content => template('blog/backup_planet-files.sh') } cron { "Backup files (planet)": - user => root, - hour => '23', - minute => '42', - command => "/usr/local/bin/backup_planet-files.sh", - require => [File["backup_planet-files"]], + user => root, + hour => '23', + minute => '42', + command => '/usr/local/bin/backup_planet-files.sh', + require => [File['backup_planet-files']], } } } diff --git a/modules/planet/templates/deploy_new-planet.sh b/modules/planet/templates/deploy_new-planet.sh index 605fa273..b3889d31 100755 --- a/modules/planet/templates/deploy_new-planet.sh +++ b/modules/planet/templates/deploy_new-planet.sh @@ -22,7 +22,8 @@ then # Deploy new planet with locale given /bin/mkdir $FILE /bin/chown planet:apache $FILE - /usr/bin/wget -O $PATH_TO_FILE"/moonmoon.tar.gz" http://damsweb.net/files/moonmoon_mageia.tar.gz + # TODO: this URL returns 403 (2024-01) + /usr/bin/wget -O $PATH_TO_FILE"/moonmoon.tar.gz" https://damsweb.net/files/moonmoon_mageia.tar.gz if [ $? -ne 0 ] then echo "Aborted, can't download GZIP file" @@ -32,7 +33,7 @@ then /bin/mkdir $FILE"cache" /bin/chown -R planet:apache $FILE /bin/chmod g+w $FILE"custom" $FILE"custom/people.opml" $FILE"admin/inc/pwd.inc.php" $FILE"cache" - echo -e "Info: a new Planet had been deployed.\nThe locale is: \"$locale\" - http://planet.<%= domain %>/$locale \n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -s "New planet Mageia deployed" mageia-webteam@<%= domain %> mageia-marketing@<%= domain %> + echo -e "Info: a new Planet had been deployed.\nThe locale is: \"$locale\" - https://planet.<%= domain %>/$locale \n-- \nMail sent by the script '$0' on `hostname`" | /bin/mail -s "New planet Mageia deployed" mageia-webteam@<%= domain %> mageia-marketing@<%= domain %> fi else echo "Aborted, please try again." diff --git a/modules/planet/templates/planet_vhosts.conf b/modules/planet/templates/planet_vhosts.conf index 841e33cb..b3a07ab9 100644 --- a/modules/planet/templates/planet_vhosts.conf +++ b/modules/planet/templates/planet_vhosts.conf @@ -1,11 +1,11 @@ <Directory <%= location %> > - Order deny,allow + Order deny,allow Allow from All AllowOverride All - Options FollowSymlinks + Options FollowSymlinks Options +Indexes </Directory> # Add a permanent redirection for '/*' as '/en/' for english planet <IfModule mod_alias.c> - RedirectMatch permanent ^/?$ /en/ + RedirectMatch permanent ^/?$ /en/ </IfModule> diff --git a/modules/postfix/manifests/init.pp b/modules/postfix/manifests/init.pp index e13e86b5..8a4394df 100644 --- a/modules/postfix/manifests/init.pp +++ b/modules/postfix/manifests/init.pp @@ -1,5 +1,5 @@ class postfix { - package { ['postfix', 'nail']: } + package { postfix: } service { 'postfix': subscribe => Package['postfix'], @@ -10,4 +10,15 @@ class postfix { content => '', notify => Service['postfix'], } + + file { '/etc/ssl/postfix/': + ensure => directory, + } + + openssl::self_signed_splitted_cert { "${::hostname}.${::domain}": + filename => 'postfix', + directory => '/etc/ssl/postfix/', + owner => 'postfix', + group => 'postfix' + } } diff --git a/modules/postfix/manifests/server/primary.pp b/modules/postfix/manifests/server/primary.pp index 3f089685..c14a8606 100644 --- a/modules/postfix/manifests/server/primary.pp +++ b/modules/postfix/manifests/server/primary.pp @@ -1,10 +1,16 @@ class postfix::server::primary inherits postfix::server { - package { 'postfix-ldap': } + # Adding DKIM server + include opendkim + opendkim::domain{['mageia.org', 'sucuk.mageia.org', 'duvel.mageia.org', 'forums.mageia.org', 'madb.mageia.org','rabbit.mageia.org', 'fiona.mageia.org','identity.mageia.org', 'group.mageia.org', 'neru.mageia.org']:} + opendkim::trusted{['127.0.0.0/8', '212.85.158.0/24']:} + + package { ['postfix-ldap', 'sqlite3-tools', 'dovecot-plugins-sqlite','rspamd']: } # council is here until we fully decide who has aliases in com team, + # see https://bugs.mageia.org/show_bug.cgi?id=1345 - # alumini is a special group for tracking previous members of + # alumni is a special group for tracking previous members of # the project, so they keep their aliases for a time $aliases_group = ['mga-founders', 'mga-packagers', diff --git a/modules/postfix/manifests/simple_relay.pp b/modules/postfix/manifests/simple_relay.pp index 265960ae..8911f781 100644 --- a/modules/postfix/manifests/simple_relay.pp +++ b/modules/postfix/manifests/simple_relay.pp @@ -2,4 +2,8 @@ class postfix::simple_relay inherits postfix { File['/etc/postfix/main.cf'] { content => template('postfix/simple_relay_main.cf'), } + file { + '/etc/postfix/sympa_aliases': + content => template('postfix/sympa_aliases'); + } } diff --git a/modules/postfix/templates/main.cf b/modules/postfix/templates/main.cf index ffda06b3..6b42a4de 100644 --- a/modules/postfix/templates/main.cf +++ b/modules/postfix/templates/main.cf @@ -11,26 +11,37 @@ sendmail_path = /usr/sbin/sendmail.postfix setgid_group = postdrop command_directory = /usr/sbin manpage_directory = /usr/share/man -daemon_directory = <%= lib_dir %>/postfix/ +daemon_directory = /usr/libexec/postfix +meta_directory = /etc/postfix +shlib_directory = /usr/lib64 +compatibility_level = 2 data_directory = /var/lib/postfix newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq queue_directory = /var/spool/postfix mail_owner = postfix +<% if all_tags.include?('postfix::simple_relay') || all_tags.include?('postfix::server::secondary') %> +relayhost = sucuk.<%= domain %> +<%- end -%> # User configurable parameters <% if all_tags.include?('postfix::simple_relay') %> -inet_interfaces = localhost +inet_interfaces = localhost, 127.0.0.1 <% else %> inet_interfaces = all <% end %> inet_protocols = all -mynetworks_style = host +<% if @hostname == 'neru' then %> +# We do not have a reverse on ipv6 :( +smtp_address_preference = ipv4 +<%- end -%> + +# FIXME Do not hardcode this +mynetworks = 212.85.158.144/28 [2a02:2178:2:7::]/64 127.0.0.0/16 163.172.148.228 [2001:bc8:4400:2800::4115] myhostname = <%= fqdn %> mydomain = <%= domain %> -myorigin = $mydomain <%- if all_tags.include?('postfix::server::secondary') -%> relay_domains = <%= domain %>, ml.<%= domain %>, @@ -38,7 +49,7 @@ relay_domains = <%= domain %>, <%- end -%> mydestination = <%= fqdn %> -<%- if classes.include?('sympa::server') -%> +<%- if all_tags.include?('postfix::server::primary') -%> ml.<%= domain %> <%- end -%> @@ -71,8 +82,25 @@ virtual_alias_maps = ldap:/etc/postfix/ldap_aliases.conf <%- if classes.include?('sympa::server') -%> regexp:/etc/postfix/sympa_aliases <%- end -%> +<% else %> +<%- if classes.include?('sympa::server') -%> +virtual_alias_maps = regexp:/etc/postfix/sympa_aliases +<%- end -%> <%- end -%> +<%- if all_tags.include?('postfix::server::primary') -%> +# Adding DKIM Miler for primaryserver (sucuk) +smtpd_milters = inet:127.0.0.1:8891 +non_smtpd_milters = $smtpd_milters +milter_default_action = accept +milter_protocol = 2 + +# Adding Sender Rewriting Scheme +sender_canonical_maps = socketmap:inet:localhost:10003:forward +sender_canonical_classes = envelope_sender +recipient_canonical_maps = socketmap:inet:localhost:10003:reverse +recipient_canonical_classes= envelope_recipient,header_recipient +<%- end -%> <%- if all_tags.include?('postfix::server') -%> transport_maps = regexp:/etc/postfix/transport_regexp @@ -89,12 +117,15 @@ smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) (<%= lsbdistid %>) unknown_local_recipient_reject_code = 450 smtp-filter_destination_concurrency_limit = 2 lmtp-filter_destination_concurrency_limit = 2 -# disabled for the time being, as the certificate do not exist -# FIXME create the cert in puppet -smtpd_use_tls = no -#smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem -#smtpd_tls_key_file = /etc/pki/tls/private/postfix.pem -#smtpd_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt +# enable opportunistic TLS when receiving +smtpd_use_tls = yes +smtpd_tls_received_header = yes +smtpd_tls_cert_file = /etc/ssl/postfix/postfix.crt +smtpd_tls_key_file = /etc/ssl/postfix/postfix.key +smtpd_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt +# enable opportunistic TLS when sending +smtp_tls_security_level = may +smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt <%- if all_tags.include?('postfix::server') -%> smtpd_etrn_restrictions = reject @@ -105,13 +136,18 @@ smtpd_data_restrictions = permit_mynetworks reject_unauth_pipelining reject_multi_recipient_bounce -smtpd_recipient_restrictions = reject_non_fqdn_recipient - reject_non_fqdn_sender +smtpd_recipient_restrictions = permit_mynetworks # not done yet, not sure if we need to offer this kind of service # permit_sasl_authenticated - permit_mynetworks - reject_unauth_destination reject_non_fqdn_helo_hostname + reject_non_fqdn_recipient + reject_non_fqdn_sender + check_sender_access hash:/etc/postfix/access + reject_rhsbl_helo sbl.spamhaus.org + reject_rhsbl_reverse_client sbl.spamhaus.org + reject_rhsbl_sender sbl.spamhaus.org + reject_rbl_client sbl.spamhaus.org + reject_unauth_destination reject_unknown_sender_domain reject_unknown_client <%- if classes.include?('postgrey') -%> @@ -119,3 +155,5 @@ smtpd_recipient_restrictions = reject_non_fqdn_recipient <%- end -%> <%- end -%> +# Needed for buggy clients +always_add_missing_headers = yes diff --git a/modules/postfix/templates/primary_master.cf b/modules/postfix/templates/primary_master.cf index 8037d037..e05d33dc 100644 --- a/modules/postfix/templates/primary_master.cf +++ b/modules/postfix/templates/primary_master.cf @@ -174,4 +174,3 @@ smtp-filter unix - - y - - smtp -o max_use=20 # ##### END OF CONTENT FILTER CUSTOMIZATIONS ##### - diff --git a/modules/postfix/templates/simple_relay_main.cf b/modules/postfix/templates/simple_relay_main.cf index a6cf2113..e0c116a7 100644 --- a/modules/postfix/templates/simple_relay_main.cf +++ b/modules/postfix/templates/simple_relay_main.cf @@ -11,7 +11,7 @@ sendmail_path = /usr/sbin/sendmail.postfix setgid_group = postdrop command_directory = /usr/sbin manpage_directory = /usr/share/man -daemon_directory = <%= lib_dir %>/postfix/ +daemon_directory = /usr/libexec/postfix/ data_directory = /var/lib/postfix newaliases_path = /usr/bin/newaliases mailq_path = /usr/bin/mailq @@ -22,11 +22,10 @@ mail_owner = postfix myhostname = <%= fqdn %> mydomain = <%= domain %> -inet_interfaces = localhost inet_protocols = all mynetworks_style = host #delay_warning_time = 4h -smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) (Mandriva Linux) +smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) (Mageia Linux) unknown_local_recipient_reject_code = 450 smtp-filter_destination_concurrency_limit = 2 lmtp-filter_destination_concurrency_limit = 2 @@ -34,3 +33,19 @@ smtpd_use_tls = yes smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem smtpd_tls_key_file = /etc/pki/tls/private/postfix.pem smtpd_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt + +<%- if classes.include?('sympa::server') -%> +local_recipient_maps = +fallback_transport_maps = regexp:/etc/postfix/transport_regexp +transport_maps = regexp:/etc/postfix/transport_regexp +mydestination = ml.<%= domain %> +sympa_destination_recipient_limit = 1 +sympabounce_destination_recipient_limit = 1 +virtual_alias_maps = regexp:/etc/postfix/sympa_aliases +# needed by sympa to handle bounce, according to the doc +recipient_delimiter = + +# This is ugly for a simple relay but we need ml.mageia.org to accept email :( +inet_interfaces = all +<%- else -%> +inet_interfaces = localhost +<%- end -%> diff --git a/modules/postfix/templates/sympa_aliases b/modules/postfix/templates/sympa_aliases index e5f74c0b..436e7a28 100644 --- a/modules/postfix/templates/sympa_aliases +++ b/modules/postfix/templates/sympa_aliases @@ -1,5 +1,5 @@ # everything is handled with transports in postfix, -# but according to http://www.sympa.org/faq/postfix, we also need this one +# but according to https://www.sympa.org/faq/postfix, we also need this one <% escaped_domain = ( 'ml.' + domain ).sub('.','\.') %> /^(.*)-owner\@<%= escaped_domain %>$/ $1+owner@ml.<%= domain %> # redirect the mail from the ml domain to sysadmin diff --git a/modules/postfix/templates/transport_regexp b/modules/postfix/templates/transport_regexp index ceb8e2fb..3eb5494f 100644 --- a/modules/postfix/templates/transport_regexp +++ b/modules/postfix/templates/transport_regexp @@ -3,15 +3,8 @@ ml_domain = 'ml\.' + domain.gsub('.','\.') %> <%- if classes.include?('sympa::server') -%> /^.*+owner\@<%= ml_domain %>$/ sympabounce: +/^bounce+.*\@<%= ml_domain %>$/ sympabounce: /^.*\@<%= ml_domain %>$/ sympa: +<%- else -%> +/^.*\@<%= ml_domain %>$/ smtp:sucuk.mageia.org <%- end -%> - -# temporary work around for bugzilla being unable to send mail to webteam -# -# the current setup ( 13/02/2011 ) is that most active mls are on zarb.org, -# using @mageia domain. But we want to start hosting aliases on the current -# ml server ( and main smtp, ie alamut ). So we need to dispatch old mls -# to zarb, and the rest on alamut. Old mls are all prefixed by mageia-*@mageia -# this hack should be removed once all mls are migrated from zarb.org -# -/^mageia-.*\@<%= domain %>$/ smtp:ryu.zarb.org diff --git a/modules/postfix/templates/virtual_aliases b/modules/postfix/templates/virtual_aliases index 0890dd06..861e79c6 100644 --- a/modules/postfix/templates/virtual_aliases +++ b/modules/postfix/templates/virtual_aliases @@ -1,16 +1,22 @@ # do not forget to add $domain or it will not work # do not hardcode the domain, or it will be harvested by bot -treasurer@<%= domain %> rda@<%= domain %> +treasurer@<%= domain %> treasurer@group.<%= domain %> president@<%= domain %> ennael@<%= domain %> secretary@<%= domain %> obgr_seneca@<%= domain %> +contact@<%= domain %> council@group.<%= domain %> +press@<%= domain %> council@group.<%= domain %> + # later switch to a team alias root@<%= domain %> sysadmin@group.<%= domain %> -security@<%= domain %> security_officers@group.<%= domain %> +security@<%= domain %> security@group.<%= domain %> + +# Temporary(?) alias until there is a real board-commits@ list +board-commits@ml.<%= domain %> board-public@ml.<%= domain %> -# TODO see http://www.ietf.org/rfc/rfc2142.txt +# TODO see https://www.ietf.org/rfc/rfc2142.txt <% ['postmaster','hostmaster','abuse','noc','listmaster','MAILER-DAEMON'].each { |a| %> diff --git a/modules/postgresql/manifests/database.pp b/modules/postgresql/manifests/database.pp index 82670b5e..34cee2a6 100644 --- a/modules/postgresql/manifests/database.pp +++ b/modules/postgresql/manifests/database.pp @@ -3,15 +3,16 @@ define postgresql::database($description = '', $user = 'postgres', $callback_notify = '') { - exec { "createdb -O $user -U postgres $name '$description'": + exec { "createdb -O ${user} -U postgres ${name} '${description}' ": user => 'root', - unless => "psql -A -t -U postgres -l | grep '^$name|'", + unless => "psql -A -t -U postgres -l | grep '^${name}|'", require => Service['postgresql'], } # this is fetched by the manifest asking the database creation, # once the db have been created # FIXME proper ordering ? + # FIXME In puppet >3.0 word 'tag' is reserved, so it has to be renamed @@postgresql::database_callback { $name: tag => $name, callback_notify => $callback_notify, diff --git a/modules/postgresql/manifests/database_callback.pp b/modules/postgresql/manifests/database_callback.pp index 8d4b217c..0ab1771f 100644 --- a/modules/postgresql/manifests/database_callback.pp +++ b/modules/postgresql/manifests/database_callback.pp @@ -1,7 +1,7 @@ define postgresql::database_callback($callback_notify = '') { # dummy declaration, so we can trigger the notify if $callback_notify { - exec { "callback $name": + exec { "callback ${name}": command => '/bin/true', notify => $callback_notify, } diff --git a/modules/postgresql/manifests/hba_entry.pp b/modules/postgresql/manifests/hba_entry.pp new file mode 100644 index 00000000..30fccda0 --- /dev/null +++ b/modules/postgresql/manifests/hba_entry.pp @@ -0,0 +1,40 @@ +# == Define: postgresql::hba_entry +# +# Set a new entry to pg_hba.conf file +# +# === Parameters +# +# See pgsql doc for more details about pg_hba.conf parameters : +# https://www.postgresql.org/docs/9.1/static/auth-pg-hba-conf.html +# +# [*namevar*] +# namevar is not used. +# +# [*type*] +# can be local, host, hostssl, hostnossl +# +# [*database*] +# database name +# +# [*user*] +# user name +# +# [*address*] +# host name or IP address range +# +# [*method*] +# authentication method to use +# +define postgresql::hba_entry( + $type, + $database, + $user, + $address, + $method +) { + include postgresql::var + Postgresql::Pg_hba <| title == $postgresql::var::hba_file |> { + conf_lines +> "${type} ${database} ${user} ${address} ${method}", + } +} +# vim: sw=2 diff --git a/modules/postgresql/manifests/pg_hba.pp b/modules/postgresql/manifests/pg_hba.pp new file mode 100644 index 00000000..777eee47 --- /dev/null +++ b/modules/postgresql/manifests/pg_hba.pp @@ -0,0 +1,13 @@ +define postgresql::pg_hba( + $conf_lines = [] +) { + $db = list_exported_ressources('Postgresql::Db_and_user') + + $forum_lang = list_exported_ressources('Phpbb::Locale_db') + +# (tmb) disable rewriting config as we are moving to mariadb +# postgresql::config { $name: +# content => template('postgresql/pg_hba.conf'), +# } +} +# vim: sw=2 diff --git a/modules/postgresql/manifests/remote_database.pp b/modules/postgresql/manifests/remote_database.pp index 19beb712..15b54651 100644 --- a/modules/postgresql/manifests/remote_database.pp +++ b/modules/postgresql/manifests/remote_database.pp @@ -1,3 +1,4 @@ +# FIXME: In puppet >3.0 word 'tag' is reserved, so it has to be renamed define postgresql::remote_database($description = '', $user = 'postgresql', $callback_notify = '', diff --git a/modules/postgresql/manifests/remote_db_and_user.pp b/modules/postgresql/manifests/remote_db_and_user.pp index bb331304..07e3ea23 100644 --- a/modules/postgresql/manifests/remote_db_and_user.pp +++ b/modules/postgresql/manifests/remote_db_and_user.pp @@ -1,3 +1,4 @@ +# FIXME: In puppet >3.0 word 'tag' is reserved, so it have to be renamed define postgresql::remote_db_and_user($password, $description = '', $tag = 'default', @@ -10,7 +11,7 @@ define postgresql::remote_db_and_user($password, password => $password, } - # fetch the exported ressources that should have been exported + # fetch the exported resources that should have been exported # once the db was created, and trigger a notify to the object # passed as callback_notify Postgresql::Database_callback <<| tag == $name |>> diff --git a/modules/postgresql/manifests/remote_user.pp b/modules/postgresql/manifests/remote_user.pp index ed2bf033..fb53df4c 100644 --- a/modules/postgresql/manifests/remote_user.pp +++ b/modules/postgresql/manifests/remote_user.pp @@ -1,3 +1,4 @@ +# FIXME: In puppet >3.0 word 'tag' is reserved, so it have to be renamed define postgresql::remote_user( $password, $tag = 'default') { @@postgresql::user { $name: diff --git a/modules/postgresql/manifests/server.pp b/modules/postgresql/manifests/server.pp index 84be87ad..8b92bb2b 100644 --- a/modules/postgresql/manifests/server.pp +++ b/modules/postgresql/manifests/server.pp @@ -1,15 +1,14 @@ class postgresql::server { - $pgsql_data = '/var/lib/pgsql/data/' - $pg_version = '9.0' + include postgresql::var # missing requires is corrected in cooker, # should be removed # once the fix is in a stable release - package { "postgresql${pg_version}-plpgsql": + package { "postgresql${postgresql::var::pg_version}-plpgsql": alias => 'postgresql-plpgsql', } - package { "postgresql${pg_version}-server": + package { "postgresql${postgresql::var::pg_version}-server": alias => 'postgresql-server', require => Package['postgresql-plpgsql'], } @@ -22,9 +21,9 @@ class postgresql::server { refreshonly => true, } - openssl::self_signed_splitted_cert { "pgsql.$::domain": + openssl::self_signed_splitted_cert { "pgsql.${::domain}": filename => 'server', - directory => $pgsql_data, + directory => $postgresql::var::pgsql_data, owner => 'postgres', group => 'postgres', require => Package['postgresql-server'] @@ -35,16 +34,20 @@ class postgresql::server { content => template('postgresql/pam'), } - $db = list_exported_ressources('Postgresql::Db_and_user') + @postgresql::pg_hba { $postgresql::var::hba_file: } - $forum_lang = list_exported_ressources('Phpbb::Locale_db') + postgresql::hba_entry { 'allow_local_ipv4': + type => 'host', + database => 'all', + user => 'all', + address => '127.0.0.1/32', + method => 'md5', + } postgresql::config { - "$pgsql_data/pg_hba.conf": - content => template('postgresql/pg_hba.conf'); - "$pgsql_data/pg_ident.conf": + "${postgresql::var::pgsql_data}/pg_ident.conf": content => template('postgresql/pg_ident.conf'); - "$pgsql_data/postgresql.conf": + "${postgresql::var::pgsql_data}/postgresql.conf": content => template('postgresql/postgresql.conf'); } } diff --git a/modules/postgresql/manifests/tagged.pp b/modules/postgresql/manifests/tagged.pp index 56cdc033..6a49e3ff 100644 --- a/modules/postgresql/manifests/tagged.pp +++ b/modules/postgresql/manifests/tagged.pp @@ -1,3 +1,4 @@ +# FIXME: In puppet >3.0 word 'tag' is reserved, so it have to be renamed define postgresql::tagged() { # TODO add a system of tag so we can declare database on more than one # server diff --git a/modules/postgresql/manifests/user.pp b/modules/postgresql/manifests/user.pp index b70dd122..5b73b243 100644 --- a/modules/postgresql/manifests/user.pp +++ b/modules/postgresql/manifests/user.pp @@ -1,13 +1,13 @@ # TODO convert to a regular type, so we can later change password # without erasing the current user define postgresql::user($password) { - $sql = "CREATE ROLE $name ENCRYPTED PASSWORD '\$pass' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;" + $sql = "CREATE ROLE ${name} ENCRYPTED PASSWORD '\${pass}' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;" - exec { "psql -U postgres -c \"$sql\" ": + exec { "psql -U postgres -c \"${sql}\" ": user => 'root', # do not leak the password on commandline - environment => "pass=$password", - unless => "psql -A -t -U postgres -c '\\du $name' | grep '$name'", + environment => "pass=${password}", + unless => "psql -A -t -U postgres -c '\\du ${name}' | grep '${name}'", require => Service['postgresql'], } } diff --git a/modules/postgresql/manifests/var.pp b/modules/postgresql/manifests/var.pp new file mode 100644 index 00000000..b31c7ffe --- /dev/null +++ b/modules/postgresql/manifests/var.pp @@ -0,0 +1,7 @@ +class postgresql::var { + + $pgsql_data = '/var/lib/pgsql/data/' + $pg_version = '9.6' + $hba_file = "${pgsql_data}/pg_hba.conf" +} +# vim: sw=2 diff --git a/modules/postgresql/templates/pg_hba.conf b/modules/postgresql/templates/pg_hba.conf index 91012a30..e4232a4e 100644 --- a/modules/postgresql/templates/pg_hba.conf +++ b/modules/postgresql/templates/pg_hba.conf @@ -75,8 +75,14 @@ # TYPE DATABASE USER CIDR-ADDRESS METHOD -# This file is in mageia svn: -# $Id$ + +<%- + for line in @conf_lines +-%> +<%= line %> +<%- + end +-%> # Nanar: # This bypass global config for specific user/base @@ -114,11 +120,11 @@ host template1 bugs ::1/128 md5 hostssl template1 bugs 212.85.158.146/32 md5 hostssl template1 bugs 2a02:2178:2:7::2/128 md5 -# Allow youri-ckeck on rabbit to access the results db +# Allow youri-check on rabbit to access the results db hostssl youri_check youri 88.190.12.224/32 md5 # Allow local access too -hostssl youri_check youri 212.85.158.146/32 md5 -hostssl youri_check youri 2a02:2178:2:7::2/128 md5 +hostssl youri_check youri 212.85.158.151/32 md5 +hostssl youri_check youri 2a02:2178:2:7::7/128 md5 # "local" is for Unix domain socket connections only local all all ident map=local diff --git a/modules/postgresql/templates/postgresql.conf b/modules/postgresql/templates/postgresql.conf index 813c0910..c1e7c994 100644 --- a/modules/postgresql/templates/postgresql.conf +++ b/modules/postgresql/templates/postgresql.conf @@ -113,7 +113,7 @@ ssl = on # - Memory - -shared_buffers = 24MB # min 128kB +shared_buffers = 2048MB # min 128kB # (change requires restart) #temp_buffers = 8MB # min 800kB #max_prepared_transactions = 0 # zero disables the feature @@ -122,8 +122,8 @@ shared_buffers = 24MB # min 128kB # per transaction slot, plus lock space (see max_locks_per_transaction). # It is not advisable to set max_prepared_transactions nonzero unless you # actively intend to use prepared transactions. -#work_mem = 1MB # min 64kB -#maintenance_work_mem = 16MB # min 1MB +work_mem = 64MB # min 64kB +maintenance_work_mem = 512MB # min 1MB #max_stack_depth = 2MB # min 100kB # - Kernel Resource Usage - @@ -144,7 +144,7 @@ shared_buffers = 24MB # min 128kB #bgwriter_delay = 200ms # 10-10000ms between rounds #bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round -#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round +#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round # - Asynchronous Behavior - @@ -235,7 +235,7 @@ shared_buffers = 24MB # min 128kB #cpu_tuple_cost = 0.01 # same scale as above #cpu_index_tuple_cost = 0.005 # same scale as above #cpu_operator_cost = 0.0025 # same scale as above -#effective_cache_size = 128MB +effective_cache_size = 4096MB # - Genetic Query Optimizer - @@ -467,7 +467,7 @@ shared_buffers = 24MB # min 128kB datestyle = 'iso, mdy' #intervalstyle = 'postgres' -#timezone = unknown # actually, defaults to TZ environment +timezone = 'Europe/Paris' # actually, defaults to TZ environment # setting #timezone_abbreviations = 'Default' # Select the set of available time zone # abbreviations. Currently, there are diff --git a/modules/postgrey/templates/postgrey.sysconfig b/modules/postgrey/templates/postgrey.sysconfig index ec4e6947..f08b8f6f 100644 --- a/modules/postgrey/templates/postgrey.sysconfig +++ b/modules/postgrey/templates/postgrey.sysconfig @@ -1,12 +1,10 @@ # change default configuration option here -# SOCKET=$(postconf -h queue_directory)/extern/postgrey/socket -# OPTIONS="--unix=$SOCKET" -# DBPATH=/var/lib/postgrey -# OPTIONS="$OPTIONS --dbdir=$DBPATH" +# default: unix socket +SOCKET="--unix=/var/spool/postfix/extern/postgrey/socket" -# to use an inet connection instead of a socket -#OPTIONS="--inet=127.0.0.1:10031" +# to use an inet socket instead +#SOCKET="--inet=127.0.0.1:10031" # enable whitelisting OPTIONS="$OPTIONS --auto-whitelist-clients" diff --git a/modules/postgrey/templates/whitelist_clients.local b/modules/postgrey/templates/whitelist_clients.local index 7510506d..8c87b88c 100644 --- a/modules/postgrey/templates/whitelist_clients.local +++ b/modules/postgrey/templates/whitelist_clients.local @@ -1,7 +1,2 @@ -# zarb -ryu.zarb.org -cthulhu.zarb.org # mageia -*.<%= domain %> -# for damsweb mail server -/mail-out\.ovh\.net$/ +<%= domain %> diff --git a/modules/puppet/manifests/client.pp b/modules/puppet/manifests/client.pp index 38857810..1168373b 100644 --- a/modules/puppet/manifests/client.pp +++ b/modules/puppet/manifests/client.pp @@ -2,7 +2,7 @@ class puppet::client inherits puppet { cron { 'puppet': ensure => present, - command => '/usr/sbin/puppetd -o --no-daemonize -l syslog >/dev/null 2>&1', + command => 'puppet agent --onetime --no-daemonize -l syslog >/dev/null 2>&1', user => 'root', minute => fqdn_rand( 60 ), } diff --git a/modules/puppet/manifests/hiera.pp b/modules/puppet/manifests/hiera.pp index 8b692316..02900cd7 100644 --- a/modules/puppet/manifests/hiera.pp +++ b/modules/puppet/manifests/hiera.pp @@ -1,12 +1,5 @@ class puppet::hiera { - package { ['ruby-hiera','ruby-hiera-puppet']: } - - # ugly, remove once hiera is either fixed or integrated to puppet - file { '/etc/puppet/external/hiera': - ensure => link, - target => '/usr/lib/ruby/gems/1.8/gems/hiera-puppet-0.3.0/', - require => Package['ruby-hiera-puppet'], - } + package { ['ruby-hiera']: } # ease the use fo the command line tool # who use a different location for the config file diff --git a/modules/puppet/manifests/master.pp b/modules/puppet/manifests/master.pp index 1d2420a5..55529466 100644 --- a/modules/puppet/manifests/master.pp +++ b/modules/puppet/manifests/master.pp @@ -6,7 +6,8 @@ class puppet::master inherits puppet { # do not enable until bug 4591 is solved # include puppet::thin - package { ["ruby-$puppet::stored_config::database", 'ruby-rails']: } + # rails and sqlite3 are used for stored config + package { ["ruby-${puppet::stored_config::database}"]: } File['/etc/puppet/puppet.conf'] { content => template('puppet/puppet.conf', @@ -15,13 +16,12 @@ class puppet::master inherits puppet { } - # rails and sqlite3 are used for stored config package { 'puppet-server': } service { 'puppetmaster': # uncomment once thin is enabled -# ensure => stopped, - subscribe => [Package['puppet-server'], +# ensure => stopped, + subscribe => [Package['puppet-server'], File['/etc/puppet/puppet.conf']], } diff --git a/modules/puppet/manifests/queue.pp b/modules/puppet/manifests/queue.pp index d68fd63c..770fc6df 100644 --- a/modules/puppet/manifests/queue.pp +++ b/modules/puppet/manifests/queue.pp @@ -5,7 +5,7 @@ class puppet::queue { service { 'puppetqd': provider => base, - start => '/usr/sbin/puppetqd', + start => 'puppet queue', require => [Package['puppet-server'], Package['ruby-stomp'], File['/etc/puppet/puppet.conf']], diff --git a/modules/puppet/manifests/stored_config.pp b/modules/puppet/manifests/stored_config.pp index 9b19702b..51820d83 100644 --- a/modules/puppet/manifests/stored_config.pp +++ b/modules/puppet/manifests/stored_config.pp @@ -9,7 +9,7 @@ class puppet::stored_config { # # if ($::environment == 'production') { # # FIXME not really elegant, but we do not have much choice -# # this make servers not bootstrapable for now +# # this make servers not bootstrappable for now # $pgsql_password = extlookup('puppet_pgsql','x') # # postgresql::remote_db_and_user { 'bugs': diff --git a/modules/puppet/manifests/thin.pp b/modules/puppet/manifests/thin.pp index 0c6259e4..1ca03a7e 100644 --- a/modules/puppet/manifests/thin.pp +++ b/modules/puppet/manifests/thin.pp @@ -1,6 +1,7 @@ class puppet::thin { package { 'ruby-thin': } + include apache::base include apache::mod::ssl include apache::mod::proxy @@ -8,7 +9,7 @@ class puppet::thin { vhost_file => 'puppet/apache_proxy_vhost.conf', } - apache::config { '/etc/httpd/conf.d/puppet.conf': + apache::config { "${apache::base::conf_d}/puppet.conf": content => 'Listen 8140', } diff --git a/modules/puppet/templates/apache_proxy_vhost.conf b/modules/puppet/templates/apache_proxy_vhost.conf index d1e797e2..89157fc2 100644 --- a/modules/puppet/templates/apache_proxy_vhost.conf +++ b/modules/puppet/templates/apache_proxy_vhost.conf @@ -1,7 +1,7 @@ ProxyRequests Off <Proxy balancer://puppet> -# TODO dynamically ajust that with a variable +# TODO dynamically adjust that with a variable BalancerMember http://127.0.0.1:18140 BalancerMember http://127.0.0.1:18141 BalancerMember http://127.0.0.1:18142 @@ -40,4 +40,3 @@ ProxyRequests Off ProxyPreserveHost on </VirtualHost> - diff --git a/modules/puppet/templates/hiera.yaml b/modules/puppet/templates/hiera.yaml index 84e75607..fcef4278 100644 --- a/modules/puppet/templates/hiera.yaml +++ b/modules/puppet/templates/hiera.yaml @@ -1,10 +1,9 @@ --- -:backends: - yaml - -:logger: console - -:hierarchy: - %{env} - - common +:backends: + - yaml :yaml: - :datadir: /etc/puppet/hieradata - + :datadir: /etc/puppet/hieradata +:logger: console +:hierarchy: + - "%{::environment}" + - common diff --git a/modules/puppet/templates/puppet.agent.conf b/modules/puppet/templates/puppet.agent.conf index b08a903b..44dfedb7 100644 --- a/modules/puppet/templates/puppet.agent.conf +++ b/modules/puppet/templates/puppet.agent.conf @@ -15,7 +15,7 @@ environment = <%= environment %> <% end %> # The file in which puppetd stores a list of the classes - # associated with the retrieved configuratiion. Can be loaded in + # associated with the retrieved configuration. Can be loaded in # the separate ``puppet`` executable using the ``--loadclasses`` # option. # The default value is '$confdir/classes.txt'. diff --git a/modules/puppet/templates/puppet.conf b/modules/puppet/templates/puppet.conf index fdda64ab..28e8c363 100644 --- a/modules/puppet/templates/puppet.conf +++ b/modules/puppet/templates/puppet.conf @@ -1,5 +1,8 @@ <% db_config = scope.lookupvar('puppet::stored_config::db_config') %> [main] + # listen on both ipv4 and ipv6 + bindaddress = * + # The Puppet log directory. # The default value is '$vardir/log'. logdir = /var/log/puppet @@ -11,10 +14,8 @@ # Where SSL certificates are kept. # The default value is '$confdir/ssl'. ssldir = $vardir/ssl - + modulepath = $confdir/modules:$confdir/deployment:$confdir/external:/usr/share/puppet/modules queue_type = stomp queue_source = stomp://localhost:61613 <%= db_config %> - - diff --git a/modules/restrictshell/manifests/allow.pp b/modules/restrictshell/manifests/allow.pp index 361ee4a7..cb1fd9a2 100644 --- a/modules/restrictshell/manifests/allow.pp +++ b/modules/restrictshell/manifests/allow.pp @@ -1,7 +1,7 @@ define restrictshell::allow { include shell - file { "/etc/membersh-conf.d/allow_$name.pl": + file { "/etc/membersh-conf.d/allow_${name}.pl": mode => '0755', - content => "\$use_$name = 1;\n", + content => "\$use_${name} = 1;\n", } } diff --git a/modules/restrictshell/manifests/shell.pp b/modules/restrictshell/manifests/shell.pp index 77044ed4..3ef2a036 100644 --- a/modules/restrictshell/manifests/shell.pp +++ b/modules/restrictshell/manifests/shell.pp @@ -3,7 +3,7 @@ class restrictshell::shell { ensure => directory, } - mga-common::local_script { 'sv_membersh.pl': + mga_common::local_script { 'sv_membersh.pl': content => template('restrictshell/sv_membersh.pl'), } diff --git a/modules/restrictshell/templates/membersh-conf.pl b/modules/restrictshell/templates/membersh-conf.pl index ea7d2957..9e0c8bf5 100755 --- a/modules/restrictshell/templates/membersh-conf.pl +++ b/modules/restrictshell/templates/membersh-conf.pl @@ -5,13 +5,13 @@ $regexp_svn = "^svnserve -t\$"; #@prepend_args_svn = ( '-r', '/svn' ); @prepend_args_svn = (); -$bin_git = "/usr/bin/git-shell"; +$bin_git = "/usr/share/gitolite/gitolite-shell"; $bin_rsync = "/usr/bin/rsync"; $regexp_rsync = "^rsync --server"; $regexp_dir_rsync = "^/.*"; -$bin_sftp = "<%= lib_dir %>/ssh/sftp-server"; +$bin_sftp = "<%= @lib_dir %>/ssh/sftp-server"; $regexp_sftp = "^(/usr/lib{64,}/ssh/sftp-server|/usr/lib/sftp-server|/usr/libexec/sftp-server|/usr/lib/openssh/sftp-server)"; foreach my $f (glob("/etc/membersh-conf.d/allow_*pl")) { diff --git a/modules/restrictshell/templates/sv_membersh.pl b/modules/restrictshell/templates/sv_membersh.pl index 155bc300..0b07f23a 100644 --- a/modules/restrictshell/templates/sv_membersh.pl +++ b/modules/restrictshell/templates/sv_membersh.pl @@ -147,10 +147,11 @@ if ($#ARGV == 1 and $ARGV[0] eq "-c") { push( @args, @args_user ); exec($bin_svn, @args) or die("Failed to exec $bin_svn: $!"); - } elsif ($use_git and $ARGV[1] =~ m:^git-.+:) { + } elsif ($use_git and $ARGV[1] =~ m:^$bin_git\b:) { - # Delegate filtering to git-shell - exec($bin_git, @ARGV) or die("Failed to exec $bin_git: $!"); + # Delegate filtering to gitolite-shell + my ($gitolite_bin, @rest) = split(' ', $ARGV[1]); + exec($bin_git, @rest) or die("Failed to exec $bin_git: $!"); } elsif ($use_pkgsubmit and $ARGV[1] =~ m:$regexp_pkgsubmit:) { @@ -169,7 +170,7 @@ if ($#ARGV == 1 and $ARGV[0] eq "-c") { } unless (-e "/etc/membersh-errormsg") { - if ($ARGV) { + if (@ARGV) { print STDERR "You tried to execute: @ARGV[1..$#ARGV]\n"; } else { print STDERR "You tried to run a interactive shell.\n" diff --git a/modules/rsnapshot/manifests/init.pp b/modules/rsnapshot/manifests/init.pp index fdfa1616..5d145172 100644 --- a/modules/rsnapshot/manifests/init.pp +++ b/modules/rsnapshot/manifests/init.pp @@ -1,30 +1,30 @@ class rsnapshot { - class base($confdir = '/backups/conf') { - package { ['rsnapshot']: } + class base($confdir = '/data/backups/conf') { + package { ['rsnapshot']: } - file { $confdir: - ensure => directory, - owner => root, - group => root, - mode => 0700, - } + file { $confdir: + ensure => directory, + owner => root, + group => root, + mode => '0700', + } - @rsnapshot::cron_file { 'hourly': } - @rsnapshot::cron_file { 'daily': } - @rsnapshot::cron_file { 'weekly': } - @rsnapshot::cron_file { 'monthly': } + @rsnapshot::cron_file { 'hourly': } + @rsnapshot::cron_file { 'daily': } + @rsnapshot::cron_file { 'weekly': } + @rsnapshot::cron_file { 'monthly': } } define cron_file($rsnapshot_conf = []) { - $filepath = "/tmp/cron.${name}_rsnapshot-backups" - $rsnapshot_arg = $name - file { $filepath: - ensure => present, - content => template('rsnapshot/cron_file'), - owner => root, - group => root, - mode => 0755, - } + $filepath = "/tmp/cron.${name}_rsnapshot-backups" + $rsnapshot_arg = $name + file { $filepath: + ensure => present, + content => template('rsnapshot/cron_file'), + owner => root, + group => root, + mode => '0755', + } } # - 'backup' is an array of "source destination" to backup @@ -33,42 +33,42 @@ class rsnapshot { # backups that should be kept. If you don't want hourly, daily, # weekly or monthly backups, set ${x}_interval to '0' define backup( - $snapshot_root = '/backups', - $one_fs = '1', - $backup = [], - $backup_script = [], - $hourly_interval = '0', - $daily_interval = '6', - $weekly_interval = '4', - $monthly_interval = '3' + $snapshot_root = '/data/backups', + $one_fs = '1', + $backup = [], + $backup_script = [], + $hourly_interval = '0', + $daily_interval = '6', + $weekly_interval = '4', + $monthly_interval = '3' ) { - $conffile = "${rsnapshot::base::confdir}/${name}.conf" - file { $conffile: - owner => root, - group => root, - mode => 0700, - content => template('rsnapshot/rsnapshot.conf'), - } + $conffile = "${rsnapshot::base::confdir}/${name}.conf" + file { $conffile: + owner => root, + group => root, + mode => '0700', + content => template('rsnapshot/rsnapshot.conf'), + } - if ($hourly_interval != '0') { - Rsnapshot::Cron_file <| title == 'hourly' |> { - rsnapshot_conf +> $conffile, - } - } - if ($daily_interval != '0') { - Rsnapshot::Cron_file <| title == 'daily' |> { - rsnapshot_conf +> $conffile, - } - } - if ($weekly_interval != '0') { - Rsnapshot::Cron_file <| title == 'weekly' |> { - rsnapshot_conf +> $conffile, - } - } - if ($monthly_interval != '0') { - Rsnapshot::Cron_file <| title == 'monthly' |> { - rsnapshot_conf +> $conffile, - } - } + if ($hourly_interval != '0') { + Rsnapshot::Cron_file <| title == 'hourly' |> { + rsnapshot_conf +> $conffile, + } + } + if ($daily_interval != '0') { + Rsnapshot::Cron_file <| title == 'daily' |> { + rsnapshot_conf +> $conffile, + } + } + if ($weekly_interval != '0') { + Rsnapshot::Cron_file <| title == 'weekly' |> { + rsnapshot_conf +> $conffile, + } + } + if ($monthly_interval != '0') { + Rsnapshot::Cron_file <| title == 'monthly' |> { + rsnapshot_conf +> $conffile, + } + } } } diff --git a/modules/rsnapshot/templates/rsnapshot.conf b/modules/rsnapshot/templates/rsnapshot.conf index d3da0495..4eeee4d0 100644 --- a/modules/rsnapshot/templates/rsnapshot.conf +++ b/modules/rsnapshot/templates/rsnapshot.conf @@ -24,7 +24,7 @@ config_version 1.2 # All snapshots will be stored under this root directory. # -snapshot_root <%= snapshot_root %> +snapshot_root <%= @snapshot_root %> # If no_create_root is enabled, rsnapshot will not automatically create the # snapshot_root directory. This is particularly useful if you are backing @@ -201,10 +201,9 @@ link_dest 1 ############################### <%- for b in @backup -%> -backup <%= b %> +<%= b.split().unshift("backup").join("\t") %> <%- end -%> <%- for bs in @backup_script -%> -backup_script <%= bs %> +<%= bs.split().unshift("backup_script").join("\t") %> <%- end -%> - diff --git a/modules/rsyncd/templates/xinetd b/modules/rsyncd/templates/xinetd index 3359ca84..b477e413 100644 --- a/modules/rsyncd/templates/xinetd +++ b/modules/rsyncd/templates/xinetd @@ -8,8 +8,8 @@ service rsync server_args = --daemon log_on_failure += USERID flags = IPv6 - # some mirorrs do not seems to use lock when downloading from - # us and try to download the same stuff 15 time in a row + # some mirrors do not seems to use locks when downloading from + # us and try to download the same stuff 15 times in a row per_source = 4 } diff --git a/modules/serial_console/manifests/init.pp b/modules/serial_console/manifests/init.pp new file mode 100644 index 00000000..b6716954 --- /dev/null +++ b/modules/serial_console/manifests/init.pp @@ -0,0 +1 @@ +class serial_console {} diff --git a/modules/serial_console/manifests/serial_console.pp b/modules/serial_console/manifests/serial_console.pp new file mode 100644 index 00000000..dd68c84c --- /dev/null +++ b/modules/serial_console/manifests/serial_console.pp @@ -0,0 +1,8 @@ +# name: ttyS0 +define serial_console::serial_console() { + service { "serial-getty@${name}": + provider => systemd, + ensure => running, + enable => true, + } +} diff --git a/modules/shorewall/manifests/init.pp b/modules/shorewall/manifests/init.pp index 7c8e1f55..daea6b2c 100644 --- a/modules/shorewall/manifests/init.pp +++ b/modules/shorewall/manifests/init.pp @@ -2,101 +2,101 @@ class shorewall { include concat::setup define shorewallfile () { - $filename = "/tmp/shorewall/${name}" - $header = "puppet:///modules/shorewall/headers/${name}" - $footer = "puppet:///modules/shorewall/footers/${name}" - concat{$filename: - owner => root, - group => root, - mode => 600, - } + $filename = "/tmp/shorewall/${name}" + $header = "puppet:///modules/shorewall/headers/${name}" + $footer = "puppet:///modules/shorewall/footers/${name}" + concat{$filename: + owner => root, + group => root, + mode => '0600', + } - concat::fragment{"${name}_header": - target => $filename, - order => 1, - source => $header, - } + concat::fragment{"${name}_header": + target => $filename, + order => 1, + source => $header, + } - concat::fragment{"${name}_footer": - target => $filename, - order => 99, - source => $footer, - } + concat::fragment{"${name}_footer": + target => $filename, + order => 99, + source => $footer, + } } ### Rules shorewallfile{ rules: } define rule_line($order = 50) { - $filename = "/tmp/shorewall/rules" - $line = "${name}\n" - concat::fragment{"newline_${name}": - target => $filename, - order => $order, - content => $line, - } + $filename = "/tmp/shorewall/rules" + $line = "${name}\n" + concat::fragment{"newline_${name}": + target => $filename, + order => $order, + content => $line, + } } class allow_ssh_in { - rule_line { "ACCEPT all all tcp 22": - order => 5, - } + rule_line { "ACCEPT all all tcp 22": + order => 5, + } } class allow_dns_in { - rule_line { "ACCEPT net fw tcp 53": } - rule_line { "ACCEPT net fw udp 53": } + rule_line { "ACCEPT net fw tcp 53": } + rule_line { "ACCEPT net fw udp 53": } } class allow_smtp_in { - rule_line { "ACCEPT net fw tcp 25": } + rule_line { "ACCEPT net fw tcp 25": } } class allow_www_in { - rule_line { "ACCEPT net fw tcp 80": } + rule_line { "ACCEPT net fw tcp 80": } } ### Zones shorewallfile{ zones: } define zone_line($order = 50) { - $filename = "/tmp/shorewall/zones" - $line = "${name}\n" - concat::fragment{"newline_${name}": - target => $filename, - order => $order, - content => $line, - } + $filename = "/tmp/shorewall/zones" + $line = "${name}\n" + concat::fragment{"newline_${name}": + target => $filename, + order => $order, + content => $line, + } } class default_zones { - zone_line { "net ipv4": - order => 2, - } - zone_line { "fw firewall": - order => 3, - } + zone_line { "net ipv4": + order => 2, + } + zone_line { "fw firewall": + order => 3, + } } ### Policy shorewallfile{ policy: } define policy_line($order = 50) { - $filename = "/tmp/shorewall/policy" - $line = "${name}\n" - concat::fragment{"newline_${name}": - target => $filename, - order => $order, - content => $line, - } + $filename = "/tmp/shorewall/policy" + $line = "${name}\n" + concat::fragment{"newline_${name}": + target => $filename, + order => $order, + content => $line, + } } class default_policy { - policy_line{ "fw net ACCEPT": - order => 2, - } - policy_line{ "net all DROP info": - order => 3, - } - policy_line{ "all all REJECT info": - order => 4, - } + policy_line{ "fw net ACCEPT": + order => 2, + } + policy_line{ "net all DROP info": + order => 3, + } + policy_line{ "all all REJECT info": + order => 4, + } } class default_firewall { - include default_zones - include default_policy - include allow_ssh_in + include default_zones + include default_policy + include allow_ssh_in } } diff --git a/modules/spec-tree-reports/manifests/init.pp b/modules/spec-tree-reports/manifests/init.pp new file mode 100644 index 00000000..dc78ea72 --- /dev/null +++ b/modules/spec-tree-reports/manifests/init.pp @@ -0,0 +1,50 @@ +# spec-rpm-mismatch is a report that compares the versions of RPMs available +# in the repository versus the versions created by the latest spec files and +# shows those that don't match. + +class spec-tree-reports( + $report = '/var/www/bs/spec-rpm-mismatch.html', + $srpms = 'file:///distrib/bootstrap/distrib/{version}/SRPMS/{media}/{section}/', + $release = "mga${buildsystem::var::distros::distros['cauldron']['version']}", +) { + $user = 'spec-tree-reports' + $home = "/var/lib/${user}" + $hour = 6 + $minute = 39 + + user { $user: + comment => 'spec-tree report generator', + home => $home, + } + + file { $home: + ensure => directory, + owner => $user, + mode => '0755', + } + + package { 'spec-tree': + ensure => installed, + } + + file { "${report}": + ensure => present, + owner => $user, + mode => '0644', + replace => false, + content => '*', + } + + mga_common::local_script { 'generate-spec-rpm-mismatch-report': + content => template('spec-tree-reports/generate-spec-rpm-mismatch-report'), + } + + cron { "rpm_mismatch_report": + command => "/usr/local/bin/generate-spec-rpm-mismatch-report |& systemd-cat -t generate-spec-rpm-mismatch-report", + hour => $hour, + minute => $minute, + user => $user, + environment => "MAILTO=root", + require => User[$user], + } +} diff --git a/modules/spec-tree-reports/templates/generate-spec-rpm-mismatch-report b/modules/spec-tree-reports/templates/generate-spec-rpm-mismatch-report new file mode 100644 index 00000000..4bc2db65 --- /dev/null +++ b/modules/spec-tree-reports/templates/generate-spec-rpm-mismatch-report @@ -0,0 +1,10 @@ +#!/bin/bash +# GENERATED BY PUPPET--DO NOT EDIT +set -e +trap 'test "$?" -ne 0 && echo Error in script' EXIT + +cd "$HOME" +test -e errors.log && mv -f errors.log errors.log.1 +/usr/share/doc/spec-tree/examples/generate-mismatch-report --srpm_source <%= scope.function_shellquote([scope.lookupvar('srpms')]) -%> --release <%= scope.function_shellquote([scope.lookupvar('release')]) %> +cp report.html <%= scope.function_shellquote([scope.lookupvar('report')]) %> +rm -f report.html diff --git a/modules/ssmtp/templates/ssmtp.conf b/modules/ssmtp/templates/ssmtp.conf index b535bc29..d7a9125f 100644 --- a/modules/ssmtp/templates/ssmtp.conf +++ b/modules/ssmtp/templates/ssmtp.conf @@ -1,9 +1,9 @@ -root=mageia-sysadm@<%= domain %> +root=mageia-sysadm@<%= @domain %> -mailhub=mx.<%= domain %> +mailhub=mx.<%= @domain %> rewriteDomain= # The full hostname -hostname=<%= fqdn %> +hostname=<%= @fqdn %> diff --git a/modules/subversion/manifests/client.pp b/modules/subversion/manifests/client.pp index a2aa42ee..083a58da 100644 --- a/modules/subversion/manifests/client.pp +++ b/modules/subversion/manifests/client.pp @@ -2,7 +2,7 @@ class subversion::client { # svn spam log with # Oct 26 13:30:01 valstar svn: No worthy mechs found # without it, - # http://mail-index.netbsd.org/pkgsrc-users/2008/11/23/msg008706.html + # https://mail-index.netbsd.org/pkgsrc-users/2008/11/23/msg008706.html # $sasl2_package = $::architecture ? { x86_64 => 'lib64sasl2-plug-anonymous', diff --git a/modules/subversion/manifests/hook.pp b/modules/subversion/manifests/hook.pp index 08b626ad..a29ae22d 100644 --- a/modules/subversion/manifests/hook.pp +++ b/modules/subversion/manifests/hook.pp @@ -2,7 +2,7 @@ define subversion::hook($content, $type) { $array = split($name,'\|') $repo = $array[0] $script = $array[1] - file { "$repo/hooks/$type.d/$script": + file { "${repo}/hooks/${type}.d/${script}": content => $content, mode => '0755', } diff --git a/modules/subversion/manifests/init.pp b/modules/subversion/manifests/init.pp index 01b06a62..9f009b5e 100644 --- a/modules/subversion/manifests/init.pp +++ b/modules/subversion/manifests/init.pp @@ -20,41 +20,46 @@ class subversion { package { ['perl-SVN-Notify-Config', 'perl-SVN-Notify-Mirror']: } $local_dir = '/usr/local/share/subversion/' - $local_dirs = ["$local_dir/pre-commit.d", "$local_dir/post-commit.d"] + $local_dirs = ["${local_dir}/pre-commit.d", "${local_dir}/post-commit.d"] file { [$local_dir,$local_dirs]: ensure => directory, } # workaround the lack of umask command in puppet < 2.7 - mga-common::local_script { 'create_svn_repo.sh': + mga_common::local_script { 'create_svn_repo.sh': content => template('subversion/create_svn_repo.sh') } - file { "$local_dir/pre-commit.d/no_binary": + file { "${local_dir}/pre-commit.d/no_binary": mode => '0755', content => template('subversion/no_binary') } - file { "$local_dir/pre-commit.d/no_root_commit": + file { "${local_dir}/pre-commit.d/no_root_commit": mode => '0755', content => template('subversion/no_root_commit') } - file { "$local_dir/pre-commit.d/no_empty_message": + file { "${local_dir}/pre-commit.d/no_empty_message": mode => '0755', content => template('subversion/no_empty_message') } - file { "$local_dir/pre-commit.d/single_word_commit": + file { "${local_dir}/pre-commit.d/single_word_commit": mode => '0755', content => template('subversion/single_word_commit') } - file { "$local_dir/pre-revprop-change": + file { "${local_dir}/pre-revprop-change": mode => '0755', content => template('subversion/pre-revprop-change') } + file { "${local_dir}/pre-commit.d/converted_to_git": + mode => '0755', + content => template('subversion/converted_to_git') + } + # TODO : add check for # - ym perl -MYAML -e 'YAML::LoadFile("-");' # - tt ( do not seem to be possible, but this would be great ) @@ -65,7 +70,7 @@ class subversion { # - openldap , like named define syntax_check($regexp_ext,$check_cmd) { - file { "$local_dir/pre-commit.d/$name": + file { "${subversion::server::local_dir}/pre-commit.d/${name}": mode => '0755', content => template('subversion/syntax_check.sh') } diff --git a/modules/subversion/manifests/mirror.pp b/modules/subversion/manifests/mirror.pp index 27741752..2285ecb2 100644 --- a/modules/subversion/manifests/mirror.pp +++ b/modules/subversion/manifests/mirror.pp @@ -1,6 +1,6 @@ class subversion::mirror { include subversion::tools - mga-common::local_script { 'create_svn_mirror.sh': + mga_common::local_script { 'create_svn_mirror.sh': content => template('subversion/create_svn_mirror.sh') } } diff --git a/modules/subversion/manifests/mirror_repository.pp b/modules/subversion/manifests/mirror_repository.pp index cf41ea63..1e0fabd3 100644 --- a/modules/subversion/manifests/mirror_repository.pp +++ b/modules/subversion/manifests/mirror_repository.pp @@ -2,14 +2,14 @@ define subversion::mirror_repository( $source, $refresh = '*/5') { include subversion::mirror - exec { "/usr/local/bin/create_svn_mirror.sh $name $source": + exec { "/usr/local/bin/create_svn_mirror.sh ${name} ${source}": creates => $name, require => Package['subversion-tools'] } - cron { "update $name": - command => "/usr/bin/svnsync synchronize -q file://$name", + cron { "update ${name}": + command => "/usr/bin/svnsync synchronize -q file://${name}", minute => $refresh, - require => Exec["/usr/local/bin/create_svn_mirror.sh $name $source"], + require => Exec["/usr/local/bin/create_svn_mirror.sh ${name} ${source}"], } } diff --git a/modules/subversion/manifests/pre_commit_link.pp b/modules/subversion/manifests/pre_commit_link.pp index a9b543a7..fa3c2b2c 100644 --- a/modules/subversion/manifests/pre_commit_link.pp +++ b/modules/subversion/manifests/pre_commit_link.pp @@ -2,7 +2,7 @@ define subversion::pre_commit_link() { $scriptname = regsubst($name,'^.*/', '') file { $name: ensure => 'link', - target => "/usr/local/share/subversion/pre-commit.d/$scriptname", + target => "/usr/local/share/subversion/pre-commit.d/${scriptname}", mode => '0755', } } diff --git a/modules/subversion/manifests/repository.pp b/modules/subversion/manifests/repository.pp index 7f2f8356..b223e6ae 100644 --- a/modules/subversion/manifests/repository.pp +++ b/modules/subversion/manifests/repository.pp @@ -2,10 +2,10 @@ # group : group that have commit access on the svn # public : boolean if the svn is readable by anybody or not # commit_mail : array of people who will receive mail after each commit -# cia_post : send commits to cia.vc -# cia_module : name of the module to send to cia.vc -# cia_ignore_author : a regexp to ignore commits from some authors -# no_binary : do not accept files with common binary extensions +# irker_conf : hash containing irker config values. See man irkerhook +# for possible values in irker.conf. +# irkerhook_path : path to irkerhook.py script +# no_binary : do not accept files with common binary extensions # on this repository # restricted_to_user : restrict commits to select user # syntax_check : array of pre-commit script with syntax check to add @@ -16,115 +16,117 @@ define subversion::repository($group = 'svn', $public = true, $commit_mail = '', + $irker_conf = undef, + $irkerhook_path = '/usr/lib/irker/irkerhook.py', $i18n_mail = '', - $cia_post = true, - $cia_module = 'default', - $cia_ignore_author = '', $no_binary = false, $restricted_to_user = false, $syntax_check = '', $extract_dir = '') { # check permissions - # http://svnbook.red-bean.com/nightly/fr/svn.serverconfig.multimethod.html + # https://svnbook.red-bean.com/nightly/fr/svn.serverconfig.multimethod.html # $name ==> directory of the repo include subversion::server # TODO set umask -> requires puppet 2.7.0 - # unfortunatly, umask is required - # http://projects.puppetlabs.com/issues/4424 - exec { "/usr/local/bin/create_svn_repo.sh $name": + # unfortunately, umask is required + # https://projects.puppetlabs.com/issues/4424 + exec { "/usr/local/bin/create_svn_repo.sh ${name}": user => 'root', group => $group, - creates => "$name/hooks", + creates => "${name}/hooks", require => Package['subversion-tools'], } file { $name: + ensure => directory, group => $group, owner => 'root', mode => $public ? { - true => 644, - false => 640, + true => '0644', + false => '0640', }, - ensure => directory } - file { ["$name/hooks/pre-commit","$name/hooks/post-commit"]: + file { ["${name}/hooks/pre-commit","${name}/hooks/post-commit"]: mode => '0755', content => template('subversion/hook_commit.sh'), - require => Exec["/usr/local/bin/create_svn_repo.sh $name"], + require => Exec["/usr/local/bin/create_svn_repo.sh ${name}"], } - file { ["$name/hooks/post-commit.d", "$name/hooks/pre-commit.d"]: + file { ["${name}/hooks/post-commit.d", "${name}/hooks/pre-commit.d"]: ensure => directory, - require => File["$name/hooks/pre-commit"], + require => File["${name}/hooks/pre-commit"], } - file { "$name/hooks/pre-revprop-change": - ensure => "$subversion::server::local_dir/pre-revprop-change", + file { "${name}/hooks/pre-revprop-change": + ensure => "${subversion::server::local_dir}/pre-revprop-change", mode => '0755', - require => File["$name/hooks/pre-commit"], + require => File["${name}/hooks/pre-commit"], } if $restricted_to_user { - subversion::hook::pre_commit { "$name|restricted_to_user": + subversion::hook::pre_commit { "${name}|restricted_to_user": content => template('subversion/restricted_to_user'), } } else { - file { "$name/hooks/pre-commit.d/restricted_to_user": + file { "${name}/hooks/pre-commit.d/restricted_to_user": ensure => absent, } } if $commit_mail { - subversion::hook::post_commit { "$name|send_mail": + subversion::hook::post_commit { "${name}|send_mail": content => template('subversion/hook_sendmail.pl'), require => Package['perl-SVN-Notify-Config'], } } else { - file { "$name/hooks/post-commit.d/send_mail": + file { "${name}/hooks/post-commit.d/send_mail": ensure => absent, } } - if $cia_post { - subversion::hook::post_commit { "$name|cia.vc": - content => template('subversion/ciabot_svn.sh'), + if $irker_conf { + subversion::hook::post_commit { "${name}|irker": + content => template('subversion/hook_irker'), + } + file { "${name}/irker.conf": + content => template('subversion/irker.conf'), } } else { - file { "$name/hooks/post-commit.d/cia.vc": + file { "${name}/hooks/post-commit.d/irker": ensure => absent, } } if $no_binary { - pre_commit_link { "$name/hooks/pre-commit.d/no_binary": } + pre_commit_link { "${name}/hooks/pre-commit.d/no_binary": } } else { - file { "$name/hooks/pre-commit.d/no_binary": + file { "${name}/hooks/pre-commit.d/no_binary": ensure => absent, } } if $extract_dir { - subversion::hook::post_commit {"$name|extract_dir": + subversion::hook::post_commit {"${name}|extract_dir": content => template('subversion/hook_extract.pl'), require => [Package['perl-SVN-Notify-Mirror']], } } else { - file { "$name/hooks/post-commit.d/extract_dir": + file { "${name}/hooks/post-commit.d/extract_dir": ensure => absent, } } - pre_commit_link { "$name/hooks/pre-commit.d/no_empty_message": } + pre_commit_link { "${name}/hooks/pre-commit.d/no_empty_message": } + + pre_commit_link { "${name}/hooks/pre-commit.d/no_root_commit": } - pre_commit_link { "$name/hooks/pre-commit.d/no_root_commit": } + pre_commit_link { "${name}/hooks/pre-commit.d/converted_to_git": } if $syntax_check { - $syntax_check_array = regsubst($syntax_check,'^',"$name/hooks/pre-commit.d/") + $syntax_check_array = regsubst($syntax_check,'^',"${name}/hooks/pre-commit.d/") pre_commit_link { $syntax_check_array: } } } - - diff --git a/modules/subversion/manifests/snapshot.pp b/modules/subversion/manifests/snapshot.pp index 179f1ef1..00e66dde 100644 --- a/modules/subversion/manifests/snapshot.pp +++ b/modules/subversion/manifests/snapshot.pp @@ -4,18 +4,18 @@ define subversion::snapshot($source, include subversion::client - exec { "/usr/bin/svn co $source $name": + exec { "/usr/bin/svn co ${source} ${name}": creates => $name, user => $user, require => Package['subversion'], } if ($refresh != '0') { - cron { "update $name": - command => "cd $name && /usr/bin/svn update -q", + cron { "update ${name}": + command => "cd ${name} && /usr/bin/svn update -q", user => $user, minute => $refresh, - require => Exec["/usr/bin/svn co $source $name"], + require => Exec["/usr/bin/svn co ${source} ${name}"], } } } diff --git a/modules/subversion/templates/ciabot_svn.py b/modules/subversion/templates/ciabot_svn.py deleted file mode 100644 index ab7828b4..00000000 --- a/modules/subversion/templates/ciabot_svn.py +++ /dev/null @@ -1,398 +0,0 @@ -#!/usr/bin/env python -# -# This is a CIA client script for Subversion repositories, written in python. -# It generates commit messages using CIA's XML format, and can deliver them -# using either XML-RPC or email. See below for usage and cuztomization -# information. -# -# -------------------------------------------------------------------------- -# -# Copyright (c) 2004-2007, Micah Dowty -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# -------------------------------------------------------------------------- -# -# This script is cleaner and much more featureful than the shell -# script version, but won't work on systems without Python. -# -# To use the CIA bot in your Subversion repository... -# -# 1. Customize the parameters below -# -# 2. This script should be called from your repository's post-commit -# hook with the repository and revision as arguments. For example, -# you could copy this script into your repository's "hooks" directory -# and add something like the following to the "post-commit" script, -# also in the repository's "hooks" directory: -# -# REPOS="$1" -# REV="$2" -# $REPOS/hooks/ciabot_svn.py "$REPOS" "$REV" & -# -# Or, if you have multiple project hosted, you can add each -# project's name to the commandline in that project's post-commit -# hook: -# -# $REPOS/hooks/ciabot_svn.py "$REPOS" "$REV" "ProjectName" & -# -############# There are some parameters for this script that you can customize: - -class config: - # Replace this with your project's name, or always provide a project - # name on the commandline. - # - # NOTE: This shouldn't be a long description of your project. Ideally - # it is a short identifier with no spaces, punctuation, or - # unnecessary capitalization. This will be used in URLs related - # to your project, as an internal identifier, and in IRC messages. - # If you want a longer name shown for your project on the web - # interface, please use the "title" metadata key rather than - # putting that here. - # - project = "Mageia" - - # Subversion's normal directory hierarchy is powerful enough that - # it doesn't have special methods of specifying modules, tags, or - # branches like CVS does. Most projects do use a naming - # convention though that works similarly to CVS's modules, tags, - # and branches. - # - # This is a list of regular expressions that are tested against - # paths in the order specified. If a regex matches, the 'branch' - # and 'module' groups are stored and the matching section of the - # path is removed. - # - # Several common directory structure styles are below as defaults. - # Uncomment the ones you're using, or add your own regexes. - # Whitespace in the each regex are ignored. - - pathRegexes = [ - # r"^ trunk/ (?P<module>[^/]+)/ ", - # r"^ (branches|tags)/ (?P<branch>[^/]+)/ ", - # r"^ (branches|tags)/ (?P<module>[^/]+)/ (?P<branch>[^/]+)/ ", - ] - - # If your repository is accessible over the web, put its base URL here - # and 'uri' attributes will be given to all <file> elements. This means - # that in CIA's online message viewer, each file in the tree will link - # directly to the file in your repository. - repositoryURI = None - - # If your repository is accessible over the web via a tool like ViewVC - # that allows viewing information about a full revision, put a format string - # for its URL here. You can specify various substitution keys in the Python - # syntax: "%(project)s" is replaced by the project name, and likewise - # "%(revision)s" and "%(author)s" are replaced by the revision / author. - # The resulting URI is added to the data sent to CIA. After this, in CIA's - # online message viewer, the commit will link directly to the corresponding - # revision page. - revisionURI = None - # Example (works for ViewVC as used by SourceForge.net): - #revisionURI = "https://svn.sourceforge.net/viewcvs.cgi/%(project)s?view=rev&rev=%(revision)s" - - # This can be the http:// URI of the CIA server to deliver commits over - # XML-RPC, or it can be an email address to deliver using SMTP. The - # default here should work for most people. If you need to use e-mail - # instead, you can replace this with "cia@cia.navi.cx" - server = "http://cia.navi.cx" - - # The SMTP server to use, only used if the CIA server above is an - # email address. - smtpServer = "localhost" - - # The 'from' address to use. If you're delivering commits via email, set - # this to the address you would normally send email from on this host. - fromAddress = "cia-user@localhost" - - # When nonzero, print the message to stdout instead of delivering it to CIA. - debug = 0 - - -############# Normally the rest of this won't need modification - -import sys, os, re, urllib, getopt - -class File: - """A file in a Subversion repository. According to our current - configuration, this may have a module, branch, and URI in addition - to a path.""" - - # Map svn's status letters to our action names - actionMap = { - 'U': 'modify', - 'A': 'add', - 'D': 'remove', - } - - def __init__(self, fullPath, status=None): - self.fullPath = fullPath - self.path = fullPath - self.action = self.actionMap.get(status) - - def getURI(self, repo): - """Get the URI of this file, given the repository's URI. This - encodes the full path and joins it to the given URI.""" - quotedPath = urllib.quote(self.fullPath) - if quotedPath[0] == '/': - quotedPath = quotedPath[1:] - if repo[-1] != '/': - repo = repo + '/' - return repo + quotedPath - - def makeTag(self, config): - """Return an XML tag for this file, using the given config""" - attrs = {} - - if config.repositoryURI is not None: - attrs['uri'] = self.getURI(config.repositoryURI) - - if self.action: - attrs['action'] = self.action - - attrString = ''.join([' %s="%s"' % (key, escapeToXml(value,1)) - for key, value in attrs.items()]) - return "<file%s>%s</file>" % (attrString, escapeToXml(self.path)) - - -class SvnClient: - """A CIA client for Subversion repositories. Uses svnlook to - gather information""" - name = 'Python Subversion client for CIA' - version = '1.20' - - def __init__(self, repository, revision, config): - self.repository = repository - self.revision = revision - self.config = config - - def deliver(self, message): - if config.debug: - print message - else: - server = self.config.server - if server.startswith('http:') or server.startswith('https:'): - # Deliver over XML-RPC - import xmlrpclib - xmlrpclib.ServerProxy(server).hub.deliver(message) - else: - # Deliver over email - import smtplib - smtp = smtplib.SMTP(self.config.smtpServer) - smtp.sendmail(self.config.fromAddress, server, - "From: %s\r\nTo: %s\r\n" - "Subject: DeliverXML\r\n\r\n%s" % - (self.config.fromAddress, server, message)) - - def main(self): - self.collectData() - self.deliver("<message>" + - self.makeGeneratorTag() + - self.makeSourceTag() + - self.makeBodyTag() + - "</message>") - - def makeAttrTags(self, *names): - """Given zero or more attribute names, generate XML elements for - those attributes only if they exist and are non-None. - """ - s = '' - for name in names: - if hasattr(self, name): - v = getattr(self, name) - if v is not None: - # Recent Pythons don't need this, but Python 2.1 - # at least can't convert other types directly - # to Unicode. We have to take an intermediate step. - if type(v) not in (type(''), type(u'')): - v = str(v) - - s += "<%s>%s</%s>" % (name, escapeToXml(v), name) - return s - - def makeGeneratorTag(self): - return "<generator>%s</generator>" % self.makeAttrTags( - 'name', - 'version', - ) - - def makeSourceTag(self): - return "<source>%s</source>" % self.makeAttrTags( - 'project', - 'module', - 'branch', - ) - - def makeBodyTag(self): - return "<body><commit>%s%s</commit></body>" % ( - self.makeAttrTags( - 'revision', - 'author', - 'log', - 'diffLines', - 'url', - ), - self.makeFileTags(), - ) - - def makeFileTags(self): - """Return XML tags for our file list""" - return "<files>%s</files>" % ''.join([file.makeTag(self.config) - for file in self.files]) - - def svnlook(self, command): - """Run the given svnlook command on our current repository and - revision, returning all output""" - # We have to set LC_ALL to force svnlook to give us UTF-8 output, - # then we explicitly slurp that into a unicode object. - return unicode(os.popen( - 'LC_ALL="en_US.UTF-8" svnlook %s -r "%s" "%s"' % - (command, self.revision, self.repository)).read(), - 'utf-8', 'replace') - - def collectData(self): - self.author = self.svnlook('author').strip() - self.project = self.config.project - self.log = self.svnlook('log') - self.diffLines = len(self.svnlook('diff').split('\n')) - self.files = self.collectFiles() - if self.config.revisionURI is not None: - self.url = self.config.revisionURI % self.__dict__ - else: - self.url = None - - def collectFiles(self): - # Extract all the files from the output of 'svnlook changed' - files = [] - for line in self.svnlook('changed').split('\n'): - path = line[2:].strip() - if path: - status = line[0] - files.append(File(path, status)) - - # Try each of our several regexes. To be applied, the same - # regex must mach every file under consideration and they must - # all return the same results. If we find one matching regex, - # or we try all regexes without a match, we're done. - matchDict = None - for regex in self.config.pathRegexes: - matchDict = matchAgainstFiles(regex, files) - if matchDict is not None: - self.__dict__.update(matchDict) - break - - return files - - -def matchAgainstFiles(regex, files): - """Try matching a regex against all File objects in the provided list. - If the regex returns the same matches for every file, the matches - are returned in a dict and the matched portions are filtered out. - If not, returns None. - """ - prevMatchDict = None - compiled = re.compile(regex, re.VERBOSE) - for f in files: - - match = compiled.match(f.fullPath) - if not match: - # Give up, it must match every file - return None - - matchDict = match.groupdict() - if prevMatchDict is not None and prevMatchDict != matchDict: - # Give up, we got conflicting matches - return None - - prevMatchDict = matchDict - - # If we got this far, the regex matched every file with - # the same results. Now filter the matched portion out of - # each file and store the matches we found. - for f in files: - f.path = compiled.sub('', f.fullPath) - return prevMatchDict - - -def escapeToXml(text, isAttrib=0): - text = unicode(text) - text = text.replace("&", "&") - text = text.replace("<", "<") - text = text.replace(">", ">") - if isAttrib == 1: - text = text.replace("'", "'") - text = text.replace("\"", """) - return text - - -def usage(): - """Print a short usage description of this script and exit""" - sys.stderr.write("Usage: %s [OPTIONS] REPOS-PATH REVISION [PROJECTNAME]\n" % - sys.argv[0]) - - -def version(): - """Print out the version of this script""" - sys.stderr.write("%s %s\n" % (sys.argv[0], SvnClient.version)) - - -def main(): - try: - options = [ "version" ] - for key in config.__dict__: - if not key.startswith("_"): - options.append(key + "="); - opts, args = getopt.getopt(sys.argv[1:], "", options) - except getopt.GetoptError: - usage() - sys.exit(2) - - for o, a in opts: - if o == "--version": - version() - sys.exit() - else: - # Everything else maps straight to a config key. Just have - # to remove the "--" prefix from the option name. - config.__dict__[o[2:]] = a - - # Print a usage message when not enough parameters are provided. - if not len(args) in (2,3): - sys.stderr.write("%s: incorrect number of arguments\n" % sys.argv[0]) - usage(); - sys.exit(2); - - # If a project name was provided, override the default project name. - if len(args) == 3: - config.project = args[2] - - # Go do the real work. - SvnClient(args[0], args[1], config).main() - - -if __name__ == "__main__": - main() - -### The End ### diff --git a/modules/subversion/templates/ciabot_svn.sh b/modules/subversion/templates/ciabot_svn.sh deleted file mode 100755 index 63aa77a8..00000000 --- a/modules/subversion/templates/ciabot_svn.sh +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/sh -# -# This is a CIA bot client script for Subversion repositories, -# delivering via email. See below for usage and customization information. -# -# -------------------------------------------------------------------------- -# -# Copyright (c) 2004-2005, Micah Dowty -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# -------------------------------------------------------------------------- -# -# See http://cia.vc for more information on what the CIA bot -# is and how it works, and links to other client scripts. -# -# To use the CIA bot in your Subversion repository... -# -# 1. Customize the parameters below, specifically the ones under -# the "Project information" section -# -# 2. This script should be called from your repository's post-commit -# hook with the repository and revision as arguments. For example, -# you could copy this script into your repository's "hooks" directory -# and add something like the following to the "post-commit" script, -# also in the repository's "hooks" directory: -# -# REPOS="$1" -# REV="$2" -# $REPOS/hooks/ciabot_svn.sh "$REPOS" "$REV"& -# -# ------ There are some parameters for this script that you can customize: - -# Project information -# -# NOTE: This shouldn't be a long description of your project. Ideally -# it is a short identifier with no spaces, punctuation, or -# unnecessary capitalization. This will be used in URLs related -# to your project, as an internal identifier, and in IRC messages. -# If you want a longer name shown for your project on the web -# interface, please use the "title" metadata key rather than -# putting that here. -# -project_name="Mageia" -module_name="<%= cia_module %>" -return_address="root@<%= domain %>" -ignore_author="<%= cia_ignore_author %>" - -# System -sendmail_command="/usr/sbin/sendmail -t" - -############# Below this line you shouldn't have to change anything - -# Script arguments -REPOS="$1" -REV="$2" - -# The email address CIA lives at -cia_address="cia@cia.vc" - -author=`svnlook author -r "$REV" "$REPOS" | sed 's/\&/\&/g;s/</\</g;s/>/\>/g'` -if test -n "$ignore_author" && echo "$author" | grep -q "$ignore_author" -then - exit 0 -fi -log=`svnlook log -r "$REV" "$REPOS" | sed 's/\&/\&/g;s/</\</g;s/>/\>/g'` -diff_lines=`svnlook diff -r "$REV" "$REPOS" | wc -l` -for file in `svnlook changed -r "$REV" "$REPOS" | cut -c 3- | sed 's/\&/\&/g;s/</\</g;s/>/\>/g'`; do - files="$files<file>$file</file>" -done - -url="http://svnweb.<%= domain%>/${REPOS/\/svn\//}?view=revision&revision=$REV" - -# Send an email with the final XML message -(cat <<EOF -From: $return_address -To: $cia_address -Subject: DeliverXML - -<message> - <generator> - <name>Subversion CIA Bot client shell script</name> - <version>1.1</version> - </generator> - <source> - <project>$project_name</project> - <module>$module_name</module> - </source> - <body> - <commit> - <revision>$REV</revision> - <author>$author</author> - <files>$files</files> - <log>$log</log> - <url>$url</url> - <diffLines>$diff_lines</diffLines> - </commit> - </body> -</message> -EOF -) | $sendmail_command - -### The End ### diff --git a/modules/subversion/templates/converted_to_git b/modules/subversion/templates/converted_to_git new file mode 100644 index 00000000..8f137506 --- /dev/null +++ b/modules/subversion/templates/converted_to_git @@ -0,0 +1,16 @@ +#!/bin/sh + +REPOS="$1" +TXN="$2" + +if [ ! -f "$REPOS/conf/git.conf" ]; then + exit 0 +fi + +REGEX=$(cat "$REPOS/conf/git.conf" | grep -v "^#" | grep -v "^ *$" | xargs | sed 's/ /|/g') + +if (svnlook dirs-changed -t $TXN "$REPOS" | grep -qE "^($REGEX)"); then + echo "The subversion path you have attempted to commit to has been converted to git." >&2 + echo "Please see: https://wiki.mageia.org/en/Git_Migration" >&2 + exit 1 +fi diff --git a/modules/subversion/templates/hook_commit.sh b/modules/subversion/templates/hook_commit.sh index ec7ea1cb..2b1b6ff3 100644 --- a/modules/subversion/templates/hook_commit.sh +++ b/modules/subversion/templates/hook_commit.sh @@ -9,9 +9,9 @@ author=$(svnlook author -t "$TXN" "$REP") # We will be able to remove it when updating to a better send mail hook if [ "$author" = 'schedbot' ]; then - LIST= `ls $0.d/* | grep -v send_mail` + LIST=`ls -1 $0.d/* | grep -v send_mail` else - LIST=`ls $0.d/*` + LIST=`ls -1 $0.d/*` fi for script in $LIST; do @@ -25,4 +25,3 @@ for script in $LIST; do $script $@ || exit 1 done - diff --git a/modules/subversion/templates/hook_irker b/modules/subversion/templates/hook_irker new file mode 100644 index 00000000..8fd7a874 --- /dev/null +++ b/modules/subversion/templates/hook_irker @@ -0,0 +1,4 @@ +#!/bin/sh +REPO=$1 +REV=$2 +<%= irkerhook_path %> --repository=$REPO $REV diff --git a/modules/subversion/templates/hook_sendmail.pl b/modules/subversion/templates/hook_sendmail.pl index aab1db5a..cf3be6a4 100644 --- a/modules/subversion/templates/hook_sendmail.pl +++ b/modules/subversion/templates/hook_sendmail.pl @@ -7,7 +7,11 @@ alternative: HTML::ColorDiff with-diff: 1 max_diff_length: 20000 - from: root@<%= domain %> + ticket_map: + '(\bmga#(\d+)\b)': 'https://bugs.mageia.org/show_bug.cgi?id=%s' + revision-url: "https://svnweb.mageia.org/packages/?revision=%s&view=revision" + subject_cx: 1 + from: subversion_noreply@ml.<%= @domain %> to: <%- commit_mail.each do |mail| -%> - <%= mail %> @@ -19,6 +23,10 @@ alternative: HTML::ColorDiff with-diff: 1 max_diff_length: 20000 - from: root@<%= domain %> + ticket_map: + '(\bmga#(\d+)\b)': 'https://bugs.mageia.org/show_bug.cgi?id=%s' + revision-url: "https://svnweb.mageia.org/packages/?revision=%s&view=revision" + subject_cx: 1 + from: subversion_noreply@ml.<%= @domain %> to: <%= i18n_mail %> <%- end -%> diff --git a/modules/subversion/templates/irker.conf b/modules/subversion/templates/irker.conf new file mode 100644 index 00000000..d037a120 --- /dev/null +++ b/modules/subversion/templates/irker.conf @@ -0,0 +1,7 @@ +<%- + content = '' + @irker_conf.keys.sort.each {|key| + content += key + ' = ' + @irker_conf[key] + "\n" + } +-%> +<%= content %> diff --git a/modules/subversion/templates/no_binary b/modules/subversion/templates/no_binary index a7f2eb94..284642e5 100644 --- a/modules/subversion/templates/no_binary +++ b/modules/subversion/templates/no_binary @@ -3,7 +3,7 @@ REP="$1" TXN="$2" -# Filter some binary files based on common filename extentions. +# Filter some binary files based on common filename extensions. # It does not fully prevent commit of binary files, this script is only # here to avoid simple mistakes if svnlook changed -t "$TXN" "$REP" | grep -qi '\.\(gz\|bz2\|xz\|lzma\|Z\|7z\|tar\|tgz\|zip\|jpg\|gif\|png\|ogg\|mp3\|wav\|rar\|pdf\)$' diff --git a/modules/subversion/templates/restricted_to_user b/modules/subversion/templates/restricted_to_user index 5c70132e..98297627 100644 --- a/modules/subversion/templates/restricted_to_user +++ b/modules/subversion/templates/restricted_to_user @@ -6,7 +6,7 @@ TXN="$2" author=$(svnlook author -t "$TXN" "$REP") if [ "$author" != '<%= restricted_to_user %>' ]; then - echo "this repository is restrected to user <%= restricted_to_user %>" >&2 + echo "this repository is restricted to user <%= restricted_to_user %>" >&2 exit 1 fi diff --git a/modules/subversion/templates/xinetd b/modules/subversion/templates/xinetd index 87827ec2..0919ae60 100644 --- a/modules/subversion/templates/xinetd +++ b/modules/subversion/templates/xinetd @@ -12,4 +12,3 @@ service svnserve server_args = -i -r <%= svn_base_path %> flags = IPv6 } - diff --git a/modules/sudo/manifests/sudoers_config.pp b/modules/sudo/manifests/sudoers_config.pp index 29e51c8a..fdc38e9b 100644 --- a/modules/sudo/manifests/sudoers_config.pp +++ b/modules/sudo/manifests/sudoers_config.pp @@ -1,5 +1,5 @@ define sudo::sudoers_config($content) { - file { "/etc/sudoers.d/$name": + file { "/etc/sudoers.d/${name}": mode => '0440', content => $content, } diff --git a/modules/sympa/files/scenari/open_web_only_notify b/modules/sympa/files/scenari/open_web_only_notify index 9c0b1dbc..621e425c 100644 --- a/modules/sympa/files/scenari/open_web_only_notify +++ b/modules/sympa/files/scenari/open_web_only_notify @@ -3,4 +3,3 @@ title.gettext anyone on the web, notification is sent to list owner # do not notify if it is just an update is_subscriber([listname],[sender]) smtp,smime,md5 -> do_it true() md5 -> do_it,notify - diff --git a/modules/sympa/files/scenari/subscriber_moderated b/modules/sympa/files/scenari/subscriber_moderated deleted file mode 100644 index 9e301213..00000000 --- a/modules/sympa/files/scenari/subscriber_moderated +++ /dev/null @@ -1,6 +0,0 @@ -title.gettext Reserved to subscriber - -is_subscriber([listname],[sender]) smtp,smime,md5 -> do_it -true() smime,md5 -> do_it -true() smtp -> reject(reason='send_subscriber') - diff --git a/modules/sympa/files/topics.conf b/modules/sympa/files/topics.conf index 53824f0d..92e1809c 100644 --- a/modules/sympa/files/topics.conf +++ b/modules/sympa/files/topics.conf @@ -1,3 +1,6 @@ +bugsquad +title Bug triaging + sysadmin title System administration, infrastructure @@ -24,3 +27,6 @@ title Local Community atelier title Atelier (Artwork, Web, Marketing, Communication) + +users +title Users discussions diff --git a/modules/sympa/manifests/announce_list_email.pp b/modules/sympa/manifests/announce_list_email.pp deleted file mode 100644 index bebeea13..00000000 --- a/modules/sympa/manifests/announce_list_email.pp +++ /dev/null @@ -1,18 +0,0 @@ -# list where announce are sent by $email only -# reply_to is set to $reply_to -define sympa::announce_list_email($subject, - $reply_to, - $sender_email, - $subscriber_ldap_group = false, - $language = 'en', - $topics = false) { - list { $name: - subject => $subject, - profile => '', - language => $language, - topics => $topics, - reply_to => $reply_to, - sender_email => $sender_email, - subscriber_ldap_group => $subscriber_ldap_group, - } -} diff --git a/modules/sympa/manifests/announce_list_group.pp b/modules/sympa/manifests/announce_list_group.pp deleted file mode 100644 index ddb3747a..00000000 --- a/modules/sympa/manifests/announce_list_group.pp +++ /dev/null @@ -1,17 +0,0 @@ -# list where announce are sent by member of ldap_group -# reply_to is set to $reply_to -define sympa::announce_list_group($subject, - $reply_to, - $sender_ldap_group, - $language = 'en', - $topics = false) { - # profile + scenario - list { $name: - subject => $subject, - profile => '', - language => $language, - topics => $topics, - reply_to => $reply_to, - sender_ldap_group => $sender_ldap_group, - } -} diff --git a/modules/sympa/manifests/datasource/ldap_group.pp b/modules/sympa/manifests/datasource/ldap_group.pp index 6b34ec92..6060bec4 100644 --- a/modules/sympa/manifests/datasource/ldap_group.pp +++ b/modules/sympa/manifests/datasource/ldap_group.pp @@ -1,5 +1,5 @@ define sympa::datasource::ldap_group { - file { "/etc/sympa/data_sources/$name.incl": + file { "/etc/sympa/data_sources/${name}.incl": content => template('sympa/data_sources/ldap_group.incl') } } diff --git a/modules/sympa/manifests/list.pp b/modules/sympa/manifests/list.pp index 4e265f31..205d2719 100644 --- a/modules/sympa/manifests/list.pp +++ b/modules/sympa/manifests/list.pp @@ -1,38 +1,33 @@ define sympa::list( $subject, - $profile = false, $language = 'en', $topics = false, $reply_to = false, + $sender_subscriber = false, $sender_email = false, $sender_ldap_group = false, $subscriber_ldap_group = false, $public_archive = true, - $subscription_open = false) { + $subscription_open = false, + $critical = false) { include sympa::variable $ldap_password = extlookup('sympa_ldap','x') $custom_subject = $name - $xml_file = "/etc/sympa/lists_xml/$name.xml" - - if $sender_email { - $sender_email_file = regsubst($sender_email,'\@','-at-') - } else { - $sender_email_file = '' - } + $xml_file = "/etc/sympa/lists_xml/${name}.xml" file { $xml_file: content => template('sympa/list.xml'), require => Package[sympa], } - exec { "sympa.pl --create_list --robot=$sympa::variable::vhost --input_file=$xml_file": + exec { "sympa.pl --create_list --robot=${sympa::variable::vhost} --input_file=${xml_file}": require => File[$xml_file], - creates => "/var/lib/sympa/expl/$name", - before => File["/var/lib/sympa/expl/$name/config"], + creates => "/var/lib/sympa/expl/${name}", + before => File["/var/lib/sympa/expl/${name}/config"], } - file { "/var/lib/sympa/expl/$name/config": + file { "/var/lib/sympa/expl/${name}/config": owner => 'sympa', group => 'sympa', mode => '0750', @@ -40,16 +35,10 @@ define sympa::list( $subject, notify => Service['sympa'], } - if $sender_ldap_group { - if ! defined(Sympa::Scenario::Sender_ldap_group[$sender_ldap_group]) { - sympa::scenario::sender_ldap_group { $sender_ldap_group: } - } - } - - if $sender_email { - if ! defined(Sympa::Scenario::Sender_email[$sender_email]) { - sympa::scenario::sender_email { $sender_email: } - } + sympa::scenario::sender_restricted { $name: + ldap_group => $sender_ldap_group, + email => $sender_email, + allow_subscriber => $sender_subscriber, } if $subscriber_ldap_group { @@ -57,6 +46,12 @@ define sympa::list( $subject, sympa::search_filter::ldap { $subscriber_ldap_group: } } } + + if $sender_ldap_group { + if ! defined(Sympa::Search_filter::Ldap[$sender_ldap_group]) { + sympa::search_filter::ldap { $sender_ldap_group: } + } + } } diff --git a/modules/sympa/manifests/list/announce.pp b/modules/sympa/manifests/list/announce.pp new file mode 100644 index 00000000..2dd1c647 --- /dev/null +++ b/modules/sympa/manifests/list/announce.pp @@ -0,0 +1,21 @@ +# list where announce are sent by $email or $ldap_group only +# reply_to is set to $reply_to +define sympa::list::announce($subject, + $reply_to, + $sender_email = false, + $sender_ldap_group = false, + $subscriber_ldap_group = false, + $language = 'en', + $topics = false, + $critical = false) { + list { $name: + subject => $subject, + language => $language, + topics => $topics, + reply_to => $reply_to, + sender_email => $sender_email, + sender_ldap_group => $sender_ldap_group, + subscriber_ldap_group => $subscriber_ldap_group, + critical => $critical + } +} diff --git a/modules/sympa/manifests/list/private.pp b/modules/sympa/manifests/list/private.pp index d58d7ab2..c8d9b38e 100644 --- a/modules/sympa/manifests/list/private.pp +++ b/modules/sympa/manifests/list/private.pp @@ -1,15 +1,16 @@ # list with private archive, restricted to member of $ldap_group define sympa::list::private($subject, $subscriber_ldap_group, + $sender_email = false, $language ='en', $topics = false) { list { $name: subject => $subject, - profile => '', language => $language, topics => $topics, subscriber_ldap_group => $subscriber_ldap_group, sender_ldap_group => $subscriber_ldap_group, + sender_email => $sender_email, public_archive => false, } } diff --git a/modules/sympa/manifests/list/private_email.pp b/modules/sympa/manifests/list/private_email.pp deleted file mode 100644 index 54e70592..00000000 --- a/modules/sympa/manifests/list/private_email.pp +++ /dev/null @@ -1,17 +0,0 @@ -# same as private_list, but post are restricted to $email -# ( scripting ) -define sympa::list::private_email($subject, - $subscriber_ldap_group, - $sender_email, - $language ='en', - $topics = false) { - list { $name: - subject => $subject, - profile => '', - language => $language, - topics => $topics, - subscriber_ldap_group => $subscriber_ldap_group, - sender_email => $sender_email, - public_archive => false, - } -} diff --git a/modules/sympa/manifests/list/private_open.pp b/modules/sympa/manifests/list/private_open.pp deleted file mode 100644 index 7f3f5105..00000000 --- a/modules/sympa/manifests/list/private_open.pp +++ /dev/null @@ -1,18 +0,0 @@ -# list with private archive, restricted to member of $ldap_group -# everybody can post -# used for contact alias -define sympa::list::private_open( $subject, - $subscriber_ldap_group, - $language = 'en', - $topics = false) { - sympa::list { $name: - subject => $subject, - profile => '', - language => $language, - topics => $topics, - subscriber_ldap_group => $subscriber_ldap_group, - public_archive => false, - } -} - - diff --git a/modules/sympa/manifests/list/public.pp b/modules/sympa/manifests/list/public.pp new file mode 100644 index 00000000..7b97534a --- /dev/null +++ b/modules/sympa/manifests/list/public.pp @@ -0,0 +1,16 @@ +# public discussion list +# reply_to is set to the list +define sympa::list::public($subject, + $language = 'en', + $topics = false, + $sender_email = false) { + include sympa::variable + list { $name: + subject => $subject, + language => $language, + topics => $topics, + sender_email => $sender_email, + sender_subscriber => true, + reply_to => "${name}@${sympa::variable::vhost}", + } +} diff --git a/modules/sympa/manifests/public_restricted_list.pp b/modules/sympa/manifests/list/public_restricted.pp index fec079f7..5c316368 100644 --- a/modules/sympa/manifests/public_restricted_list.pp +++ b/modules/sympa/manifests/list/public_restricted.pp @@ -1,17 +1,17 @@ -# list where only people from the ldap_group can post, ad where +# list where only people from the ldap_group can post, and where # they are subscribed by default, but anybody else can subscribe # to read and receive messages -define sympa::public_restricted_list( $subject, +define sympa::list::public_restricted($subject, $subscriber_ldap_group, $language = 'en', $topics = false) { list { $name: subject => $subject, - profile => '', topics => $topics, language => $language, subscriber_ldap_group => $subscriber_ldap_group, sender_ldap_group => $subscriber_ldap_group, subscription_open => true, + reply_to => "${name}@${sympa::variable::vhost}", } } diff --git a/modules/sympa/manifests/list/restricted.pp b/modules/sympa/manifests/list/restricted.pp deleted file mode 100644 index 779cd3fb..00000000 --- a/modules/sympa/manifests/list/restricted.pp +++ /dev/null @@ -1,15 +0,0 @@ -# list where people cannot subscribe, where people from $ldap_group receive -# mail, with public archive -define sympa::list::restricted($subject, - $subscriber_ldap_group, - $language = 'en', - $topics = false) { - list { $name: - subject => $subject, - profile => '', - topics => $topics, - language => $language, - subscriber_ldap_group => $subscriber_ldap_group, - sender_ldap_group => $subscriber_ldap_group, - } -} diff --git a/modules/sympa/manifests/public_list.pp b/modules/sympa/manifests/public_list.pp deleted file mode 100644 index 6b660abf..00000000 --- a/modules/sympa/manifests/public_list.pp +++ /dev/null @@ -1,13 +0,0 @@ -# public discussion list -# reply_to is set to the list -define sympa::public_list($subject, - $language = 'en', - $topics = false) { - include sympa::variable - list { $name: - subject => $subject, - language => $language, - topics => $topics, - reply_to => "$name@$sympa::variable::vhost", - } -} diff --git a/modules/sympa/manifests/restricted_list_open.pp b/modules/sympa/manifests/restricted_list_open.pp deleted file mode 100644 index 1730b970..00000000 --- a/modules/sympa/manifests/restricted_list_open.pp +++ /dev/null @@ -1,14 +0,0 @@ -# same as restricted list, but anybody can post -define sympa::restricted_list_open( $subject, - $subscriber_ldap_group, - $language = 'en', - $topics = false) { - list { $name: - subject => $subject, - profile => '', - language => $language, - topics => $topics, - subscriber_ldap_group => $subscriber_ldap_group, - sender_ldap_group => $subscriber_ldap_group, - } -} diff --git a/modules/sympa/manifests/scenario/sender_email.pp b/modules/sympa/manifests/scenario/sender_email.pp deleted file mode 100644 index 4f811189..00000000 --- a/modules/sympa/manifests/scenario/sender_email.pp +++ /dev/null @@ -1,6 +0,0 @@ -define sympa::scenario::sender_email { - $sender_email_file = regsubst($name,'\@','-at-') - file { "/etc/sympa/scenari/send.restricted_$sender_email_file": - content => template('sympa/scenari/sender.email') - } -} diff --git a/modules/sympa/manifests/scenario/sender_ldap_group.pp b/modules/sympa/manifests/scenario/sender_ldap_group.pp deleted file mode 100644 index 363af4f3..00000000 --- a/modules/sympa/manifests/scenario/sender_ldap_group.pp +++ /dev/null @@ -1,7 +0,0 @@ -define sympa::scenario::sender_ldap_group { - file { "/etc/sympa/scenari/send.restricted_$name": - content => template('sympa/scenari/sender.ldap_group') - } -} - - diff --git a/modules/sympa/manifests/scenario/sender_restricted.pp b/modules/sympa/manifests/scenario/sender_restricted.pp new file mode 100644 index 00000000..c69d3669 --- /dev/null +++ b/modules/sympa/manifests/scenario/sender_restricted.pp @@ -0,0 +1,9 @@ +define sympa::scenario::sender_restricted( + $email = false, + $ldap_group = false, + $allow_subscriber = false +) { + file { "/etc/sympa/scenari/send.restricted_${name}": + content => template('sympa/scenari/sender.restricted') + } +} diff --git a/modules/sympa/manifests/server.pp b/modules/sympa/manifests/server.pp index daed4e07..bcdda789 100644 --- a/modules/sympa/manifests/server.pp +++ b/modules/sympa/manifests/server.pp @@ -10,12 +10,17 @@ class sympa::server( 'perl-CGI-Fast', 'perl-Socket6']: } - # sympa script start 5 differents script, I am not + # sympa script starts 5 different scripts; I am not # sure that puppet will correctly handle this service { 'sympa': subscribe => [ Package['sympa'], File['/etc/sympa/sympa.conf']] } + service { 'sympa-outgoing': + ensure => running, + require => Service['sympa'] + } + $pgsql_password = extlookup('sympa_pgsql','x') $ldap_password = extlookup('sympa_ldap','x') @@ -30,8 +35,8 @@ class sympa::server( $vhost = $sympa::variable::vhost file { '/etc/sympa/sympa.conf': - # should be cleaner to have it root owned, but puppet do not support acl - # and in any case, config will be reset if it change + # should be cleaner to have it root owned, but puppet does not support acls + # and in any case, config will be reset if it changes owner => 'sympa', group => 'apache', mode => '0640', @@ -56,9 +61,9 @@ class sympa::server( content => template('sympa/vhost_ml.conf'), } - subversion::snapshot { '/etc/sympa/web_tt2': - source => 'svn://svn.mageia.org/svn/web/templates/sympa/trunk', - } +# git::snapshot { '/etc/sympa/web_tt2': +# source => "git://git.${::domain}/web/templates/sympa", +# } file { ['/etc/sympa/lists_xml/', '/etc/sympa/scenari/', @@ -75,8 +80,6 @@ class sympa::server( source => 'puppet:///modules/sympa/scenari/open_web_only_notify'; '/etc/sympa/scenari/unsubscribe.open_web_only_notify': source => 'puppet:///modules/sympa/scenari/open_web_only_notify'; - '/etc/sympa/scenari/send.subscriber_moderated': - source => 'puppet:///modules/sympa/scenari/subscriber_moderated'; '/etc/sympa/scenari/create_list.forbidden': source => 'puppet:///modules/sympa/scenari/forbidden'; '/etc/sympa/topics.conf': @@ -96,4 +99,5 @@ class sympa::server( ensure => directory, owner => 'sympa', } + } diff --git a/modules/sympa/manifests/variable.pp b/modules/sympa/manifests/variable.pp index 274c4bb8..26f60294 100644 --- a/modules/sympa/manifests/variable.pp +++ b/modules/sympa/manifests/variable.pp @@ -1,3 +1,3 @@ class sympa::variable { - $vhost = "ml.$::domain" + $vhost = "ml.${::domain}" } diff --git a/modules/sympa/templates/auth.conf b/modules/sympa/templates/auth.conf index af998b68..854fdf9c 100644 --- a/modules/sympa/templates/auth.conf +++ b/modules/sympa/templates/auth.conf @@ -6,8 +6,10 @@ ldap get_dn_by_email_filter (|(mail=[sender])(mailalternateaddress=[sender])) email_attribute mail scope sub - use_ssl 1 + use_tls ldaps + ssl_version tlsv1_2 + ca_verify none bind_dn cn=sympa-<%= hostname %>,ou=System Accounts,<%= dc_suffix %> - bind_password <%= ldap_password %> + bind_password <%= scope.lookupvar("sympa::server::ldap_password") %> authentication_info_url <%= authentication_info_url %> diff --git a/modules/sympa/templates/config b/modules/sympa/templates/config index 36510531..4262f3ca 100644 --- a/modules/sympa/templates/config +++ b/modules/sympa/templates/config @@ -1,10 +1,16 @@ -subject <%= subject %> -status open +archive +period month +mail_access owner +<%- if public_archive and not @critical -%> +web_access public +<%- else -%> +web_access private +<%- end -%> visibility noconceal -lang <%= language %> +digest 1,4 13:26 <% if subscriber_ldap_group and not subscription_open %> # TODO check scenari @@ -17,91 +23,81 @@ subscribe open_web_only_notify unsubscribe open_web_only_notify <% end %> -# TODO reception nomail -# profile normal - -owner -email postmaster@<%= domain %> -gecos Sysadmin team -reception nomail - -owner_include -source mga-sysadmin +editor +email listmaster@<%= domain %> reception nomail -profile normal +gecos Moderator team visibility conceal -editor -email listmaster@<%= domain %> -gecos Moderator team +editor_include reception nomail - -editor_include source mga-ml_moderators -reception nomail visibility conceal +subject <%= subject %> -<% if reply_to %> -# TODO -reply_to_header -value other_email -other_email <%= reply_to %> -apply forced +custom_subject <%= custom_subject %> + +<%- if @critical -%> +info conceal + +subscribe auth owner + +unsubscribe auth_notify + +invite owner <% end %> +lang <%= language %> +owner +gecos Sysadmin team +reception nomail +email postmaster@<%= domain %> +visibility noconceal +profile normal -<% if sender_email %> -#TODO write scenari -send restricted_<%= sender_email_file %> +owner_include +profile normal +visibility conceal +source mga-sysadmin +reception nomail -<% elsif sender_ldap_group %> -#TODO write scenari -send restricted_<%= sender_ldap_group %> -<% else %> -#TODO write scenari -send subscriber_moderated +<%- if @reply_to -%> +reply_to_header +value other_email +other_email <%= reply_to %> +apply forced +<%- end -%> -<% end %> +review owner <% if topics %> topics <%= topics %> <% end %> +send restricted_<%= @name %> + <% if subscriber_ldap_group %> include_ldap_query - host ldap.<%= domain %> - suffix ou=People,<%= dc_suffix %> timeout 10 - filter (memberOf=cn=<%= subscriber_ldap_group %>,ou=Group,<%= dc_suffix %>) - attrs mail - select first scope one - use_ssl yes - user cn=sympa-<%= hostname %>,ou=System Accounts,<%= dc_suffix %> - passwd <%= ldap_password %> - -<% end %> - -<%- if public_archive -%> -web_archive - #TODO check - access public -<%- else -%> -web_archive - #TODO check - access private -<%- end -%> - -archive -access owner -period month + select first + ssl_version tlsv1_2 + ca_verify none + use_tls ldaps + attrs mail + ssl_ciphers ALL + passwd <%= scope.lookupvar("sympa::server::ldap_password") %> + user cn=sympa-<%= hostname %>,ou=System Accounts,<%= dc_suffix %> + suffix ou=People,<%= dc_suffix %> + filter (memberOf=cn=<%= subscriber_ldap_group %>,ou=Group,<%= dc_suffix %>) + host ldap.<%= domain %> -digest 1,4 13:26 +<% end %> -review private +process_archive on -custom_subject <%= custom_subject %> +status open diff --git a/modules/sympa/templates/data_sources/ldap_group.incl b/modules/sympa/templates/data_sources/ldap_group.incl index 4517fe26..609a7e42 100644 --- a/modules/sympa/templates/data_sources/ldap_group.incl +++ b/modules/sympa/templates/data_sources/ldap_group.incl @@ -1,8 +1,10 @@ include_ldap_2level_query host ldap.<%= domain %> - use_ssl yes + use_tls ldaps + ssl_version tlsv1_2 + ca_verify none user cn=sympa-<%= hostname %>,ou=System Accounts,<%= dc_suffix %> - passwd <%= ldap_password %> + passwd <%= scope.lookupvar("sympa::server::ldap_password") %> suffix1 ou=Group,<%= dc_suffix %> scope1 one filter1 (&(objectClass=groupOfNames)(cn=<%= name %>)) @@ -13,4 +15,3 @@ include_ldap_2level_query filter2 (objectClass=inetOrgPerson) attrs2 mail select2 first - diff --git a/modules/sympa/templates/list.xml b/modules/sympa/templates/list.xml index 1d83125e..74e4f07f 100644 --- a/modules/sympa/templates/list.xml +++ b/modules/sympa/templates/list.xml @@ -6,10 +6,11 @@ <description/> <status>open</status> <language><%= language %></language> - <owner_include> - <source>mga-sysadm</source> + <owner_include multiple="1"> + <source>mga-sysadmin</source> </owner_include> - <editor_include> + <editor_include multiple="1"> <source>mga-ml_moderators</source> </editor_include> + <topic><%= topics %></topic> </list> diff --git a/modules/sympa/templates/scenari/sender.email b/modules/sympa/templates/scenari/sender.email deleted file mode 100644 index ee293dfd..00000000 --- a/modules/sympa/templates/scenari/sender.email +++ /dev/null @@ -1,5 +0,0 @@ -title.gettext restricted to email <%= name %> - -equal([sender], '<%= name %>') smtp,md5,smime -> do_it -true() smtp,md5,smime -> reject(reason='send_subscriber') - diff --git a/modules/sympa/templates/scenari/sender.ldap_group b/modules/sympa/templates/scenari/sender.ldap_group deleted file mode 100644 index d1abe66d..00000000 --- a/modules/sympa/templates/scenari/sender.ldap_group +++ /dev/null @@ -1,5 +0,0 @@ -title.gettext restricted to group <%= name %> - -search(<%= name %>.ldap) smtp,md5,smime -> do_it -true() smtp,md5,smime -> reject(reason='send_subscriber') - diff --git a/modules/sympa/templates/scenari/sender.restricted b/modules/sympa/templates/scenari/sender.restricted new file mode 100644 index 00000000..66139e6c --- /dev/null +++ b/modules/sympa/templates/scenari/sender.restricted @@ -0,0 +1,17 @@ +title.gettext restricted list + +<%- if @ldap_group -%> +search(<%= @ldap_group %>.ldap) smtp,md5,smime -> do_it +<%- end -%> +<%- if @email -%> + <%- for e in @email -%> +equal([sender], '<%= e %>') smtp,md5,smime -> do_it + <%- end -%> +<%- end -%> +<%- if allow_subscriber -%> +equal([sender], 'sysadmin@group.mageia.org') smtp,smime,md5 -> do_it +match([sender], /@mageia\.org$/) smtp,smime,md5 -> do_it +is_subscriber([listname],[sender]) smtp,smime,md5 -> do_it +true() smime,md5 -> do_it +<%- end -%> +true() smtp,md5,smime -> reject(reason='send_subscriber') diff --git a/modules/sympa/templates/search_filters/group.ldap b/modules/sympa/templates/search_filters/group.ldap index fd1f28d9..884e0db1 100644 --- a/modules/sympa/templates/search_filters/group.ldap +++ b/modules/sympa/templates/search_filters/group.ldap @@ -1,7 +1,9 @@ host ldap.<%= domain %>:636 bind_dn cn=sympa-<%= hostname %>,ou=System Accounts,<%= dc_suffix %> -bind_password <%= ldap_password %> -use_ssl yes +bind_password <%= scope.lookupvar("sympa::server::ldap_password") %> +use_tls ldaps +ssl_version tlsv1_2 +ca_verify none suffix ou=People,<%= dc_suffix %> filter (&(mail=[sender])(memberOf=cn=<%= name %>,ou=Group,<%= dc_suffix %>)) scope sub diff --git a/modules/sympa/templates/sympa.conf b/modules/sympa/templates/sympa.conf index 83654914..edfaba15 100644 --- a/modules/sympa/templates/sympa.conf +++ b/modules/sympa/templates/sympa.conf @@ -1,297 +1,627 @@ -###\\\\ Directories and file location ////### +###\\\\ Service description ////### -## Directory containing mailing lists subdirectories -home /var/lib/sympa/expl +## Primary mail domain name +domain <%= vhost %> -## Directory for configuration files ; it also contains scenari/ and templates/ directories -etc /etc/sympa +## Email addresses of listmasters +## Email addresses of the listmasters (users authorized to perform global +## server commands). Some error reports may also be sent to these addresses. +## Listmasters can be defined for each virtual host, however, the default +## listmasters will have privileges to manage all virtual hosts. +listmaster listmaster@<%= vhost %> -## File containing Sympa PID while running. -## Sympa also locks this file to ensure that it is not running more than once. Caution : user sympa need to write access without special privilegee. -pidfile /var/run/sympa/sympa.pid +## Default language +## This is the default language used by Sympa. One of supported languages +## should be chosen. +lang en-US -pidfile_distribute /var/run/sympa/sympa-distribute.pid - -pidfile_creation /var/run/sympa/sympa-creation.pid - -pidfile_bulk /var/run/sympa/bulk.pid - -## Umask used for file creation by Sympa -umask 027 - -## Directory containing available NLS catalogues (Message internationalization) -localedir /usr/share/locale - -## The main spool containing various specialized spools -## All spool are created at runtime by sympa.pl -spool /var/spool/sympa - -## Incoming spool -queue /var/spool/sympa/msg - -## Bounce incoming spool -queuebounce /var/spool/sympa/bounce - -## Automatic list creation spool -queueautomatic /var/spool/sympa/automatic - -## -queuedigest /var/spool/sympa/digest - -## -queuemod /var/spool/sympa/moderation - -## -queuetopic /var/spool/sympa/topic - -## -queueauth /var/spool/sympa/auth - -## -queueoutgoing /var/spool/sympa/outgoing - -## -queuetask /var/spool/sympa/task - -## -queuesubscribe /var/spool/sympa/subscribe - -## URL to a virtual host. -http_host http://domain.tld - -## The directory where Sympa stores static contents (CSS, members pictures, documentation) directly delivered by Apache -static_content_path /var/lib/sympa/static_content - -## The URL mapped with the static_content_path directory defined above -static_content_url /static-sympa - -###\\\\ Syslog ////### - -## The syslog facility for sympa -## Do not forget to edit syslog.conf -syslog mail +## Supported languages +## All supported languages for the user interface. Languages proper locale +## information not installed are ignored. +supported_lang en_US + +## Title of service +## The name of your mailing list service. It will appear in the header of web +## interface and subjects of several service messages. +title Mageia Mailing lists service + +## Display name of Sympa +## This parameter is used for display name in the "From:" header field for the +## messages sent by Sympa itself. +gecos SYMPA + +## Support of legacy character set +## If set to "on", enables support of legacy character set according to +## charset.conf(5) configuration file. +## In some language environments, legacy encoding (character set) can be +## preferred for e-mail messages: for example iso-2022-jp in Japanese +## language. +legacy_character_support_feature off + +###\\\\ Database related ////### + +## Type of the database +## Possible types are "MySQL", "PostgreSQL", "Oracle", "Sybase" and "SQLite". +db_type PostgreSQL + +## Hostname of the database server +## With PostgreSQL, you can also use the path to Unix Socket Directory, e.g. +## "/var/run/postgresql" for connection with Unix domain socket. +db_host pg.<%= domain %> + +## Port of the database server +db_port 5432/tcp -## Communication mode with syslogd is either unix (via Unix sockets) or inet (use of UDP) -log_socket_type unix +## Name of the database +## With SQLite, this must be the full path to database file. With Oracle +## Database, this must be Oracle SID. +db_name sympa + +## User for the database connection +db_user sympa + +## Password for the database connection +## What ever you use a password or not, you must protect the SQL server (is it +## not a public internet service ?) +db_passwd <%= scope.lookupvar("sympa::server::pgsql_password") %> + +## Environment variables setting for database +## With Oracle Database, this is useful for defining ORACLE_HOME and NLS_LANG. +# db_env NLS_LANG=American_America.AL32UTF8;ORACLE_HOME=/u01/app/oracle/product/11.2.0/server + +## Database private extension to subscriber table +## Adds more fields to "subscriber_table" table. Sympa recognizes fields +## defined with this parameter. You will then be able to use them from within +## templates and scenarios: +## * for scenarios: [subscriber->field] +## * for templates: [% subscriber.field %] +## These fields will also appear in the list members review page and will be +## editable by the list owner. This parameter is a comma-separated list. +## You need to extend the database format with these fields +# db_additional_subscriber_fields billing_delay,subscription_expiration -## Log intensity -## 0 : normal, 2,3,4 for debug -log_level 0 +## Database private extension to user table +## Adds more fields to "user_table" table. Sympa recognizes fields defined +## with this parameter. You will then be able to use them from within +## templates: [% subscriber.field %] +## This parameter is a comma-separated list. +## You need to extend the database format with these fields +# db_additional_user_fields age,address -log_smtp off +###\\\\ System log ////### -## Number of months that elapse before a log is expired. -logs_expiration_period 3 +## System log facility for Sympa +## Do not forget to configure syslog server. +syslog mail -###\\\\ General definition ////### +## Communication mode with syslog server +log_socket_type unix -## Main robot hostname -domain <%= vhost %> +## Log verbosity +## Sets the verbosity of logs. +## 0: Only main operations are logged +## 3: Almost everything is logged. +log_level 0 -## Listmasters email list comma separated -## Sympa will associate listmaster privileges to these email addresses (mail and web interfaces). Some error reports may also be sent to these addresses. -listmaster listmaster@<%= vhost %> +###\\\\ Receiving ////### -## Local part of sympa email adresse -## Effective address will be \[EMAIL\]@\[HOST\] -email sympa +## Default maximum number of list members +## Default limit for the number of subscribers per list (0 means no limit). +default_max_list_members 0 -## Who is able to create lists -## This parameter is a scenario, check sympa documentation about scenarios if you want to define one -create_list forbidden +## Maximum size of messages +## Incoming messages smaller than this size is allowed distribution by Sympa. +max_size 5242880 -edit_list owner +## Reject mail sent from automated services to list +## Rejects messages that seem to be from automated services, based on a few +## header fields ("Content-Identifier:", "Auto-Submitted:"). +## Sympa also can be configured to reject messages based on the "From:" header +## field value (see "loop_prevention_regex"). +reject_mail_from_automates_feature off -###\\\\ Tuning ////### +## Priority for command messages +## Priority applied to messages sent to Sympa command address. +sympa_priority 1 -## Use of binary version of the list config structure on disk: none | binary_file -## Set this parameter to "binary_file" if you manage a big amount of lists (1000+) ; it should make the web interface startup faster -cache_list_config none +## Priority for messages bound for list owners +## Priority for processing of messages bound for "LIST-request" address, i.e. +## owners of the list +request_priority 0 -## Sympa commands priority -sympa_priority 1 +## Priority for non-VERP bounces +## Priority for processing of messages bound for "LIST-owner" address, i.e. +## non-delivery reports (bounces). +owner_priority 9 ## Default priority for list messages -default_list_priority 5 - -## Default timeout between two scheduled synchronizations of list members with data sources. -default_ttl 3600 - -## Default timeout between two action-triggered synchronizations of list members with data sources. -default_distribution_ttl 300 - -## Default priority for a packet to be sent by bulk. -sympa_packet_priority 5 - -request_priority 0 - -owner_priority 9 - -## The minimum number of packets in database before the bulk forks to increase sending rate -## -bulk_fork_threshold 1 - -## The max number of bulks that will run on the same server. -## -bulk_max_count 3 - -## the number of seconds a slave bulk will remain running without processing a message before it spontaneously dies. -## -bulk_lazytime 600 - -## The number of seconds a master bulk waits between two packets number checks. -## Keep it small if you expect brutal increases in the message sending load. -bulk_wait_to_fork 10 - -## the number of seconds a bulk sleeps between starting a new loop if it didn't find a message to send. +## Priority for processing of messages posted to list addresses. +default_list_priority 5 + +###\\\\ Sending related ////### + +## Header fields to be removed from incoming messages +## Use it, for example, to ensure some privacy for your users in case that +## "anonymous_sender" mode is inappropriate. +## The removal of these header fields is applied before Sympa adds its own +## header fields ("rfc2369_header_fields" and "custom_header"). +# was remove_headers ARRAY(0x4116e50) +remove_headers X-Sympa-To,X-Family-To,Return-Receipt-To,Precedence,X-Sequence,Disposition-Notification-To + +## RFC 2369 header fields +## Specify which RFC 2369 mailing list header fields to be added. +## "List-Id:" header field defined in RFC 2919 is always added. Sympa also +## adds "Archived-At:" header field defined in RFC 5064. +# was rfc2369_header_fields ARRAY(0x4116c88) +rfc2369_header_fields help,subscribe,unsubscribe,post,owner,archive + +## Default priority for a packet +## The default priority set to a packet to be sent by the bulk. +sympa_packet_priority 5 + +## Fork threshold of bulk daemon +## The minimum number of packets before bulk daemon forks the new worker to +## increase sending rate. +bulk_fork_threshold 1 + +## Maximum number of bulk workers +bulk_max_count 3 + +## Idle timeout of bulk workers +## The number of seconds a bulk worker will remain running without processing +## a message before it spontaneously exists. +bulk_lazytime 600 + +## Sleep time of bulk workers +## The number of seconds a bulk worker sleeps between starting a new loop if +## it didn't find a message to send. ## Keep it small if you want your server to be reactive. -bulk_sleep 1 - -## Secret used by Sympa to make MD5 fingerprint in web cookies secure -## Should not be changed ! May invalid all user password -#cookie 123456789 - -## If set to "on", enables support of legacy characters -## -legacy_character_support_feature off - -## The default maximum size (in bytes) for messages (can be re-defined for each list) -max_size 5242880 - -## comma separated list of operations for which blacklist filter is applied -## Setting this parameter to "none" will hide the blacklist feature -use_blacklist send,create_list - -## Specify which rfc2369 mailing list headers to add -rfc2369_header_fields help,subscribe,unsubscribe,post,owner,archive - -## Specify header fields to be removed before message distribution -remove_headers X-Sympa-To,X-Family-To,Return-Receipt-To,Precedence,X-Sequence,Disposition-Notification-To - -bounce_warn_rate 30 +bulk_sleep 1 -bounce_halt_rate 50 - -###\\\\ Internationalization ////### - -## Default lang (ca | cs | de | el | es | et_EE | en_US | fr | fi | hu | it | ja_JP | ko | nl | nb_NO | oc | pl | pt_BR | ru | sv | tr | vi | zh_CN | zh_TW) -## This is the default language used by Sympa -lang en_US - -## Supported languages -## This is the set of language that will be proposed to your users for the Sympa GUI. Don't select a language if you don't have the proper locale packages installed. -#supported_lang ca,cs,de,el,es,et_EE,en_US,fr,fi,hu,it,ja_JP,ko,nl,nb_NO,oc,pl,pt_BR,ru,sv,tr,vi,zh_CN,zh_TW -supported_lang en_US +## Interval between checks of packet numbers +## Number of seconds a master bulk daemon waits between two packets number +## checks. +## Keep it small if you expect brutal increases in the message sending load. +bulk_wait_to_fork 10 + +## Path to sendmail +## Absolute path to sendmail command line utility (e.g.: a binary named +## "sendmail" is distributed with Postfix). +## Sympa expects this binary to be sendmail compatible (exim, Postfix, qmail +## and so on provide it). Sympa also bundles "sympa_smtpc" program which may +## be a replacement to sendmail binary. +sendmail /usr/sbin/sendmail + +## Log invocation of sendmail +## This can be overwritten by "-m" option for sympa.pl. +log_smtp off + +## Maximum number of sendmail processes +## Maximum number of simultaneous child processes spawned by Sympa. This is +## the main load control parameter. +## Proposed value is quite low, but you can rise it up to 100, 200 or even 300 +## with powerful systems. +maxsmtp 40 + +## Maximum number of recipients per call to sendmail +## This grouping factor makes it possible for the sendmail processes to +## optimize the number of SMTP sessions for message distribution. If needed, +## you can limit the number of recipients for a particular domain. Check the +## "nrcpt_by_domain.conf" configuration file. +nrcpt 25 + +## Maximum number of different mail domains per call to sendmail +avg 10 + +###\\\\ Privileges ////### -###\\\\ Errors management ////### +## Who is able to create lists +## Defines who can create lists (or request list creation) by creating new +## lists or by renaming or copying existing lists. +create_list forbidden + +## Use blacklist +## List of operations separated by comma for which blacklist filter is +## applied. Setting this parameter to "none" will hide the blacklist feature. +use_blacklist send,create_list + +## List of required domains for list owner addresses +## Restrict list ownership to addresses in the specified domains. This can be +## used to reserve list ownership to a group of trusted users from a set of +## domains associated with an organization, while allowing editors and +## subscribers from the Internet at large. +# owner_domain domain1.tld domain2.tld + +## Minimum number of list owners that must match owner_domain restriction +## Minimum number of list owners that must satisfy the owner_domain +## restriction. The default of zero (0) means *all* list owners must match. +## Setting to 1 requires only one list owner to match owner_domain; all other +## owners can be from any domain. This setting can be used to ensure that +## there is always at least one known contact point for a mailing list. +owner_domain_min 0 + +###\\\\ Archives ////### + +## Store distributed messages into archive +## If enabled, distributed messages via lists will be archived. Otherwise +## archiving is disabled. +## Note that even if setting this parameter disabled, past archives will not +## be removed and will be accessible according to access settings by each +## list. +process_archive on + +## Path to MHonArc mail-to-HTML converter +## This is required for HTML mail archiving. +mhonarc /usr/bin/mhonarc + +# There is a need to protect Sympa website against spambot +spam_protection javascript + +# The same as spam_protection, but restricted to the web archive. +web_archive_spam_protection cookie + +###\\\\ Bounce management and tracking ////### + +## Default bounce warn rate +## The list owner receives a warning whenever a message is distributed and the +## number (percentage) of bounces exceeds this value. +bounce_warn_rate 30 + +## Default bounce halt rate +## NOT USED YET. If bounce rate reaches the halt_rate, messages for the list +## will be halted, i.e. they are retained for subsequent moderation. +bounce_halt_rate 50 + +## Remove bouncing new subscribers +## If set to unique, the welcome message is sent using a unique return path in +## order to remove the subscriber immediately in the case of a bounce. +welcome_return_path owner + +## Remove subscribers bouncing remind message +## Same as welcome_return_path, but applied to remind messages. +remind_return_path owner + +## Task for expiration of old bounces +## This task resets bouncing information for addresses not bouncing in the +## last 10 days after the latest message distribution. +expire_bounce_task daily + +###\\\\ Automatic lists ////### + +## Definition of automatic list families +## Defines the families the automatic lists are based on. It is a character +## string structured as follows: +## * each family is separated from the other by a semi-column (;) +## * inside a family definition, each field is separated from the other by a +## column (:) +## * each field has the structure: "<field name>=<filed value>" +## Basically, each time Sympa uses the automatic lists families, the values +## defined in this parameter will be available in the family object. +## * for scenarios: [family->name] +## * for templates: [% family.name %] +# automatic_list_families name=family_one:prefix=f1:display=My automatic lists:prefix_separator=+:classes separator=-:family_owners_list=alist@domain.tld;name=family_two:prefix=f2:display=My other automatic lists:prefix_separator=+:classes separator=-:family_owners_list=anotherlist@domain.tld; + +## Parsed files for families +## comma-separated list of files that will be parsed by Sympa when +## instantiating a family (no space allowed in file names) +parsed_family_files message.footer,message.header,message.footer.mime,message.header.mime,info + +###\\\\ Tag based spam filtering ////### + +## Header field to tag spams +## If a spam filter (like spamassassin or j-chkmail) add a header field to tag +## spams, name of this header field (example X-Spam-Status) +antispam_tag_header_name X-Spam-Status + +## Regular expression to check header field to tag spams +## Regular expression applied on this header to verify message is a spam +## (example Yes) +antispam_tag_header_spam_regexp ^\s*Yes + +## Regular expression to determine spam or ham. +## Regular expression applied on this header field to verify message is NOT a +## spam (example No) +antispam_tag_header_ham_regexp ^\s*No + +## Name of header field to inform +## Messages are supposed to be filtered by an spam filter that add one more +## headers to messages. This parameter is used to select a special scenario in +## order to decide the message spam status: ham, spam or unsure. This +## parameter replace antispam_tag_header_name, antispam_tag_header_spam_regexp +## and antispam_tag_header_ham_regexp. +spam_status x-spam-status + +###\\\\ Directories ////### + +## List home +## Base directory of list configurations. +home /var/lib/sympa/expl + +## Directory for configuration files +## Base directory of global configuration (except "sympa.conf"). +etc /etc/sympa + +## Base directory of spools +## Base directory of all spools which are created at runtime. This directory +## must be writable by Sympa user. +spool /var/spool/sympa + +## Directory for message incoming spool +## This spool is used both by "queue" program and "sympa_msg.pl" daemon." +queue /var/spool/sympa/msg + +## Directory for moderation spool +queuemod /var/spool/sympa/moderation + +## Directory for digest spool +queuedigest /var/spool/sympa/digest + +## Directory for held message spool +## This parameter is named such by historical reason. +queueauth /var/spool/sympa/auth + +## Directory for archive spool +## This parameter is named such by historical reason. +queueoutgoing /var/spool/sympa/outgoing + +## Directory for held request spool +## This parameter is named such by historical reason. +queuesubscribe /var/spool/sympa/subscribe + +## Directory for topic spool +queuetopic /var/spool/sympa/topic + +## Directory for bounce incoming spool +## This spool is used both by "bouncequeue" program and "bounced.pl" daemon. +queuebounce /var/spool/sympa/bounce + +## Directory for task spool +queuetask /var/spool/sympa/task + +## Directory for automatic list creation spool +## This spool is used both by "familyqueue" program and "sympa_automatic.pl" +## daemon. +queueautomatic /var/spool/sympa/automatic + +## Directory for message outgoing spool +## This parameter is named such by historical reason. +queuebulk /var/spool/sympa/bulk + +## Directory to cache formatted messages +## Base directory path of directories where HTML view of messages are cached. +viewmail_dir /var/spool/sympa/viewmail + +## Directory for storing bounces +## The directory where bounced.pl daemon will store the last bouncing message +## for each user. A message is stored in the file: <bounce_path>/<list +## name>@<mail domain name>/<email address>, or, if tracking is enabled: +## <bounce_path>/<list name>@<mail domain name>/<email address>_<envelope ID>. +## Users can access to these messages using web interface in the bounce +## management page. +## Don't confuse with "queuebounce" parameter which defines the spool where +## incoming error reports are stored and picked by bounced.pl daemon. +bounce_path /var/lib/sympa/bounce + +## Directory for storing archives +## Where to store HTML archives. This parameter is used by the "archived.pl" +## daemon. It is a good idea to install the archive outside the web document +## hierarchy to ensure accesses passing WWSympa's access control will be +## prevented. +arc_path /var/lib/sympa/arc + +###\\\\ Miscellaneous ////### + +## Local part of Sympa email address +## Local part (the part preceding the "@" sign) of the address by which mail +## interface of Sympa accepts mail commands. +## If you change the default value, you must modify the mail aliases too. +email sympa + +## Custom robot parameter +## Used to define a custom parameter for your server. Do not forget the +## semicolon between the parameter name and the parameter value. +## You will be able to access the custom parameter value in web templates by +## variable "conf.custom_robot_parameter.<param_name>" +# custom_robot_parameter param_name ; param_value + +## Use of binary cache of list configuration +## binary_file: Sympa processes will maintain a binary version of the list +## configuration, "config.bin" file on local disk. If you manage a big amount +## of lists (1000+), it should make the web interface startup faster. +## You can recreate cache by running "sympa.pl --reload_list_config". +cache_list_config none + +## Max age of logs in database +## Number of months that elapse before a log is expired +logs_expiration_period 3 + +## Umask +## Default mask for file creation (see umask(2)). Note that it will be +## interpreted as an octal value. +umask 027 + +## Secret string for generating unique keys +## This allows generated authentication keys to differ from a site to another. +## It is also used for encryption of user passwords stored in the database. +## The presence of this string is one reason why access to "sympa.conf" needs +## to be restricted to the "sympa" user. +## Note that changing this parameter will break all HTTP cookies stored in +## users' browsers, as well as all user passwords and lists X509 private keys. +## To prevent a catastrophe, Sympa refuses to start if this "cookie" parameter +## was changed. +# cookie 123456789 + +###\\\\ Web interface parameters ////### + +## URL prefix of web interface +## This is used to construct URLs of web interface. +wwsympa_url https://<%= vhost %>/l + +## URL prefix of WWSympa behind proxy +#http_host http://domain.tld + +## URL for static contents +## HTTP server have to map it with "static_content_path" directory. +static_content_url /static-sympa +css_url /static-sympa/css +pictures_url /static-sympa/pictures + +## Directory for static contents +static_content_path /var/lib/sympa/static_content +css_path /var/lib/sympa/static_content/css +pictures_path /var/lib/sympa/static_content/pictures + +## System log facility for web interface +## System log facility for WWSympa, archived.pl and bounced.pl. Default is to +## use value of "syslog" parameter. +log_facility LOCAL1 + +###\\\\ Web interface parameters: Appearances ////### + +## Type of main web page +## "lists" for the page of list of lists. "home" for home page. +default_home lists + +## Default index organization of web archive +## thrd: Threaded index. +## mail: Chronological index. +archive_default_index thrd + +## Size of review page +## Default number of lines of the array displaying users in the review page +review_page_size 25 + +## Size of viewlogs page +## Default number of lines of the array displaying the log entries in the logs +## page. +viewlogs_page_size 25 + +###\\\\ Web interface parameters: Miscellaneous ////### + +## HTTP cookies validity domain +## If beginning with a dot ("."), the cookie is available within the specified +## Internet domain. Otherwise, for the specified host. The only reason for +## replacing the default value would be where WWSympa's authentication process +## is shared with an application running on another host. +cookie_domain <%= vhost %> + +## HTTP cookies lifetime +## This is the default value when not set explicitly by users. "0" means the +## cookie may be retained during browser session. +cookie_expire 0 + +## Average interval to refresh HTTP session ID. +cookie_refresh 60 + +## Use HTML editor +## If set to "on", users will be able to post messages in HTML using a +## javascript WYSIWYG editor. +use_html_editor 0 + +## URL of HTML editor +## URL path to the javascript file making the WYSIWYG HTML editor available. +## Relative path under <static_content_url> or absolute path. +## Example is for TinyMCE 4 installed under <static_content_path>/js/tinymce/. +# html_editor_url js/tinymce/tinymce.min.js + +## HTML editor initialization +## Javascript excerpt that enables and configures the WYSIWYG HTML editor. +# html_editor_init tinymce.init({selector:"#body",language:lang.split(/[^a-zA-Z]+/).join("_")}); + +## Count limit of wrong password submission +## If this limit is reached, the account is locked until the user renews their +## password. The default value is chosen in order to block bots trying to log +## in using brute force strategy. This value should never be reached by real +## users that will probably uses the renew password service before they +## performs so many tries. +max_wrong_password 19 + +## Password case +## "insensitive" or "sensitive". +## If set to "insensitive", WWSympa's password check will be insensitive. This +## only concerns passwords stored in the Sympa database, not the ones in LDAP. +## Should not be changed! May invalid all user password. +password_case insensitive + +###\\\\ S/MIME and TLS ////### -## Bouncing email rate for warn list owner -#bounce_warn_rate 20 +## Password used to crypt lists private keys +## If not defined, Sympa assumes that list private keys are not encrypted. +# key_passwd your_password -## Bouncing email rate for halt the list (not implemented) -## Not yet used in current version, Default is 50 -#bounce_halt_rate 50 +## Directory containing user certificates +ssl_cert_dir /var/lib/sympa/X509-user-certs -## Task name for expiration of old bounces -#expire_bounce_task daily +###\\\\ Data sources setup ////### -## Welcome message return-path -## If set to unique, new subcriber is removed if welcome message bounce -#welcome_return_path unique +## Default of SQL fetch timeout +## Default timeout while performing a fetch with include_sql_query. +default_sql_fetch_timeout 300 -###\\\\ MTA related ////### +###\\\\ DKIM ////### -## Path to the MTA (sendmail, postfix, exim or qmail) -## should point to a sendmail-compatible binary (eg: a binary named "sendmail" is distributed with Postfix) -sendmail /usr/sbin/sendmail +## Enable DKIM +## If set to "on", Sympa may verify DKIM signatures of incoming messages and/ +## or insert DKIM signature to outgoing messages. +dkim_feature off -## Maximum number of recipients per call to Sendmail. The nrcpt_by_domain.conf file allows a different tuning per destination domain. -nrcpt 25 +## Which service messages to be signed +## Inserts a DKIM signature to service messages in context of robot, list or +## both +dkim_add_signature_to robot,list -## Max. number of different domains per call to Sendmail -avg 10 +## The "d=" tag as defined in rfc 4871 +## The DKIM "d=" tag, is the domain of the signing entity. Default is virtual +## host domain name +dkim_signer_domain <%= vhost %> -## Max. number of Sendmail processes (launched by Sympa) running simultaneously -## Proposed value is quite low, you can rise it up to 100, 200 or even 300 with powerfull systems. -maxsmtp 40 +## Rewrite header for DKIM signed messages and DMARC rejecting domains +dmarc_protection_mode dkim_signature,dmarc_reject -###\\\\ Plugin ////### +###\\\\ Antivirus plug-in ////### ## Path to the antivirus scanner engine -## supported antivirus : McAfee/uvscan, Fsecure/fsav, Sophos, AVP and Trend Micro/VirusWall -#antivirus_path /usr/local/uvscan/uvscan - -## Antivirus pluggin command argument -#antivirus_args --secure --summary --dat /usr/local/uvscan +## Supported antivirus: Clam AntiVirus/clamscan & clamdscan, McAfee/uvscan, +## Fsecure/fsav, Sophos, AVP and Trend Micro/VirusWall +# antivirus_path /usr/local/bin/clamscan -###\\\\ S/MIME pluggin ////### +## Antivirus plugin command line arguments +# antivirus_args --no-summary --database /usr/local/share/clamav -## Path to OpenSSL -## Sympa knowns S/MIME if openssl is installed -#openssl /usr/bin/ssl +###\\\\ Password validation ////### -## The directory path use by OpenSSL for trusted CA certificates -#capath /etc/sympa/ssl.crt +## Password validation +## The password validation techniques to be used against user passwords that +## are added to mailing lists. Options come from Data::Password +## (https://search.cpan.org/~razinf/Data-Password-1.07/Password.pm#VARIABLES) +# password_validation MINLEN=8,GROUPS=3,DICTIONARY=4,DICTIONARIES=/pentest/dictionaries -## This parameter sets the all-in-one file where you can assemble the Certificates of Certification Authorities (CA) -#cafile /usr/local/apache/conf/ssl.crt/ca-bundle.crt - -## User CERTs directory -ssl_cert_dir /var/lib/sympa/X509-user-certs - -crl_dir /var/lib/sympa/crl - -## Password used to crypt lists private keys -#key_passwd your_password - -###\\\\ Database ////### - -## Database type (mysql | Pg | Oracle | Sybase | SQLite) -## be carefull to the case -db_type Pg - -## Name of the database -## with SQLite, the name of the DB corresponds to the DB file -db_name sympa - -## The host hosting your sympa database -db_host pgsql.<%= domain %> - -## The database port -db_port 5432/tcp - -## Database user for connexion -db_user sympa - -## Database password (associated to the db_user) -## What ever you use a password or not, you must protect the SQL server (is it a not a public internet service ?) -db_passwd <%= pgsql_password %> - -## Database private extention to user table -## You need to extend the database format with these fields -#db_additional_user_fields age,address - -## Database private extention to subscriber table -## You need to extend the database format with these fields -#db_additional_subscriber_fields billing_delay,subscription_expiration +###\\\\ Authentication with LDAP ////### -###\\\\ Web interface ////### +## Use canonical email address for LDAP authentication +## When using LDAP authentication, if the identifier provided by the user was +## a valid email, if this parameter is set to false, then the provided email +## will be used to authenticate the user. Otherwise, use of the first email +## returned by the LDAP server will be used. +ldap_force_canonical_email 1 -## Sympa's main page URL -wwsympa_url https://<%= vhost %>/l +###\\\\ Obsoleted parameters ////### -## If a spam filter (like spamassassin or j-chkmail) add a smtp headers to tag spams, name of this header (example X-Spam-Status) -antispam_tag_header_name X-Spam-Status +## Default timeout between two scheduled synchronizations of list members with +## data sources. +default_ttl 3600 -## The regexp applied on this header to verify message is a spam (example \s*Yes) -antispam_tag_header_spam_regexp ^\s*Yes +## Default timeout between two action-triggered synchronizations of list +## members with data sources. +default_distribution_ttl 300 -## The regexp applied on this header to verify message is NOT a spam (example \s*No) -antispam_tag_header_ham_regexp ^\s*No +edit_list owner -# Disable alias management, already managed in postfix -sendmail_aliases none +## Enable FastCGI +## Is FastCGI module for HTTP server installed. This module provide much +## faster web interface. +use_fast_cgi 1 -# keep this enabled for bugzilla automatic mail sending -# feature ( which are marked as such in the header ) -reject_mail_from_automates_feature off +# Upgrade from 6.2.40 to 6.2.42 +# 22 May 2019 at 21:22:06 +shared_feature on diff --git a/modules/sympa/templates/vhost_ml.conf b/modules/sympa/templates/vhost_ml.conf index ad6b4400..11aa7ae5 100644 --- a/modules/sympa/templates/vhost_ml.conf +++ b/modules/sympa/templates/vhost_ml.conf @@ -2,13 +2,19 @@ RewriteRule ^/?$ /l/home [R] RewriteRule ^/l$ /l/ RewriteRule ^/l/(.*)$ /wwsympa-wrapper.fcgi/$1 - + DocumentRoot <%= lib_dir + "/sympa/cgi" %> Alias /static-sympa /var/lib/sympa/static_content <Directory /var/lib/sympa/static_content> - Order allow,deny - Allow from all + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> </Directory> - diff --git a/modules/sympa/templates/webapp_sympa.conf b/modules/sympa/templates/webapp_sympa.conf index b920a8f1..1a508199 100644 --- a/modules/sympa/templates/webapp_sympa.conf +++ b/modules/sympa/templates/webapp_sympa.conf @@ -1,8 +1,16 @@ <Directory <%= lib_dir + "/sympa/cgi" %> > - Options ExecCGI - AddHandler fastcgi-script .fcgi + SetHandler fcgid-script + Options +ExecCGI + AddHandler cgi-script .fcgi DirectoryIndex wwsympa-wrapper.fcgi - Order allow,deny - Allow from all + <IfModule mod_authz_core.c> + # Apache 2.4 + Require all granted + </IfModule> + <IfModule !mod_authz_core.c> + # Apache 2.2 + Order allow,deny + Allow from all + </IfModule> </Directory> diff --git a/modules/testvm/manifests/init.pp b/modules/testvm/manifests/init.pp index a13608f1..d8ca9564 100644 --- a/modules/testvm/manifests/init.pp +++ b/modules/testvm/manifests/init.pp @@ -1,40 +1,40 @@ class testvm { - $testvm_login = "testvm" - $testvmdir = "/home/testvm" + $testvm_login = 'testvm' + $testvmdir = '/home/testvm' - group {"$testvm_login": - ensure => present, + group {"${testvm_login}": + ensure => present, } - user {"$testvm_login": - ensure => present, - comment => "System user used to run test VMs", - managehome => true, - gid => $vmtest_login, - shell => "/bin/bash", + user {"${testvm_login}": + ensure => present, + comment => "System user used to run test VMs", + managehome => true, + gid => $vmtest_login, + shell => '/bin/bash', } - - file { "$testvmdir/bin/": - ensure => directory, + + file { "${testvmdir}/bin/": + ensure => directory, require => User[$testvm_login], } - file { "$testvmdir/bin/_vm": - ensure => present, - owner => root, - group => root, - mode => 644, - source => "puppet:///modules/testvm/_vm", - require => File["$testvmdir/bin"], + file { "${testvmdir}/bin/_vm": + ensure => present, + owner => root, + group => root, + mode => '0644', + source => "puppet:///modules/testvm/_vm", + require => File["${testvmdir}/bin"], } - file { "$testvmdir/bin/vm-jonund": - ensure => present, - owner => root, - group => $testvm_login, - mode => 750, - source => "puppet:///modules/testvm/vm-jonund", - require => File["$testvmdir/bin"], + file { "${testvmdir}/bin/vm-jonund": + ensure => present, + owner => root, + group => $testvm_login, + mode => '0750', + source => "puppet:///modules/testvm/vm-jonund", + require => File["${testvmdir}/bin"], } } diff --git a/modules/timezone/manifests/timezone.pp b/modules/timezone/manifests/timezone.pp index 04abfb73..8f3298a2 100644 --- a/modules/timezone/manifests/timezone.pp +++ b/modules/timezone/manifests/timezone.pp @@ -1,6 +1,6 @@ define timezone::timezone() { file { '/etc/localtime': ensure => link, - target => "/usr/share/zoneinfo/$name" + target => "/usr/share/zoneinfo/${name}" } } diff --git a/modules/transifex/manifests/init.pp b/modules/transifex/manifests/init.pp index 56ad2bf2..282b3f9a 100644 --- a/modules/transifex/manifests/init.pp +++ b/modules/transifex/manifests/init.pp @@ -6,7 +6,7 @@ class transifex { $pgsql_password = extlookup('transifex_pgsql','x') $ldap_password = extlookup('transifex_ldap','x') - $templates_dir = "/var/lib/transifex/templates" + $templates_dir = '/var/lib/transifex/templates' postgresql::remote_db_and_user { 'transifex': description => 'Transifex database', @@ -16,12 +16,12 @@ class transifex { define config() { $filename = $name - file { "/etc/transifex/$filename": + file { "/etc/transifex/${filename}": group => 'apache', mode => '0640', require => Package['transifex'], notify => Service['apache'], - content => template("transifex/$filename"), + content => template("transifex/${filename}"), } } @@ -31,11 +31,11 @@ class transifex { '45-ldap.conf', '50-project.conf']: } - subversion::snapshot { $templates_dir: - source => 'svn://svn.mageia.org/svn/web/templates/transifex/trunk' + git::snapshot { $templates_dir: + source => "git://git.${::domain}/web/templates/transifex" } - apache::vhost::django_app { "transifex.$::domain": + apache::vhost::django_app { "transifex.${::domain}": module => 'transifex', use_ssl => true, module_path => ['/usr/share/transifex','/usr/share','/usr/local/lib/'], @@ -50,7 +50,7 @@ class transifex { require => Package['transifex'], } - apache::vhost::redirect_ssl { "transifex.$::domain": } + apache::vhost::redirect_ssl { "transifex.${::domain}": } # the group are mapped from ldap, since AUTH_LDAP_FIND_GROUP_PERMS is set to yes # but the group need to exist in django first diff --git a/modules/transifex/templates/20-engines.conf b/modules/transifex/templates/20-engines.conf index 13eb0334..620a9556 100644 --- a/modules/transifex/templates/20-engines.conf +++ b/modules/transifex/templates/20-engines.conf @@ -3,14 +3,14 @@ ## Database configuration -# http://docs.djangoproject.com/en/dev/ref/settings/#database-engine +# https://docs.djangoproject.com/en/dev/ref/settings/#database-engine DATABASE_ENGINE = 'postgresql_psycopg2' # Use file path for sqlite3 DATABASE_NAME = 'transifex' # The following are not used for sqlite3 DATABASE_USER = 'transifex' -DATABASE_PASSWORD = '<%= pgsql_password %>' -DATABASE_HOST = 'pgsql.<%= domain %>' # Set to empty string for local socket +DATABASE_PASSWORD = '<%= @pgsql_password %>' +DATABASE_HOST = 'pgsql.<%= @domain %>' # Set to empty string for local socket DATABASE_PORT = '' # Set to empty string for default ## Caching (optional) diff --git a/modules/transifex/templates/30-site.conf b/modules/transifex/templates/30-site.conf index 4d4e9e4c..3c386354 100644 --- a/modules/transifex/templates/30-site.conf +++ b/modules/transifex/templates/30-site.conf @@ -1,7 +1,7 @@ # Sites SITE_ID = 1 # Your site's domain. This is used only in this file. -SITE_DOMAIN = '<%= domain %>' +SITE_DOMAIN = '<%= @domain %>' ADMINS = ( # ('Your Name', 'your_email@domain.com'), diff --git a/modules/transifex/templates/40-apps.conf b/modules/transifex/templates/40-apps.conf index fe1d0492..dd92fb1c 100644 --- a/modules/transifex/templates/40-apps.conf +++ b/modules/transifex/templates/40-apps.conf @@ -56,4 +56,3 @@ AJAX_LOOKUP_CHANNELS = { 'projects' : ('projects.lookups', 'ProjectsLookup'), 'resources' : ('resources.lookups', 'ResourcesLookup'), } - diff --git a/modules/transifex/templates/45-ldap.conf b/modules/transifex/templates/45-ldap.conf index dd215dc9..2532edf5 100644 --- a/modules/transifex/templates/45-ldap.conf +++ b/modules/transifex/templates/45-ldap.conf @@ -17,16 +17,16 @@ from django_auth_ldap.config import LDAPSearch, GroupOfNamesType # Baseline configuration. -AUTH_LDAP_SERVER_URI = "ldap://ldap.<%= domain %> ldap://ldap-slave-1.<%= domain %>" +AUTH_LDAP_SERVER_URI = "ldap://ldap.<%= @domain %> ldap://ldap-slave-1.<%= @domain %>" -AUTH_LDAP_BIND_DN = "cn=transifex-<%= hostname %>,ou=System Accounts,<%= dc_suffix %>" -AUTH_LDAP_BIND_PASSWORD = "<%= ldap_password %>" +AUTH_LDAP_BIND_DN = "cn=transifex-<%= @hostname %>,ou=System Accounts,<%= @dc_suffix %>" +AUTH_LDAP_BIND_PASSWORD = "<%= @ldap_password %>" -AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=People,<%= dc_suffix %> ", +AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=People,<%= @dc_suffix %> ", ldap.SCOPE_SUBTREE, "(|(uid=%(user)s)(mail=%(user)s))") # Set up the basic group parameters. -AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=Group,<%= dc_suffix %>", +AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=Group,<%= @dc_suffix %>", ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)" ) AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr="cn") @@ -42,7 +42,7 @@ AUTH_LDAP_USER_ATTR_MAP = { } AUTH_LDAP_USER_FLAGS_BY_GROUP = { - "is_active": "cn=mga-i18n,ou=Group,<%= dc_suffix %>", - "is_staff": "cn=mga-i18n-committers,ou=Group,<%= dc_suffix %>", - "is_superuser": "cn=mga-sysadmin,ou=Group,<%= dc_suffix %>" + "is_active": "cn=mga-i18n,ou=Group,<%= @dc_suffix %>", + "is_staff": "cn=mga-i18n-committers,ou=Group,<%= @dc_suffix %>", + "is_superuser": "cn=mga-sysadmin,ou=Group,<%= @dc_suffix %>" } diff --git a/modules/transifex/templates/50-project.conf b/modules/transifex/templates/50-project.conf index 761dc725..013741b2 100644 --- a/modules/transifex/templates/50-project.conf +++ b/modules/transifex/templates/50-project.conf @@ -40,7 +40,7 @@ MIDDLEWARE_CLASSES = [ ROOT_URLCONF = 'urls' TEMPLATE_DIRS = [ - '<%= templates_dir %>', + '<%= @templates_dir %>', os.path.join(TX_ROOT, 'templates'), ] @@ -68,7 +68,7 @@ INSTALLED_APPS = [ 'authority', # Transifex specific apps: 'transifex.txcommon', - # It's coming here due http://trac.transifex.org/ticket/596 + # It's coming here due https://trac.transifex.org/ticket/596 'userprofile', 'transifex.languages', 'transifex.projects', diff --git a/modules/viewvc/files/robots.txt b/modules/viewvc/files/robots.txt new file mode 100644 index 00000000..dbb13834 --- /dev/null +++ b/modules/viewvc/files/robots.txt @@ -0,0 +1,29 @@ +User-agent: Googlebot +User-agent: Baiduspider +User-agent: bingbot +User-agent: YandexBot +User-agent: Mail.RU_Bot +User-agent: MJ12bot +User-agent: ClaudeBot +User-agent: Amazonbot +User-agent: PetalBot +User-agent: Bytespider +User-agent: facebookexternalhit +Disallow: /*/tags/ +Disallow: *?view=annotate* +Disallow: *?annotate=* +Disallow: *?view=diff* +Disallow: *?r1=* +Disallow: *sortby=* +Disallow: *sortdir=* +Disallow: *?revision=*&view=markup&* +Disallow: *pathrev=* +Disallow: *?*&view=log* +Disallow: *view=log&* +Disallow: *diff_format=* +User-agent: AhrefsBot +Disallow: / +User-agent: Sogou web spider +Disallow: / +User-agent: * +Crawl-delay: 30 diff --git a/modules/viewvc/files/setcookieredirect.html b/modules/viewvc/files/setcookieredirect.html new file mode 100644 index 00000000..fe98b9dc --- /dev/null +++ b/modules/viewvc/files/setcookieredirect.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> + <head> + <title>User check</title> + <script type="text/javascript" defer> + const randomValue = "6436"; // Chosen by fair dice roll. Guaranteed to be random. + document.cookie = `session=${randomValue}; path=/; expires=${new Date(Date.now() + 24*3600*1000).toUTCString()}`; + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + let path = params.to; + // Sanitize redirect path to avoid malicious arbitrary redirects + if (/^\/[-a-zA-Z0-9~_.?&=/+]*$/.test(decodeURIComponent(path))) { + const current = new URL(window.location.toLocaleString()); + window.location.href = encodeURI(current.origin + decodeURIComponent(path)); + } else { + window.onload = function() { + document.getElementById('error').innerHTML = 'Error! Bad redirect location!'; + } + } + </script> + </head> + <body> + Redirecting back... + <br> + <p id="error"><!-- space for error message --></p> + </body> +</html> diff --git a/modules/viewvc/manifests/init.pp b/modules/viewvc/manifests/init.pp index 882fe288..bd676f29 100644 --- a/modules/viewvc/manifests/init.pp +++ b/modules/viewvc/manifests/init.pp @@ -1,13 +1,15 @@ class viewvc { + include apache::mod::fcgid + include viewvc::var package {['viewvc', - 'python-svn', + 'python2-svn', 'python-flup']: } # http_expiration_time = 600 # svn_roots = admin: svn://svn.mageia.org/svn/adm/ file { '/etc/viewvc/viewvc.conf': - content => template('viewvc/viewvc.conf'), + content => template($viewvc::var::tmpl_viewvc_conf), notify => Service['apache'], require => Package['viewvc'], } @@ -16,7 +18,7 @@ class viewvc { webapp_file => 'viewvc/webapp.conf', } - local_script { 'kill_viewvc': + mga_common::local_script { 'kill_viewvc': content => template('viewvc/kill_viewvc.sh'), } @@ -28,10 +30,45 @@ class viewvc { environment => 'MAILTO=root', } - apache::vhost::base { "svnweb.$::domain": - aliases => {'/viewvc' => '/var/www/viewvc/', - '/' => '/usr/share/viewvc/bin/wsgi/viewvc.fcgi/'}, - content => template('viewvc/vhost.conf') + $viewvc_docroot = '/usr/share/viewvc/templates/docroot' + $robotsfile = "$viewvc_docroot/robots.txt" + file { $robotsfile: + ensure => present, + mode => '0644', + owner => root, + group => root, + source => 'puppet:///modules/viewvc/robots.txt', + } + + file { "$viewvc_docroot/setcookieredirect.html": + ensure => present, + mode => '0644', + owner => root, + group => root, + source => 'puppet:///modules/viewvc/setcookieredirect.html', + } + + $vhost_aliases = { + '/viewvc' => $viewvc_docroot, + '/robots.txt' => $robotsfile, + '/_check' => "$viewvc_docroot/setcookieredirect.html", + } + + $script_aliases = { + '/' => '/usr/share/viewvc/bin/wsgi/viewvc.fcgi/', + } + + $process = 4 + + apache::vhost::base { $viewvc::var::hostname: + aliases => $vhost_aliases, + content => template('apache/vhost_fcgid_norobot.conf'), } -} + apache::vhost::base { "ssl_${viewvc::var::hostname}": + vhost => $viewvc::var::hostname, + use_ssl => true, + aliases => $vhost_aliases, + content => template('apache/vhost_fcgid_norobot.conf'), + } +} diff --git a/modules/viewvc/manifests/var.pp b/modules/viewvc/manifests/var.pp new file mode 100644 index 00000000..9027d808 --- /dev/null +++ b/modules/viewvc/manifests/var.pp @@ -0,0 +1,9 @@ +# $hostname: +# vhost used by viewvc +# $tmpl_viewvc_conf: +# path to /etc/viewvc.conf template file +class viewvc::var( + $hostname = "svnweb.${::domain}", + $tmpl_viewvc_conf = 'viewvc/viewvc.conf' +) { +} diff --git a/modules/viewvc/templates/kill_viewvc.sh b/modules/viewvc/templates/kill_viewvc.sh index 4c27d3f3..7283a10c 100755 --- a/modules/viewvc/templates/kill_viewvc.sh +++ b/modules/viewvc/templates/kill_viewvc.sh @@ -1,13 +1,12 @@ #!/bin/sh +# Kill viewvc if the process gets too large +max_memory=1000000 # size in KiB -max_memory=1000000 - -for process in `pgrep viewvc.fcgi` +for process in $(pgrep viewvc.fcgi) do process_mem=$(pmap "$process" | grep total | sed 's/ \+total \+\([[:digit:]]\+\)K/\1/') - if [ "$process_mem" -gt "$max_memory" ] + if [ -n "$process_mem" ] && [ "$process_mem" -gt "$max_memory" ] then - kill -15 "$process" + kill -15 "$process" fi done - diff --git a/modules/viewvc/templates/vhost.conf b/modules/viewvc/templates/vhost.conf deleted file mode 100644 index 28916f98..00000000 --- a/modules/viewvc/templates/vhost.conf +++ /dev/null @@ -1,2 +0,0 @@ - FastCgiServer /usr/share/viewvc/bin/wsgi/viewvc.fcgi -processes 4 -idle-timeout 30 - diff --git a/modules/viewvc/templates/viewvc.conf b/modules/viewvc/templates/viewvc.conf index 920aa9ed..dec74771 100644 --- a/modules/viewvc/templates/viewvc.conf +++ b/modules/viewvc/templates/viewvc.conf @@ -113,7 +113,7 @@ ## repositories may reside. Rather than force you to add a new entry ## to 'cvs_roots' or 'svn_roots' each time you create a new repository, ## ViewVC rewards you for organising all your repositories under a few -## parent directories by allowing you to simply specifiy just those +## parent directories by allowing you to simply specify just those ## parent directories. ViewVC will then notice each repository in that ## directory as a new root whose name is the subdirectory of the parent ## path in which that repository lives. @@ -326,7 +326,7 @@ mime_types_files = /etc/viewvc/mimetypes.conf, /etc/httpd/conf/mime.types #checkout_magic = 0 ## allowed_views: List the ViewVC views which are enabled. Views not -## in this comma-delited list will not be served (or, will return an +## in this comma-delimited list will not be served (or, will return an ## error on attempted access). ## Possible values: "annotate", "co", "diff", "markup", "roots", "tar" ## @@ -484,7 +484,7 @@ http_expiration_time = 600 ## #hr_funout = 0 -## hr_ignore_white: Ignore whitespace (indendation and stuff) for human +## hr_ignore_white: Ignore whitespace (indentation and stuff) for human ## readable diffs. ## ('-w' option to diff) ## @@ -650,7 +650,7 @@ log_pagesize = 100 ## directory specified by the "template_dir" configuration option (see ## the documentation for that option for details). But if you want to ## use a different template for a particular view, simply uncomment the -## appropriate option below and specify the currect location of the EZT +## appropriate option below and specify the correct location of the EZT ## template file you wish to use for that view. ## ## Templates are specified relative to the configured template diff --git a/modules/xinetd/manifests/port_forward.pp b/modules/xinetd/manifests/port_forward.pp index 23d00f03..2717466e 100644 --- a/modules/xinetd/manifests/port_forward.pp +++ b/modules/xinetd/manifests/port_forward.pp @@ -1,6 +1,6 @@ define xinetd::port_forward($target_ip, $target_port, $port, $proto = 'tcp') { include xinetd - file { "/etc/xinetd.d/$name": + file { "/etc/xinetd.d/${name}": require => Package['xinetd'], content => template('xinetd/port_forward'), notify => Service['xinetd'] diff --git a/modules/xinetd/manifests/service.pp b/modules/xinetd/manifests/service.pp index 23ebeedf..24caafd9 100644 --- a/modules/xinetd/manifests/service.pp +++ b/modules/xinetd/manifests/service.pp @@ -1,6 +1,6 @@ define xinetd::service($content) { include xinetd - file { "/etc/xinetd.d/$name": + file { "/etc/xinetd.d/${name}": require => Package['xinetd'], content => $content, notify => Service['xinetd'] diff --git a/modules/xinetd/templates/port_forward b/modules/xinetd/templates/port_forward index 16ba9a1c..99518dcd 100644 --- a/modules/xinetd/templates/port_forward +++ b/modules/xinetd/templates/port_forward @@ -1,16 +1,15 @@ -service <%= name %> +service <%= @name %> { disable = no type = UNLISTED -<%- if proto == 'tcp' -%> +<%- if @proto == 'tcp' -%> socket_type = stream <%- else -%> socket_type = dgram <%- end -%> - protocol = <%= proto %> + protocol = <%= @proto %> user = nobody wait = no - redirect = <%= target_ip %> <%= target_port %> - port = <%= port %> + redirect = <%= @target_ip %> <%= @target_port %> + port = <%= @port %> } - diff --git a/modules/xymon/manifests/client.pp b/modules/xymon/manifests/client.pp index 58d44257..cfde8134 100644 --- a/modules/xymon/manifests/client.pp +++ b/modules/xymon/manifests/client.pp @@ -1,17 +1,19 @@ class xymon::client { package { 'xymon-client': } - service { 'xymon-client': + $service = 'xymon' + + service { $service: hasstatus => false, - status => "$::lib_dir/xymon/client/runclient.sh status", + status => "${::lib_dir}/xymon/client/runclient.sh status", require => Package['xymon-client'], } - # TODO replace with a exported ressource + # TODO replace with a exported resource $server = extlookup('hobbit_server','x') file { '/etc/sysconfig/xymon-client': content => template('xymon/xymon-client'), - notify => Service['xymon-client'], + notify => Service[$service], require => Package['xymon-client'], } } diff --git a/modules/xymon/manifests/server.pp b/modules/xymon/manifests/server.pp index 223dab6b..b6c269cf 100644 --- a/modules/xymon/manifests/server.pp +++ b/modules/xymon/manifests/server.pp @@ -1,12 +1,6 @@ class xymon::server { package { ['xymon','fping']: } - service { 'xymon': - hasstatus => false, - status => "su xymon -c '$::lib_dir/xymon/server/hobbit.sh status'", - require => Package['xymon'], - } - File { group => 'xymon', require => Package['xymon'], @@ -14,6 +8,11 @@ class xymon::server { } file { + # Define hosts and web view layout, and lists tests to be run against + # host by e.g. network tests from xymon server + '/etc/xymon/hosts.cfg': + content => template('xymon/bb-hosts'); + # Environment variables user by hobbitd,hobbitlaunch,hobbitd_rrd,CGIs # and bbgen (which generates the static html pages) # hobbitlaunch (started by init script) may need to be restarted for @@ -22,11 +21,6 @@ class xymon::server { '/etc/xymon/hobbitserver.cfg': content => template('xymon/hobbitserver.cfg'); - # Define hosts and web view layout, and lists tests to be run against - # host by e.g. network tests from xymon server - '/etc/xymon/bb-hosts': - content => template('xymon/bb-hosts'); - # Defines thresholds for test data reported by clients, e.g. load # disk, procs, ports, memory, as well as those which require some # configuration server side to the client: files, msgs, diff --git a/modules/xymon/templates/bb-hosts b/modules/xymon/templates/bb-hosts index 4d0370f3..140932b5 100644 --- a/modules/xymon/templates/bb-hosts +++ b/modules/xymon/templates/bb-hosts @@ -13,37 +13,40 @@ # You need to define at least the Xymon server itself here. page visible Visible Services -0.0.0.0 blog.<%= domain %> # http://blog.<%= domain %> +0.0.0.0 blog.<%= domain %> # sni https://blog.<%= domain %>/en/ 0.0.0.0 identity.<%= domain %> # https://identity.<%= domain %> 0.0.0.0 bugs.<%= domain %> # https://bugs.<%= domain %> 0.0.0.0 ml.<%= domain %> # https://ml.<%= domain %> -0.0.0.0 www.<%= domain %> # http://www.<%= domain %> -0.0.0.0 svnweb.<%= domain %> # http://svnweb.<%= domain %> +0.0.0.0 www.<%= domain %> # https://www.<%= domain %> +0.0.0.0 svnweb.<%= domain %> # https://svnweb.<%= domain %> 0.0.0.0 epoll.<%= domain %> # https://epoll.<%= domain %> -0.0.0.0 transifex.<%= domain %> # https://transifex.<%= domain %> -0.0.0.0 planet.<%= domain %> # http://planet.<%= domain %> -0.0.0.0 forums.<%= domain %> # https://forums.<%= domain %>=212.85.158.146/ -0.0.0.0 check.<%= domain %> # http://check.<%= domain %> -0.0.0.0 pkgsubmit.<%= domain %> # http://pkgsubmit.<%= domain %> -0.0.0.0 bcd.<%= domain %> # http://bcd.<%= domain %> +0.0.0.0 planet.<%= domain %> # sni https://planet.<%= domain %>/en/ +# This checks the public reverse proxy +0.0.0.0 forums.<%= domain %> # sni https://forums.<%= domain %>=<%= @nodes_ipaddr['sucuk']['ipv4'] %>/ +0.0.0.0 check.<%= domain %> # https://check.<%= domain %> +0.0.0.0 madb.<%= domain %> # https://madb.mageia.org +0.0.0.0 pkgsubmit.<%= domain %> # sni https://pkgsubmit.<%= domain %> +#0.0.0.0 bcd.<%= domain %> # http://bcd.<%= domain %> 0.0.0.0 hugs.<%= domain %> # http://hugs.<%= domain %> 0.0.0.0 dashboard.<%= domain %> # http://dashboard.<%= domain %> -0.0.0.0 meetbot.<%= domain %> # http://meetbot.<%= domain %> +0.0.0.0 meetbot.<%= domain %> # sni https://meetbot.<%= domain %> page servers Servers group-compress Marseille -212.85.158.146 alamut.<%= domain %> # testip bbd dns smtp ssh CLIENT:xymon.<%= domain %> http://xymon.<%= domain %> -212.85.158.147 valstar.<%= domain %> # testip ssh rsync svn git ldapssl ldap +212.85.158.151 sucuk.<%= domain %> # testip bbd dns smtp ssh CLIENT:xymon.<%= domain %> http://xymon.<%= domain %> 212.85.158.148 ecosse.<%= domain %> # testip ssh -212.85.158.149 jonund.<%= domain %> # testip ssh 212.85.158.150 fiona.<%= domain %> # testip ssh -212.85.158.151 sucuk.<%= domain %> # testip ssh 212.85.158.152 rabbit.<%= domain %> # testip ssh +212.85.158.153 duvel.<%= domain %> # testip ssh rsync svn git ldapssl ldap -group-compress Gandi -95.142.164.207 krampouezh.<%= domain %> # ssh dns ldap ldapssl smtp -217.70.188.116 champagne.<%= domain %> # ssh +group-compress VM Sucuk +192.168.122.131 friteuse.<%= domain %> # testip ssh http://forums.<%= domain %>=<%= @nodes_ipaddr['friteuse']['ipv4'] %>/ %>/ -group-compress VM Alamut -192.168.122.131 friteuse.<%= domain %> # testip ssh http://forums.<%= domain %>=192.168.122.131/ https://forums.<%= domain %>=192.168.122.131/ +group-compress Scaleway +163.172.148.228 neru.mageia.org # testip ssh dns ldap ldapssl smtp +163.172.201.211 madb.mageia.org # testip + +# NOTE: lines with IPv6 addresses are ignored in xymon versions before 4.4 or 5.0 +group-compress Oracle cloud +2603:c026:c101:f00::1:1 ociaa1.<%= domain %> # testip ssh diff --git a/modules/xymon/templates/client-local.cfg b/modules/xymon/templates/client-local.cfg index e42ce467..44428778 100644 --- a/modules/xymon/templates/client-local.cfg +++ b/modules/xymon/templates/client-local.cfg @@ -99,7 +99,7 @@ ignore MARK log:/var/log/messages:10240 ignore MARK -[mandrake] +[mageia] log:/var/log/messages:10240 ignore MARK diff --git a/modules/xymon/templates/hobbit-alerts.cfg b/modules/xymon/templates/hobbit-alerts.cfg index 36ff44a4..763e253d 100644 --- a/modules/xymon/templates/hobbit-alerts.cfg +++ b/modules/xymon/templates/hobbit-alerts.cfg @@ -74,10 +74,10 @@ # TIME - rule matching an alert by the time-of-day. This # is specified as the DOWNTIME timespecification # in the bb-hosts file (see bb-hosts(5)). -# DURATION - Rule matcing an alert if the event has lasted +# DURATION - Rule matching an alert if the event has lasted # longer/shorter than the given duration. E.g. # DURATION>10 (lasted longer than 10 minutes) or -# DURARION<30 (only sends alerts the first 30 minutes). +# DURATION<30 (only sends alerts the first 30 minutes). # RECOVERED - Rule matches if the alert has recovered from an # alert state. # NOTICE - Rule matches if the message is a "notify" message @@ -118,7 +118,7 @@ # N is the DOWNSECS value. <% -builder = ['jonund','ecosse','rabbit'] +builder = ['ecosse','rabbit'] builders = builder.map{|x| x + "." + domain }.join(',') %> HOST=<%= builders %> SERVICE=cpu diff --git a/modules/xymon/templates/hobbit-clients.cfg b/modules/xymon/templates/hobbit-clients.cfg index 72140850..ff010681 100644 --- a/modules/xymon/templates/hobbit-clients.cfg +++ b/modules/xymon/templates/hobbit-clients.cfg @@ -102,7 +102,7 @@ # show up in the "ps" listing as a command. The scanner will find # a ps-listing of e.g. "/usr/sbin/cron" if you only specify "processname" # as "cron". -# "processname" can also be a Perl-compatiable regular expression, e.g. +# "processname" can also be a Perl-compatible regular expression, e.g. # "%java.*inst[0123]" can be used to find entries in the ps-listing for # "java -Xmx512m inst2" and "java -Xmx256 inst3". In that case, # "processname" must begin with "%" followed by the reg.expression. @@ -253,7 +253,7 @@ # the output from netstat. This is typically "10.0.0.1:80" for the IP # 10.0.0.1, port 80. Or "*:80" for any local address, port 80. # NB: The Xymon clients normally report only the numeric data for -# IP-adresses and port-numbers, so you must specify the port +# IP-addresses and port-numbers, so you must specify the port # number (e.g. "80") instead of the service name ("www"). # "state" causes only the sockets in the specified state to be included; # it is usually LISTEN or ESTABLISHED. @@ -265,7 +265,7 @@ # # "addr" and "state" can be a simple strings, in which case these string must # show up in the "netstat" at the appropriate column. -# "addr" and "state" can also be a Perl-compatiable regular expression, e.g. +# "addr" and "state" can also be a Perl-compatible regular expression, e.g. # "LOCAL=%(:80|:443)" can be used to find entries in the netstat local port for # both http (port 80) and https (port 443). In that case, portname or state must # begin with "%" followed by the reg.expression. @@ -349,19 +349,20 @@ HOST=rabbit.<%= domain %> DISK %.*stage2$ IGNORE -# jonund has 24 cores and we try and utilise it as much as possible -# la of up to 1.5*cores is probably not problematic -HOST=jonund.<%= domain %> - LOAD 36.0 48.0 - # ecosse has 24 cores, is a builder, and we try to use them all HOST=ecosse.<%= domain %> LOAD 36.0 48.0 -# rabbit has 12 and mksquashfs uses all of them +# rabbit has 12 cores and mksquashfs uses all of them HOST=rabbit.<%= domain %> LOAD 18.0 24.0 +# duvel has 24 cores, dont trigger alarms too soon +HOST=duvel.<%= domain %> + LOAD 18.0 24.0 + DISK /var/lib/binrepo 95 98 + DISK /var/www 95 98 + DEFAULT # These are the built-in defaults. UP 1h diff --git a/modules/xymon/templates/hobbitserver.cfg b/modules/xymon/templates/hobbitserver.cfg index 60dd1a75..a5a7aacf 100644 --- a/modules/xymon/templates/hobbitserver.cfg +++ b/modules/xymon/templates/hobbitserver.cfg @@ -5,7 +5,7 @@ BBSERVERLOGS="/var/log/xymon" # Directory for server logs. The hobbit user must HOBBITCLIENTHOME="<%= lib_dir %>/xymon/client" # BBHOME directory for the client -BBSERVERHOSTNAME="alamut.<%= domain %>" # The hostname of your server +BBSERVERHOSTNAME="sucuk.<%= domain %>" # The hostname of your server BBSERVERIP="<%= ipaddress %>" # The IP-address of your server. Use the real one, not 127.0.0.1 . BBSERVEROS="linux" # The operating system of your server. linux,freebsd,solaris,hpux,aix,osf @@ -29,7 +29,7 @@ PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/lib64/xy # 2011-07-17 15:32:54 Oversize status msg from # 212.85.158.149 for jonund.mageia.org:procs truncated (n=350049, limit=262144) # -# http://en.wikibooks.org/wiki/System_Monitoring_with_Xymon/Other_Docs/FAQ#Q._How_do_I_fix_.22Oversize_status_msg_from_192.168.1.31_for_test.my.com:ports_truncated_.28n.3D508634.2C_limit.3D262144.29.22 +# https://en.wikibooks.org/wiki/System_Monitoring_with_Xymon/Other_Docs/FAQ#Q._How_do_I_fix_.22Oversize_status_msg_from_192.168.1.31_for_test.my.com:ports_truncated_.28n.3D508634.2C_limit.3D262144.29.22 MAXMSG_STATUS="496" ##### Normally you do not need to modify anything below this point ##### @@ -58,7 +58,7 @@ MACHINEDOTS="$BBSERVERHOSTNAME" # This systems hostname MACHINEADDR="$BBSERVERIP" # This systems IP-address # URL's generated/used by bbgen -BBWEBHOST="http://$BBSERVERWWWNAME" # Just the host part of the URL - http://www.foo.com +BBWEBHOST="https://$BBSERVERWWWNAME" # Just the host part of the URL - http://www.foo.com BBWEBHOSTURL="$BBWEBHOST$BBSERVERWWWURL" # Prefix for all static Xymon pages - http://www.foo.com/bb BBWEBHTMLLOGS="$BBWEBHOSTURL/html" # Prefix for the Xymon HTML logs (only if BBLOGSTATUS=STATIC) BBWEB="$BBSERVERWWWURL" # Xymon URL prefix without the host part diff --git a/modules/xymon/templates/xymon-client b/modules/xymon/templates/xymon-client index 1635457c..e846d2a5 100644 --- a/modules/xymon/templates/xymon-client +++ b/modules/xymon/templates/xymon-client @@ -2,19 +2,18 @@ # You MUST set the list of Hobbit servers that this # client reports to. -# It is good to use IP-adresses here instead of DNS +# It is good to use IP-addresses here instead of DNS # names - DNS might not work if there's a problem. # # E.g. (a single Hobbit server) -# HOBBITSERVERS="192.168.1.1" +# HOBBITSERVERS="192.168.1.1" # or (multiple servers) -# HOBBITSERVERS="10.0.0.1 192.168.1.1" +# HOBBITSERVERS="10.0.0.1 192.168.1.1" +XYMONSERVERS="<%= server %>" -HOBBITSERVERS="<%= server %>" - -# The defaults usually suffice for the rest of this file, -# but you can tweak the hostname that the client reports -# data with, and the OS name used (typically needed only on +# The defaults usually suffice for the rest of this file, +# but you can tweak the hostname that the client reports +# data with, and the OS name used (typically needed only on # RHEL or RHAS servers). # CLIENTHOSTNAME="" diff --git a/modules/youri-check/manifests/init.pp b/modules/youri-check/manifests/init.pp index 37902ba2..ebdaa492 100644 --- a/modules/youri-check/manifests/init.pp +++ b/modules/youri-check/manifests/init.pp @@ -1,52 +1,81 @@ class youri-check { class base { - $vhost = "check.$domain" + $vhost = "check.${::domain}" $user = 'youri' $home = '/var/lib/youri' + $home_check = '/var/www/youri-check' + $pgsql_password = extlookup('youri_pgsql','x') user { $user: comment => 'Youri Check', home => $home, } - file { $home: - ensure => directory, - owner => $user, - group => $user, - } + file { $home: + ensure => directory, + owner => $user, + group => $user, + } + + file { $home_check: + ensure => directory, + owner => $user, + group => $user, + } - $pgsql_server = "$vhost" + $pgsql_server = "${vhost}" - package { ['youri-check', 'perl-DBD-Pg', 'perl-Youri-Media']: } + package { ['youri-check', 'perl-DBD-Pg', 'perl-Youri-Media']: } } + define config($version) { - include youri-check::base + include stdlib + include youri-check::base + + $config = "/etc/youri/${version}.conf" + $outdir = "/var/www/youri-check/${version}" + $pgsql_db = "youri_check_${version}" + $pgsql_server = $base::pgsql_server + $pgsql_user = "youri${version}" + $pgsql_password = extlookup('youri_pgsql','x') + # We want to alert for packages older than the cut-off for latest mass rebuild + # 1745539200 is 2025-04-25 + $max_days = (time() - 1745539200)/(24*3600) + + file { "${config}": + ensure => present, + owner => $base::user, + mode => '0640', + content => template("youri-check/${version}.conf"), + require => User[$base::user], + } + } + - $config = "/etc/youri/$version.conf" - $outdir = "/var/www/youri-check/$version" - $pgsql_db = "youri_check_$version" - $pgsql_server = $base::pgsql_server - $pgsql_user = "youri$version" + define createdb_user($version) { + $pgsql_db = "youri_check_${version}" + $pgsql_user = "youri${version}" $pgsql_password = extlookup('youri_pgsql','x') - file { "$config": - ensure => present, - owner => $base::user, - mode => 640, - content => template("youri-check/$version.conf"), - require => User[$base::user], - } + postgresql::remote_user { $pgsql_user: + password => $base::pgsql_password, + } + + postgresql::remote_database { $pgsql_db: + description => "Youri Check results", + user => $pgsql_user, + } } define check($version, $hour = "*", $minute = 0) { - include youri-check::base - $config = "/etc/youri/$version.conf" - $pgsql_server = $base::pgsql_server - $pgsql_db = "youri_check_$version" - $pgsql_user = "youri$version" - $pgsql_password = extlookup('youri_pgsql','x') + include youri-check::base + $config = "/etc/youri/${version}.conf" + $pgsql_server = $base::pgsql_server + $pgsql_db = "youri_check_${version}" + $pgsql_user = "youri${version}" + $pgsql_password = extlookup('youri_pgsql','x') postgresql::remote_user { $pgsql_user: password => $base::pgsql_password, @@ -54,44 +83,51 @@ class youri-check { postgresql::remote_database { $pgsql_db: description => "Youri Check results", - user => $pgsql_user, + user => $pgsql_user, } - cron { "check_$version": - command => "youri-check -c $config test", - hour => $hour, - minute => $minute, - user => $base::user, - environment => "MAILTO=root", - require => User[$base::user], + cron { "check_${version}": + command => "youri-check -c ${config} --parallel test", + hour => $hour, + minute => $minute, + user => $base::user, + environment => "MAILTO=root", + require => User[$base::user], } } define report_www { include youri-check::base - $outdir = "/var/www/youri-check/" - apache::vhost_simple { $base::vhost: + $outdir = "/var/www/youri-check/" + apache::vhost::base { $base::vhost: + location => $outdir, + content => template('youri-check/vhost_check.conf'), + } + apache::vhost::base { "ssl_${base::vhost}": + vhost => $base::vhost, + use_ssl => true, location => $outdir, + content => template('youri-check/vhost_check.conf'), } } define report($version, $hour = "*", $minute = 20) { include youri-check::base - $config = "/etc/youri/$version.conf" + $config = "/etc/youri/${version}.conf" - $outdir = "/var/www/youri-check/$version" - file { "$outdir": + $outdir = "/var/www/youri-check/${version}" + file { "${outdir}": ensure => directory, - owner => $base::user, - mode => 755, + owner => $base::user, + mode => '0755', } - cron { "check_$version": - command => "youri-check -c $config report", - hour => $hour, - minute => $minute, - user => $base::user, - require => User[$base::user], + cron { "check_${version}": + command => "youri-check -c ${config} report", + hour => $hour, + minute => $minute, + user => $base::user, + require => User[$base::user], } } } diff --git a/modules/youri-check/templates/1.conf b/modules/youri-check/templates/1.conf deleted file mode 100644 index f9feefc7..00000000 --- a/modules/youri-check/templates/1.conf +++ /dev/null @@ -1,177 +0,0 @@ -# vim:ft=yaml:et:sw=4 - -# helper variables -mirror: http://repository.mageia.org/distrib/1 -mirror_i586: ${mirror}/i586/media -mirror_x86_64: ${mirror}/x86_64/media - -# resultset definition -resultset: - class: Youri::Check::Resultset::DBI - options: - driver: Pg - host: <%= pgsql_server %>;sslmode=require - base: <%= pgsql_db %> - user: <%= pgsql_user %> - pass: <%= pgsql_password %> - -resolver: - class: Youri::Check::Maintainer::Resolver::CGI - options: - url: http://pkgsubmit.<%= domain %>/data/maintdb.txt - exceptions: - - nobody - - -# checks definitions -tests: - dependencies: - class: Youri::Check::Test::Dependencies - - missing: - class: Youri::Check::Test::Missing - - updates_mandriva_2010_2: - class: Youri::Check::Test::Updates - options: - aliases: - # Only add exceptions here after making sure that the package has an Epoch - basesystem: ~ - bash-completion: ~ - sources: - mandriva: - class: Youri::Check::Test::Updates::Source::Media::Mandriva - options: - medias: - main.sources: - class: Youri::Media::URPM - options: - name: main - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/main/release/media_info/hdlist.cz - mainupdates.sources: - class: Youri::Media::URPM - options: - name: main-updates - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/main/updates/media_info/hdlist.cz - contrib.sources: - class: Youri::Media::URPM - options: - name: contrib - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/contrib/release/media_info/hdlist.cz - contribupdates.sources: - class: Youri::Media::URPM - options: - name: contrib-updates - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/contrib/updates/media_info/hdlist.cz - -# reports definitions -reports: - file: - class: Youri::Check::Report::File - options: - to: <%= outdir %> - global: 1 - individual: 1 - formats: - html: - class: Youri::Check::Report::Format::HTML - text: - class: Youri::Check::Report::Format::Text - rss: - class: Youri::Check::Report::Format::RSS - -# media definitions -medias: - core.i586: - class: Youri::Media::URPM - options: - name: core - type: binary - hdlist: ${mirror_i586}/media_info/hdlist_core.cz - options: - dependencies: - allowed: - - core.i586 - missing: - allowed: - - core.sources - - core.x86_64: - class: Youri::Media::URPM - options: - name: core - type: binary - hdlist: ${mirror_x86_64}/media_info/hdlist_core.cz - options: - dependencies: - allowed: - - core.x86_64 - - core.i586 - missing: - allowed: - - core.sources - - - core.sources: - class: Youri::Media::URPM - options: - name: core - type: source - hdlist: ${mirror_i586}/media_info/hdlist_core.src.cz - options: - dependencies: - allowed: - - core.x86_64 - - core.i586 - - nonfree.i586: - class: Youri::Media::URPM - options: - name: nonfree - type: binary - hdlist: ${mirror_i586}/media_info/hdlist_nonfree_release.cz - options: - dependencies: - allowed: - - core.i586 - - nonfree.i586 - missing: - allowed: - - nonfree.sources - - nonfree.x86_64: - class: Youri::Media::URPM - options: - name: nonfree - type: binary - hdlist: ${mirror_x86_64}/media_info/hdlist_nonfree_release.cz - options: - dependencies: - allowed: - - core.x86_64 - - core.i586 - - nonfree.x86_64 - - nonfree.i586 - missing: - allowed: - - nonfree.sources - - - nonfree.sources: - class: Youri::Media::URPM - options: - name: nonfree - type: source - hdlist: ${mirror_i586}/media_info/hdlist_nonfree_release.src.cz - options: - dependencies: - allowed: - - core.x86_64 - - nonfree.x86_64 - - core.i586 - - nonfree.i586 - diff --git a/modules/youri-check/templates/2.conf b/modules/youri-check/templates/9.conf index e2b09837..28028080 100644 --- a/modules/youri-check/templates/2.conf +++ b/modules/youri-check/templates/9.conf @@ -1,7 +1,7 @@ # vim:ft=yaml:et:sw=4 # helper variables -mirror: http://repository.mageia.org/distrib/2 +mirror: http://repository.mageia.org/distrib/9 mirror_i586: ${mirror}/i586/media mirror_x86_64: ${mirror}/x86_64/media @@ -18,7 +18,7 @@ resultset: resolver: class: Youri::Check::Maintainer::Resolver::CGI options: - url: http://pkgsubmit.<%= domain %>/data/maintdb.txt + url: https://pkgsubmit.<%= domain %>/data/maintdb.txt exceptions: - nobody @@ -31,43 +31,6 @@ tests: missing: class: Youri::Check::Test::Missing - updates_mandriva_2010_2: - class: Youri::Check::Test::Updates - options: - aliases: - # Only add exceptions here after making sure that the package has an Epoch - basesystem: ~ - bash-completion: ~ - sources: - mandriva: - class: Youri::Check::Test::Updates::Source::Media::Mandriva - options: - medias: - main.sources: - class: Youri::Media::URPM - options: - name: main - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/main/release/media_info/hdlist.cz - mainupdates.sources: - class: Youri::Media::URPM - options: - name: main-updates - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/main/updates/media_info/hdlist.cz - contrib.sources: - class: Youri::Media::URPM - options: - name: contrib - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/contrib/release/media_info/hdlist.cz - contribupdates.sources: - class: Youri::Media::URPM - options: - name: contrib-updates - type: source - hdlist: http://ftp.free.fr/pub/Distributions_Linux/MandrivaLinux/official/2010.2/SRPMS/contrib/updates/media_info/hdlist.cz - # reports definitions reports: file: @@ -100,6 +63,40 @@ medias: allowed: - core.sources + core_updates.i586: + class: Youri::Media::URPM + options: + name: core_updates + type: binary + hdlist: ${mirror_i586}/media_info/hdlist_core_updates.cz + options: + dependencies: + allowed: + - core.i586 + - core_updates.i586 + missing: + allowed: + - core.sources + - core_updates.sources + + core_updates_testing.i586: + class: Youri::Media::URPM + options: + name: core_updates_testing + type: binary + hdlist: ${mirror_i586}/media_info/hdlist_core_updates_testing.cz + options: + dependencies: + allowed: + - core.i586 + - core_updates.i586 + - core_updates_testing.i586 + missing: + allowed: + - core.sources + - core_updates.sources + - core_updates_testing.sources + core.x86_64: class: Youri::Media::URPM options: @@ -115,6 +112,44 @@ medias: allowed: - core.sources + core_updates.x86_64: + class: Youri::Media::URPM + options: + name: core_updates + type: binary + hdlist: ${mirror_x86_64}/media_info/hdlist_core_updates.cz + options: + dependencies: + allowed: + - core.i586 + - core_updates.i586 + - core.x86_64 + - core_updates.x86_64 + missing: + allowed: + - core.sources + - core_updates.sources + + core_updates_testing.x86_64: + class: Youri::Media::URPM + options: + name: core_updates_testing + type: binary + hdlist: ${mirror_x86_64}/media_info/hdlist_core_updates_testing.cz + options: + dependencies: + allowed: + - core.x86_64 + - core_updates.x86_64 + - core_updates_testing.x86_64 + - core.i586 + - core_updates.i586 + - core_updates_testing.i586 + missing: + allowed: + - core.sources + - core_updates.sources + - core_updates_testing.sources core.sources: class: Youri::Media::URPM @@ -128,6 +163,36 @@ medias: - core.x86_64 - core.i586 + core_updates.sources: + class: Youri::Media::URPM + options: + name: core_updates + type: source + hdlist: ${mirror_i586}/media_info/hdlist_core_updates.src.cz + options: + dependencies: + allowed: + - core.x86_64 + - core_updates.x86_64 + - core.i586 + - core_updates.i586 + + core_updates_testing.sources: + class: Youri::Media::URPM + options: + name: core_updates_testing + type: source + hdlist: ${mirror_i586}/media_info/hdlist_core_updates_testing.src.cz + options: + dependencies: + allowed: + - core.x86_64 + - core_updates.x86_64 + - core_updates_testing.x86_64 + - core.i586 + - core_updates.i586 + - core_updates_testing.i586 + nonfree.i586: class: Youri::Media::URPM options: @@ -174,4 +239,3 @@ medias: - nonfree.x86_64 - core.i586 - nonfree.i586 - diff --git a/modules/youri-check/templates/cauldron.conf b/modules/youri-check/templates/cauldron.conf index f294f530..aeace447 100644 --- a/modules/youri-check/templates/cauldron.conf +++ b/modules/youri-check/templates/cauldron.conf @@ -2,7 +2,9 @@ # helper variables mirror: http://repository.mageia.org/distrib/cauldron -mirror_i586: ${mirror}/i586/media +mirror_aarch64: ${mirror}/aarch64/media +mirror_armv7hl: ${mirror}/armv7hl/media +mirror_i686: ${mirror}/i686/media mirror_x86_64: ${mirror}/x86_64/media # resultset definition @@ -18,7 +20,7 @@ resultset: resolver: class: Youri::Check::Maintainer::Resolver::CGI options: - url: http://pkgsubmit.<%= domain %>/data/maintdb.txt + url: https://pkgsubmit.<%= domain %>/data/maintdb.txt exceptions: - nobody @@ -35,6 +37,13 @@ tests: class: Youri::Check::Test::Updates options: aliases: + basesystem: ~ + drakxtools: ~ + drakx-installer-advertising: ~ + drakx-installer-binaries: ~ + drakx-installer-images: ~ + drakx-installer-rescue: ~ + drakx-installer-stage2: ~ horde-accounts: accounts horde-chora: chora horde-forwards: forwards @@ -46,17 +55,26 @@ tests: horde-passwd: passwd horde-turba: turba horde-vacation: vacation - freetype2: freetype - freetype: freetype1 + freetype: freetype2 gstreamer: ~ gstreamer0.10: gstreamer gnupg2: gnupg gnupg: ~ gnome-vfs2: gnome-vfs gnome-vfs: ~ - basesystem: ~ + ldetect: ~ + ldetect-lst: ~ + libutempter: utempter + perl-URPM: ~ + rpm: ~ + rpmdrake: ~ + rpmstats: ~ + rpmtools: ~ + urpmi: ~ vte: ~ vte3: vte + xine-lib: xine-lib1.2 + xine-lib-1.2: xine-lib1.2 sources: cpan: order: 0 @@ -67,30 +85,10 @@ tests: perl-Catalyst-P-S-State-Cookie: Catalyst::Plugin::State::State::Cookie perl-Catalyst-P-S-Store-FastMmap: Catalyst::Plugin::State::Store::FastMmap perl-Catalyst-P-S-Store-File: Catalyst::Plugin::State::Store::File - mandriva: - class: Youri::Check::Test::Updates::Source::Media::Mandriva + gettext: ~ + pear: order: 0 - options: - aliases: - basesystem: ~ - drakxtools: ~ - drakx-installer-advertising: ~ - drakx-installer-binaries: ~ - drakx-installer-images: ~ - drakx-installer-rescue: ~ - drakx-installer-stage2: ~ - enigma: enigma-freeoxyd - ldetect: ~ - ldetect-lst: ~ - perl-URPM: ~ - rpm: ~ - rpmdrake: ~ - rpmstats: ~ - rpmtools: ~ - urpmi: ~ -# pear: -# order: 0 -# class: Youri::Check::Test::Updates::Source::PEAR + class: Youri::Check::Test::Updates::Source::PEAR # pypi: # order: 0 # class: Youri::Check::Test::Updates::Source::PyPI @@ -116,67 +114,35 @@ tests: nilfs-utils: nilfs-tools mobile-broadband-provider-info: ~ cpulimit: ~ + icecream: ~ + colorize: ~ fedora: order: 1 class: Youri::Check::Test::Updates::Source::Fedora options: - url: http://ftp.free.fr/mirrors/fedora.redhat.com/fedora/linux/development/rawhide/source/SRPMS/ aliases: authd: ~ + basesystem: ~ + bash: ~ + freetype: ~ + freetype2: freetype gle: ~ gtksourceview-sharp: ~ - sqlite: sqlite2 - OpenIPMI: OpenIPMI2 + modemmanager: ModemManager + netcat-openbsd: netcat + networkmanager: NetworkManager + networkmanager-applet: network-manager-applet + networkmanager-fortisslvpn: NetworkManager-fortisslvpn + networkmanager-l2tp: NetworkManager-l2tp + networkmanager-libreswan: NetworkManager-libreswan + networkmanager-openconnect: NetworkManager-openconnect + networkmanager-openvpn: NetworkManager-openvpn + networkmanager-pptp: NetworkManager-pptp + networkmanager-vpnc: NetworkManager-vpnc ocaml-lablgtk: ~ ocaml-lablgtk2: ocaml-lablgtk - netcat-openbsd: netcat - freetype: ~ - freetype2: freetype - bash: ~ -# freshmeat: -# order: 1 -# class: Youri::Check::Test::Updates::Source::Freshmeat -# options: -# preload: 1 -# aliases: -# photon: ~ -# cmt: ~ -# boo: ~ -# db2: ~ -# dsh: ~ -# torque: ~ -# mserver: ~ -# svl: ~ -# lam: lammpi -# bazaar: baz -# db4: berkeleydb -# pcp: caltech-pcp -# kamikaze: ~ -# nut: ~ -# sqlite3: sqlite -# sqlite: ~ -# ruby-evas: ~ -# acl: ~ -# listen: ~ -# knob: ~ -# dolphin: ~ -# cheese: ~ -# dumb: ~ -# serpentine: ~ -# mms: ~ -# tasks: ~ -# xsp: ~ -# pd: ~ -# deluge: deluge-torrent -# contacts: ~ -# rt: requesttracker -# psi: psijabberclient -# arena: ~ -# ccp: ~ -# ocaml-camlpdf: camlpdf -# libxml: ~ -# glib: ~ - + OpenIPMI: OpenIPMI2 + sqlite: sqlite2 gentoo: order: 1 class: Youri::Check::Test::Updates::Source::Gentoo @@ -196,7 +162,6 @@ tests: unclutter: ~ pam-krb5: pam_krb5 pam_krb5: ~ - freetype: ~ akonadi: akonadi-server attica: libattica raptor2: raptor @@ -204,77 +169,98 @@ tests: libevent: ~ wifi-radar: ~ tuxmathscrabble: ~ + chromium: ~ + cpulimit: ~ + icecream: ~ + nodejs: ~ gnome: order: 1 class: Youri::Check::Test::Updates::Source::GNOME options: + url: https://download.gnome.org/sources/ aliases: + acme: ~ GConf: ~ GConf2: GConf + gcr: ~ + gcr4: gcr + gdk-pixbuf2.0: gdk-pixbuf glib: ~ glib2.0: glib - glibmm: ~ - glibmm2.4: glibmm - gnome-desktop: ~ - gnome-desktop3: gnome-desktop - goocanvas: ~ - goocanvas2: goocanvas - gtkhtml: ~ - gtkhtml4: gtkhtml + glibmm2.4: ~ + goocanvas2: ~ + gtkmm-documentation3.0: ~ + gtkmm: ~ + gtkmm2.4: ~ + gtkmm3.0: ~ + gtkmm4.0: gtkmm + gtksourceviewmm3.0: ~ gtk: ~ gtk+2.0: ~ - gtk+3.0: gtk - libgda: ~ - libgda4.0: ~ - libgda5.0: libgda - libunique: ~ - libunique3: libunique - libwnck: ~ - libwnck3: libwnck - vte: ~ - vte3: vte + gtk+3.0: ~ + gtk4.0: gtk + modemmanager: ModemManager + networkmanager: NetworkManager + networkmanager-applet: network-manager-applet + networkmanager-fortisslvpn: NetworkManager-fortisslvpn + networkmanager-l2tp: NetworkManager-l2tp + networkmanager-libreswan: NetworkManager-libreswan + networkmanager-openconnect: NetworkManager-openconnect + networkmanager-openvpn: NetworkManager-openvpn + networkmanager-pptp: NetworkManager-pptp + networkmanager-vpnc: NetworkManager-vpnc + notify-sharp: ~ + notify-sharp3: notify-sharp + pango: ~ + pango2.0: pango netbsd: order: 1 class: Youri::Check::Test::Updates::Source::NetBSD - sourceforge: - class: Youri::Check::Test::Updates::Source::Sourceforge - options: - aliases: - bigforth: ~ - gtkmm: ~ - hydrogen: ~ - ltp: ~ - pblogan: ~ - console-tools: ~ - maxima: ~ - clisp: ~ +# sourceforge: +# class: Youri::Check::Test::Updates::Source::Sourceforge +# options: +# aliases: +# bigforth: ~ +# gtkmm: ~ +# hydrogen: ~ +# ltp: ~ +# pblogan: ~ +# console-tools: ~ +# maxima: ~ +# clisp: ~ - updates_fedora: + updates_fedora: class: Youri::Check::Test::Updates options: - aliases: - basesystem: ~ - rpm: ~ sources: fedora: order: 1 class: Youri::Check::Test::Updates::Source::Fedora options: - url: http://ftp.free.fr/mirrors/fedora.redhat.com/fedora/linux/development/rawhide/source/SRPMS/ aliases: authd: ~ + basesystem: ~ + bash: ~ + freetype: ~ + freetype2: freetype gle: ~ gtksourceview-sharp: ~ - sqlite: sqlite2 - OpenIPMI: OpenIPMI2 + modemmanager: ModemManager + netcat-openbsd: netcat + networkmanager: NetworkManager + networkmanager-applet: network-manager-applet + networkmanager-fortisslvpn: NetworkManager-fortisslvpn + networkmanager-l2tp: NetworkManager-l2tp + networkmanager-libreswan: NetworkManager-libreswan + networkmanager-openconnect: NetworkManager-openconnect + networkmanager-openvpn: NetworkManager-openvpn + networkmanager-pptp: NetworkManager-pptp + networkmanager-vpnc: NetworkManager-vpnc ocaml-lablgtk: ~ ocaml-lablgtk2: ocaml-lablgtk - netcat-openbsd: netcat - freetype: ~ - freetype2: freetype - bash: ~ - - updates_gnome: + OpenIPMI: OpenIPMI2 + sqlite: sqlite2 + updates_gnome: class: Youri::Check::Test::Updates options: sources: @@ -282,55 +268,42 @@ tests: order: 1 class: Youri::Check::Test::Updates::Source::GNOME options: + url: https://download.gnome.org/sources/ aliases: + acme: ~ GConf: ~ GConf2: GConf + gcr: ~ + gcr4: gcr + gdk-pixbuf2.0: gdk-pixbuf glib: ~ glib2.0: glib - glibmm: ~ - glibmm2.4: glibmm - gnome-desktop: ~ - gnome-desktop3: gnome-desktop - goocanvas: ~ - goocanvas2: goocanvas - gtkhtml: ~ - gtkhtml4: gtkhtml + glibmm2.4: ~ + goocanvas2: ~ + gtkmm-documentation3.0: ~ + gtkmm: ~ + gtkmm2.4: ~ + gtkmm3.0: ~ + gtkmm4.0: gtkmm + gtksourceviewmm3.0: ~ gtk: ~ gtk+2.0: ~ - gtk+3.0: gtk - libgda: ~ - libgda4.0: ~ - libgda5.0: libgda - libunique: ~ - libunique3: libunique - libwnck: ~ - libwnck3: libwnck - vte: ~ - vte3: vte - updates_mandriva: - class: Youri::Check::Test::Updates - options: - sources: - mandriva: - class: Youri::Check::Test::Updates::Source::Media::Mandriva - options: - aliases: - basesystem: ~ - drakxtools: ~ - drakx-installer-advertising: ~ - drakx-installer-binaries: ~ - drakx-installer-images: ~ - drakx-installer-rescue: ~ - drakx-installer-stage2: ~ - enigma: enigma-freeoxyd - ldetect: ~ - ldetect-lst: ~ - perl-URPM: ~ - rpm: ~ - rpmdrake: ~ - rpmstats: ~ - rpmtools: ~ - urpmi: ~ + gtk+3.0: ~ + gtk4.0: gtk + modemmanager: ModemManager + networkmanager: NetworkManager + networkmanager-applet: network-manager-applet + networkmanager-fortisslvpn: NetworkManager-fortisslvpn + networkmanager-l2tp: NetworkManager-l2tp + networkmanager-libreswan: NetworkManager-libreswan + networkmanager-openconnect: NetworkManager-openconnect + networkmanager-openvpn: NetworkManager-openvpn + networkmanager-pptp: NetworkManager-pptp + networkmanager-vpnc: NetworkManager-vpnc + notify-sharp: ~ + notify-sharp3: notify-sharp + pango: ~ + pango2.0: pango build: class: Youri::Check::Test::Build options: @@ -338,12 +311,16 @@ tests: iurt: class: Youri::Check::Test::Build::Source::Iurt options: - url: http://pkgsubmit.mageia.org/autobuild/cauldron + url: https://pkgsubmit.mageia.org/autobuild/cauldron arches: - x86_64 medias: - core - + age: + class: Youri::Check::Test::Age + options: + max: <%= max_days %> days + pattern: "%d days" # reports definitions reports: @@ -363,16 +340,44 @@ reports: # media definitions medias: - core.i586: + core.aarch64: class: Youri::Media::URPM options: name: core type: binary - hdlist: ${mirror_i586}/media_info/hdlist_core.cz + hdlist: ${mirror_aarch64}/core/release/media_info/hdlist.cz options: dependencies: allowed: - - core.i586 + - core.aarch64 + missing: + allowed: + - core.sources + + core.armv7hl: + class: Youri::Media::URPM + options: + name: core + type: binary + hdlist: ${mirror_armv7hl}/core/release/media_info/hdlist.cz + options: + dependencies: + allowed: + - core.armv7hl + missing: + allowed: + - core.sources + + core.i686: + class: Youri::Media::URPM + options: + name: core + type: binary + hdlist: ${mirror_i686}/media_info/hdlist_core.cz + options: + dependencies: + allowed: + - core.i686 missing: allowed: - core.sources @@ -387,7 +392,7 @@ medias: dependencies: allowed: - core.x86_64 - - core.i586 + - core.i686 missing: allowed: - core.sources @@ -398,24 +403,24 @@ medias: options: name: core type: source - hdlist: ${mirror_i586}/media_info/hdlist_core.src.cz + hdlist: ${mirror_i686}/media_info/hdlist_core.src.cz options: dependencies: allowed: - core.x86_64 - - core.i586 + - core.i686 - nonfree.i586: + nonfree.i686: class: Youri::Media::URPM options: name: nonfree type: binary - hdlist: ${mirror_i586}/media_info/hdlist_nonfree_release.cz + hdlist: ${mirror_i686}/media_info/hdlist_nonfree_release.cz options: dependencies: allowed: - - core.i586 - - nonfree.i586 + - core.i686 + - nonfree.i686 missing: allowed: - nonfree.sources @@ -430,9 +435,9 @@ medias: dependencies: allowed: - core.x86_64 - - core.i586 + - core.i686 - nonfree.x86_64 - - nonfree.i586 + - nonfree.i686 missing: allowed: - nonfree.sources @@ -443,12 +448,57 @@ medias: options: name: nonfree type: source - hdlist: ${mirror_i586}/media_info/hdlist_nonfree_release.src.cz + hdlist: ${mirror_i686}/media_info/hdlist_nonfree_release.src.cz options: dependencies: allowed: - core.x86_64 - nonfree.x86_64 - - core.i586 - - nonfree.i586 + - core.i686 + - nonfree.i686 + tainted.i686: + class: Youri::Media::URPM + options: + name: nonfree + type: binary + hdlist: ${mirror_i686}/media_info/hdlist_tainted_release.cz + options: + dependencies: + allowed: + - core.i686 + - tainted.i686 + missing: + allowed: + - tainted.sources + + tainted.x86_64: + class: Youri::Media::URPM + options: + name: tainted + type: binary + hdlist: ${mirror_x86_64}/media_info/hdlist_tainted_release.cz + options: + dependencies: + allowed: + - core.x86_64 + - core.i686 + - tainted.x86_64 + - tainted.i686 + missing: + allowed: + - tainted.sources + + tainted.sources: + class: Youri::Media::URPM + options: + name: tainted + type: source + hdlist: ${mirror_i686}/media_info/hdlist_tainted_release.src.cz + options: + dependencies: + allowed: + - core.x86_64 + - tainted.x86_64 + - core.i686 + - tainted.i686 diff --git a/modules/youri-check/templates/vhost_check.conf b/modules/youri-check/templates/vhost_check.conf new file mode 100644 index 00000000..2cf598b5 --- /dev/null +++ b/modules/youri-check/templates/vhost_check.conf @@ -0,0 +1,2 @@ +Header set Access-Control-Allow-Origin "http://pkgsubmit.<%= domain %>" +Header set Access-Control-Allow-Origin "https://pkgsubmit.<%= domain %>" env=HTTPS |
