
# Install and configure Puppet client.
#
# === Global variables
#
#   $puppet_server:
#       Hostname of puppet server. Defaults to 'puppet'.
#
#   $puppet_keylength:
#       Length of client keys. Defaults to 2048.
#
#   $puppet_diffargs:
#       Arguments for puppet's use of diff. Unset by default.
#
class puppet::client {

    tag("bootstrap")

    if ! $puppet_server {
        $puppet_server = "puppet"
    }

    if ! $puppet_keylength {
        $puppet_keylength = "2048"
    }

    case $::operatingsystem {
        openbsd: { $vardir = "/var/puppet" }
        default: { $vardir = "/var/lib/puppet" }
    }

    case $::operatingsystem {
        "centos","redhat","fedora": {
            package { "ruby-shadow":
                ensure => installed,
            }
        }
        ubuntu,debian: {
            package { "libaugeas-ruby":
                ensure => installed,
                name   => regsubst($rubyversion, '^([0-9]+\.[0-9]+)\..*', 'libaugeas-ruby\1'),
                before => Service["puppet"],
            }
        }
        openbsd: {
            if $::operatingsystemrelease == "4.9" {
                file { "/etc/rc.d/puppetd":
                    ensure => present,
                    source => "puppet:///modules/puppet/puppetd.rc",
                    mode   => "0755",
                    owner  => "root",
                    group  => "wheel",
                    before => Service["puppet"],
                }
            }
        }
    }

    file { "/etc/puppet/puppet.conf":
        ensure  => present,
        content => template("puppet/puppet.conf.erb"),
        mode    => "0640",
        owner   => "root",
        group   => $::operatingsystem ? {
            openbsd => "_puppet",
            default => "puppet",
        },
    }

    case $::operatingsystem {
        openbsd: {
            service { "puppet":
                name      => $::operatingsystemrelease ? {
                    /4\.[1-8]/ => "puppet",
                    default    => "puppetd",
                },
                ensure    => running,
                enable    => true,
                start     => "/usr/local/sbin/puppetd",
                stop      => "pkill -f /usr/local/sbin/puppetd",
                status    => "pgrep -f /usr/local/sbin/puppetd",
                restart   => "pkill -HUP -f /usr/local/sbin/puppetd",
                subscribe => File["/etc/puppet/puppet.conf"],
            }
        }
        debian,ubuntu: {
            service { "puppet":
                ensure    => running,
                enable    => true,
                restart   => "/usr/bin/pkill -HUP puppetd",
                subscribe => File["/etc/puppet/puppet.conf"],
            }
            file { "/etc/default/puppet":
                ensure  => present,
                source  => "puppet:///modules/puppet/puppet.enabled.default",
                mode    => "0644",
                owner   => "root",
                group   => "root",
                notify  => Service["puppet"],
            }
        }
        default: {
            service { "puppet":
                ensure    => running,
                enable    => true,
                restart   => "/usr/bin/pkill -HUP puppetd",
                subscribe => File["/etc/puppet/puppet.conf"],
            }
        }
    }

    file { "/usr/local/sbin/puppet-check":
        ensure => present,
        source => "puppet:///modules/puppet/puppet-check",
        mode   => "0755",
        owner  => "root",
        group  => $::operatingsystem ? {
            openbsd => "wheel",
            default => "root",
        },
    }
    cron { "puppet-check":
        ensure      => present,
        environment => $::operatingsystem ? {
            openbsd => "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
            default => undef,
        },
        command     => "/usr/local/sbin/puppet-check",
        user        => root,
        hour        => 5,
        minute      => fqdn_rand(60),
        require     => File["/usr/local/sbin/puppet-check"],
    }

}


# Install and configure Puppet client but disable service.
#
class puppet::manual inherits puppet::client {

    Service["puppet"] {
        ensure    => undef,
        enable    => false,
        subscribe => undef,
    }

    Cron["puppet-check"] {
        ensure => absent,
    }

    case $::operatingsystem {
        debian,ubuntu: {
            File["/etc/default/puppet"] {
                source  => "puppet:///modules/puppet/puppet.disabled.default",
            }
        }
    }

}


class puppet::server {
    fail("puppet::server class is deprecated, use puppet::server::mongrel or puppet::server::apache instead")
}


# Common configuration for all puppet server types.
#
# === Global variables
#
#   $puppet_storeconfigs:
#       Store config type to use. Valid values are "thin", "full" and "none".
#       Defaults to "thin".
#
#   $puppet_dbadapter:
#       Database adapter to use. Defaults to "sqlite3".
#
#   $puppet_dbserver:
#       Database server address. Defaults to "localhost".
#
#   $puppet_dbname:
#       Database name. Defaults to "puppet".
#
#   $puppet_dbuser:
#       Database user name. Defaults to "puppet".
#
#   $puppet_dbpassword:
#       Database password.
#
#   $puppet_report_maxage:
#       Maximum age (in hours) to keep reports. Defaults to 720 hours (30 days).
#
class puppet::server::common inherits puppet::client {

    if $::operatingsystem in ["CentOS","RedHat"] and $::operatingsystemrelease =~ /^[1-5]\..*/ {
        $seltype_readonly = "var_lib_t"
        $seltype_writable = "var_lib_t"
    } else {
        $seltype_readonly = "puppetmaster_t"
        $seltype_writable = "puppet_var_lib_t"
    }

    case $::operatingsystem {
        "openbsd": {
            $user = "_puppet"
            $group = "_puppet"
        }
        default: {
            $user = "puppet"
            $group = "puppet"
        }
    }

    case $puppet_storeconfigs {
        "": { $puppet_storeconfigs = "thin" }
        "thin","full","none": { }
        default: {
            fail("Invalid value ${puppet_storeconfigs} for variable \$puppet_storeconfigs.")
        }
    }

    if !$puppet_dbadapter {
        $puppet_dbadapter = "sqlite3"
    }
    if $puppet_dbadapter != "sqlite3" {
        if !$puppet_dbserver {
            $puppet_dbserver = "localhost"
        }
        if !$puppet_dbname {
            $puppet_dbname = "puppet"
        }
        if !$puppet_dbuser {
            $puppet_dbuser = "puppet"
        }
        if !$puppet_dbpassword {
            fail("\$puppet_dbpassword must be set when using ${puppet_dbadapter}.")
        }
    }

    package { "puppetmaster":
        name   => $::operatingsystem ? {
            debian  => "puppetmaster",
            ubuntu  => "puppetmaster",
            openbsd => "ruby-puppet",
            default => "puppet-server",
        },
        ensure => installed,
        notify => $::operatingsystem ? {
            debian  => Exec["stop-puppetmaster"],
            ubuntu  => Exec["stop-puppetmaster"],
            default => undef,
        },
        before => File["/etc/puppet/puppet.conf"],
    }

    case $::operatingsystem {
        "debian","ubuntu": {
            exec { "stop-puppetmaster":
                command     => "pkill -u puppet ; true",
                path        => "/bin:/usr/bin:/sbin:/usr/sbin",
                refreshonly => true,
                before      => File["/etc/default/puppetmaster"],
            }
        }
    }

    if $puppet_storeconfigs != "none" {
        require ruby::rails
        case $puppet_dbadapter {
            "sqlite3": {
                require ruby::sqlite3
            }
            "mysql": {
                require ruby::mysql
                if $::operatingsystem in ["CentOS","RedHat"] and $::operatingsystemrelease !~ /^[1-5]\..*/ {
                    selinux::boolean { "puppetmaster_use_db":
                        value => "on",
                    }
                }
            }
            default: {
                fail("Invalid value ${puppet_dbadapter} for variable \$puppet_dbadapter.")
            }
        }
    }

    include ruby::rrd

    if $puppet_datadir {
        file { $puppet_datadir:
            ensure  => directory,
            mode    => "0755",
            owner   => "root",
            group   => $::operatingsystem ? {
                "openbsd" => "wheel",
                default   => "root",
            },
            seltype => $seltype_readonly,
            require => Package["puppetmaster"],
        }
        selinux::manage_fcontext { "${puppet_datadir}(/.*)?":
            type   => $seltype_readonly,
            before => File[$puppet_datadir],
        }
        selinux::manage_fcontext { [
          "${puppet_datadir}/bucket(/.*)?",
          "${puppet_datadir}/reports(/.*)?",
          "${puppet_datadir}/rrd(/.*)?",
        ]:
            type   => $seltype_writable,
            before => File["/srv/puppet/reports"],
        }
        file { "/srv/puppet":
            ensure  => link,
            target  => $puppet_datadir,
            seltype => $seltype_readonly,
            require => File[$puppet_datadir],
        }
    } else {
        file { "/srv/puppet":
            ensure  => directory,
            mode    => "0755",
            owner   => "root",
            group   => $::operatingsystem ? {
                "openbsd" => "wheel",
                default   => "root",
            },
            seltype => $seltype_readonly,
            require => Package["puppetmaster"],
        }
    }
    selinux::manage_fcontext { "/srv/puppet(/.*)?":
        type   => $seltype_readonly,
        before => File["/srv/puppet"],
    }
    selinux::manage_fcontext { [
      "/srv/puppet/bucket(/.*)?",
      "/srv/puppet/reports(/.*)?",
      "/srv/puppet/rrd(/.*)?",
    ]:
        type   => $seltype_writable,
        before => File["/srv/puppet/reports"],
    }

    if $puppet_storeconfigs != "none" {
        file { "/srv/puppet/storeconfigs":
            ensure  => directory,
            mode    => "0750",
            owner   => $user,
            group   => $group,
            seltype => $seltype_readonly,
            require => File["/srv/puppet"],
        }
    }
    file { [ "/srv/puppet/bucket",
             "/srv/puppet/reports",
             "/srv/puppet/rrd", ]:
        ensure  => directory,
        mode    => "0750",
        owner   => $user,
        group   => $group,
        seltype => $seltype_writable,
        require => File["/srv/puppet"],
    }
    file { [ "/srv/puppet/files",
             "/srv/puppet/templates" ]:
        ensure  => directory,
        mode    => "0755",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        seltype => $seltype_readonly,
        require => File["/srv/puppet"],
    }
    file { "/srv/puppet/files/common":
        ensure  => directory,
        mode    => "0755",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        seltype => $seltype_readonly,
        require => File["/srv/puppet/files"],
    }
    file { "/srv/puppet/files/private":
        ensure  => directory,
        mode    => "0750",
        owner   => "root",
        group   => $group,
        seltype => $seltype_readonly,
        require => File["/srv/puppet/files"],
    }

    File["/etc/puppet/puppet.conf"] {
        content => template("puppet/puppet.conf.erb", "puppet/puppetmaster.conf.erb"),
    }

    file { "/etc/puppet/tagmail.conf":
        ensure  => present,
        source  => [ "puppet:///files/puppet/tagmail.conf.${fqdn}",
                     "puppet:///files/puppet/tagmail.conf",
                     "puppet:///modules/puppet/tagmail.conf", ],
        mode    => "0644",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        require => Package["puppetmaster"],
    }

    file { "/etc/puppet/fileserver.conf":
        ensure  => present,
        source  => [ "puppet:///files/puppet/fileserver.conf.${fqdn}",
                     "puppet:///files/puppet/fileserver.conf",
                     "puppet:///modules/puppet/fileserver.conf", ],
        mode    => "0644",
        owner   => "root",
        group   => $::operatingsystem ? {
            "openbsd" => "wheel",
            default   => "root",
        },
        require => Package["puppetmaster"],
    }

    if $::operatingsystem != "OpenBSD" {
        if !$puppet_report_maxage {
            $puppet_report_maxage = "720"
        }
        file { "/etc/cron.daily/puppet-report-cleanup":
            ensure  => present,
            content => template("puppet/puppet-report-cleanup.erb"),
            mode    => "0755",
            owner   => "root",
            group   => "root",
            require => File["/srv/puppet/reports"],
        }
    }

    if $puppet_storeconfigs != "none" {
        file { "/usr/local/sbin/puppet-clean-storeconfigs":
            ensure => present,
            source => "puppet:///modules/puppet/puppet-clean-storeconfigs",
            mode   => "0755",
            owner  => "root",
            group  => $::operatingsystem ? {
                openbsd => "wheel",
                default => "root",
            },
        }
    }

}


# Install and configure Puppet server using webrick.
#
# === Global variables
#
#   $puppet_listenports:
#       Array containing ports that puppetmaster should listen to. Defaults to
#       [ "8140" ].
#
class puppet::server::webrick {

    require puppet::server::common

    if ! $puppet_listenports {
        $puppet_listenports = [ "8140" ]
    }

    service { "puppetmaster":
        ensure    => running,
        enable    => true,
        hasstatus => true,
        subscribe => File["/etc/puppet/fileserver.conf",
                          "/etc/puppet/puppet.conf"],
        require => Package["puppetmaster"],
    }

    case $::operatingsystem {
        debian,ubuntu: {
            file { "/etc/default/puppetmaster":
                ensure  => present,
                content => template("puppet/puppetmaster.default.erb"),
                mode    => "0644",
                owner   => "root",
                group   => "root",
                notify  => Service["puppetmaster"],
            }
        }
        default: {
            file { "/etc/sysconfig/puppetmaster":
                ensure  => present,
                content => template("puppet/puppetmaster.sysconfig.erb"),
                mode    => "0644",
                owner   => "root",
                group   => "root",
                notify  => Service["puppetmaster"],
            }
        }
    }

}


# Install and configure Puppet server using mongrel.
#
# === Global variables
#
#   $puppet_listenports:
#       Array containing ports that puppetmaster should listen to. Defaults to
#       [ "18140", "18141", "18142", "18143", ].
#
class puppet::server::mongrel {

    require puppet::server::common

    if ! $puppet_listenports {
        $puppet_listenports = [ "18140", "18141", "18142", "18143", ]
    }

    if $::operatingsystem in ["CentOS","RedHat"] and $::operatingsystemrelease =~ /^[1-5]\..*/ {
        $seltype = "http_port_t"
    } else {
        $seltype = "puppet_port_t"
    }
    selinux::manage_port { $puppet_listenports:
        type   => $seltype,
        proto  => "tcp",
        before => Service["puppetmaster"],
    }

    include ldap::client::ruby
    include ::mongrel

    service { "puppetmaster":
        ensure    => running,
        enable    => true,
        hasstatus => true,
        subscribe => File["/etc/puppet/fileserver.conf",
                          "/etc/puppet/puppet.conf"],
        require   => Package["puppetmaster", "mongrel"],
    }

    case $::operatingsystem {
        debian,ubuntu: {
            file { "/etc/default/puppetmaster":
                ensure  => present,
                content => template("puppet/puppetmaster.default.erb"),
                mode    => "0644",
                owner   => "root",
                group   => "root",
                notify  => Service["puppetmaster"],
            }
        }
        default: {
            file { "/etc/sysconfig/puppetmaster":
                ensure  => present,
                content => template("puppet/puppetmaster.sysconfig.erb"),
                mode    => "0644",
                owner   => "root",
                group   => "root",
                notify  => Service["puppetmaster"],
            }
        }
    }

}


# Install and configure Puppet server using apache as proxy server.
#
class puppet::server::apache {

    require puppet::server::mongrel

    include apache::sslserver
    apache::configfile { "puppet.conf":
        content => template("puppet/puppet-httpd.conf.erb"),
        http    => false,
    }
    case $::operatingsystem {
        debian,ubuntu: {
            include apache::mod::headers
            include apache::mod::proxy
            include apache::mod::proxy_http
            include apache::mod::proxy_balancer
        }
    }

}


# Install and configure Puppet server using nginx and passenger.
#
class puppet::server::nginx::passenger {

    require puppet::server::common

    include ::nginx::passenger
    nginx::configfile { "puppet.conf":
        content => template("puppet/puppet-passenger.conf.erb"),
    }

}


# Install and configure opencollab-puppet-uploader.
#
# === Global variables
#
#   $puppet_opencollab_url:
#       Wiki URL.
#
#   $puppet_opencollab_user:
#       Wiki user.
#
#   $puppet_opencollab_pass:
#       Wiki password.
#
#   $puppet_opencollab_options:
#       Extra options for opencollab-puppet-uploader.
#
class puppet::opencollab {

    if !$puppet_opencollab_url {
        fail("\$puppet_opencollab_url must be set.")
    }
    if !$puppet_opencollab_user {
        fail("\$puppet_opencollab_user must be set.")
    }
    if !$puppet_opencollab_pass {
        fail("\$puppet_opencollab_pass must be set.")
    }

    include wiki::opencollab

    package { "PyYAML":
        name   => $::operatingsystem ? {
            debian  => "python-yaml",
            ubuntu  => "python-yaml",
            default => "PyYAML",
        },
        ensure => installed,
        before => Class["wiki::opencollab"],
    }

    file { "/etc/puppet/opencollab.conf":
        ensure  => present,
        mode    => "0600",
        owner   => "root",
        group   => "root",
        content => "[creds]\nurl = ${puppet_opencollab_url}\nusername = ${puppet_opencollab_user}\npassword = ${puppet_opencollab_pass}\n",
    }

    case $::operatingsystem {
        ubuntu:  { $script = "/usr/local/bin/opencollab-puppet-uploader" }
        default: { $script = "/usr/bin/opencollab-puppet-uploader" }
    }

    if $puppet_opencollab_options {
        $script_options = "-c /etc/puppet/opencollab.conf ${puppet_opencollab_options}"
    } else {
        $script_options = "-c /etc/puppet/opencollab.conf"
    }

    cron { "opencollab-puppet-uploader":
        ensure  => present,
        command => "${script} ${script_options} /var/lib/puppet/yaml/facts/*.yaml",
        user    => root,
        hour    => 0,
        minute  => 5,
        require => [ Class["wiki::opencollab"], File["/etc/puppet/opencollab.conf"] ],
    }

}
