#
# Cookbook:: irrigate-apache
# Recipe:: public_webapps
#
# Author:: Russell de Moose (<rdemoose@theorchard.com>)
# Copyright:: The Orchard
#

if platform_family?('rhel')
  if node['platform_version'].start_with?('7')

    # Add REMI repositories for PHP 5.6
    yum_repository 'remi-php56' do
      description 'Remi PHP 5.6 RPM repository for Enterprise Linux 7'
      mirrorlist 'http://rpms.remirepo.net/enterprise/7/php56/mirror'
      gpgkey 'http://rpms.remirepo.net/RPM-GPG-KEY-remi'
      action :create
    end

    yum_repository 'remi-php56-debuginfo' do
      description 'Remi PHP 5.6 RPM repo for Enterprise Linux 7 - debuginfo'
      baseurl 'http://rpms.remirepo.net/enterprise/7/debug-php56/$basearch/'
      gpgkey 'http://rpms.remirepo.net/RPM-GPG-KEY-remi'
      action :create
    end

    yum_repository 'remi-safe' do
      description 'Safe Remi PHP 5.6 RPM repo for Enterprise Linux 7'
      mirrorlist 'http://rpms.remirepo.net/enterprise/7/safe/mirror'
      gpgkey 'http://rpms.remirepo.net/RPM-GPG-KEY-remi'
      action :create
    end

    # There are extra required packages that are provided by the base
    # and/or apache-specific cookbooks. This array is purpose-specific.
    packages = %w(
      autoconf
      bzip2-devel
      freetype-devel
      gcc-c++
      glibc
      gmp-devel
      httpd-devel
      ImageMagick
      ImageMagick-devel
      libcurl-devel
      libdb4-devel
      libevent
      libjpeg-turbo
      libjpeg-turbo-devel
      libmcrypt
      libmcrypt-devel
      libmemcached
      libpng-devel
      libtiff
      libtiff-devel
      libxml2-devel
      make
      memcached
      mhash
      mhash-devel
      mod_ssl
      openssl-devel
      php56
      php56-php
      php56-php-bcmath
      php56-php-cli
      php56-php-common
      php56-php-devel
      php56-php-gd
      php56-php-gmp
      php56-php-ldap
      php56-php-mbstring
      php56-php-mcrypt
      php56-php-mysqlnd
      php56-php-opcache
      php56-php-pear
      php56-php-pecl-imagick
      php56-php-pecl-imagick-devel
      php56-php-pecl-memcache
      php56-php-pecl-memcached
      php56-php-pecl-ssh2
      php56-php-pecl-uploadprogress
      php56-php-pecl-yaml
      php56-php-pecl-zip
      php56-php-pgsql
      php56-php-soap
      php56-php-xml
      unixODBC
      unixODBC-devel
      zip
    )

    packages.each do |name|
      package name
    end

    # Add symlink for backwards compatibility with older php locations
    link '/usr/local/bin/php' do
      to '/opt/remi/php56/root/bin/php'
    end

    service 'memcached' do
      supports restart: true, status: true, reload: false
      action [:enable, :start]
    end

    deploy_home_dir = '/home/deploy'
    user 'deploy' do
      comment 'Deploy user'
      uid '1001'
      home deploy_home_dir
      shell '/bin/bash'
    end

    group 'webdev' do
      gid '1099'
      members %w(apache deploy)
      action :create
    end

    # SSH key used by deploy processes
    ssh_authorize_key 'deploy' do
      key 'AAAAB3NzaC1yc2EAAAABIwAAAQEAzQ/4Vj3OP6uAiX6cfV5WcBlDQp5jATXMIboUSkEl/FZEbrZFGEsGxhOS5LllHvmH23wVA5rRtmoWxZdcWikiy7GOXzDsWwomBdj5837E55ScV8uL+qXyrN0iI7T8fygqJnqoe87xD742lMWUVujYl7QnQRgwd+LKblzHrvchr8yrl+0rHY1A1oxS1iiQsp+CU/DY+t35YQPFlh3CP1xEuUipcGNkzCZDY/hAI9Prv5Fzvj6RZl+Y+VzgUvoJqKB+rrdv14ZEmvMfNcgM2Tlh33QSQd66Adu2ns22ADXUfsM421nO1IgqZ5dROOblesN8DsrMVCAXM9zL6xddLX47YQ=='
      user 'deploy'
    end

    # Grant sudo access. Specific users and privileges are defined in roles.
    include_recipe 'sudo'

    error_file_directory = node['apache']['error_file_directory']

    directory error_file_directory do
      mode '0755'
      owner 'root'
      group 'webdev'
      recursive true
    end

    error_files = %w(
      404.html
      500.html
    )

    error_files.each do |error_file|
      cookbook_file "#{error_file_directory}/#{error_file}" do
        source error_file
        owner 'root'
        group 'webdev'
        mode '0640'
      end
    end

    # This is a php.ini in the Remi-sandboxed location
    template '/opt/remi/php56/root/etc/php.ini' do
      source 'php.ini.erb'
      mode '0644'
      owner 'root'
      group 'root'
      notifies :restart, 'service[apache2]'
    end

    # PHP opcache configuration snippet in the Remi-sandboxed location
    template '/opt/remi/php56/root/etc/php.d/10-opcache.ini' do
      source '10-opcache.ini.erb'
      mode '0644'
      owner 'root'
      group 'root'
      notifies :restart, 'service[apache2]'
    end

    # PHP memcached configuration snippet in the Remi-sandboxed location
    template '/opt/remi/php56/root/etc/php.d/50-memcached.ini' do
      source '50-memcached.ini.erb'
      mode '0644'
      owner 'root'
      group 'root'
      notifies :restart, 'service[apache2]'
    end

    if node['php']['error_log'].start_with?('/')
      file node['php']['error_log'] do
        action :create_if_missing
        mode '0640'
        owner node['php']['error_log_file_owner']
      end
    end

    # PHP 5.6 is sandboxed, so add to system environment variables.
    template '/etc/profile.d/remi-php.sh' do
      source 'remi-php.sh.erb'
      mode '0644'
      owner 'root'
      group 'root'
    end

    # Create the composer installation script
    cookbook_file '/root/composer-install.sh' do
      source 'composer-install.sh'
      owner 'root'
      group 'root'
      mode '0755'
      action :create
    end

    # Only run the script if composer does not exist
    script 'composer-install' do
      interpreter 'bash'
      code '/root/composer-install.sh'
      not_if { ::File.exist?('/usr/local/bin/composer') }
    end

    # Composer needs a github token for private repositories
    # Create config directories and populate auth.json
    deploy_config_directories = %w(
      /.config
      /.config/composer
    )

    deploy_config_directories.each do |directory_name|
      directory deploy_home_dir + directory_name do
        owner 'deploy'
        mode '0755'
        action :create
      end
    end

    # Read github token from encrypted data bag
    deploy_github_token = data_bag_item('secrets', 'deploy_github_token')
    token = deploy_github_token['token'].chomp

    # Create auth.json for composer using github token
    template deploy_home_dir + '/.config/composer/auth.json' do
      source 'composer-auth.json.erb'
      mode '0644'
      owner 'root'
      group 'root'
      variables ({
        token: token,
      })
    end

    # Private key and secret specific to workstation
    # TODO: Make this conditional and automated.
    ows_auth_key_name = 'ows-auth.pem'
    ows_auth_key_location = "/var/www/#{ows_auth_key_name}"
    ows_auth_key = data_bag_item('secrets', ows_auth_key_name)
    pem = ows_auth_key['pem'].chomp
    file ows_auth_key_location do
      owner 'root'
      mode '0644'
      content pem
    end

    ows_auth_shared_secret_content = data_bag_item(
      'secrets', 'ows_auth_shared_secret')
    secret = ows_auth_shared_secret_content['secret'].chomp
    setenv_secret_params = Hash[
      'OWS_AUTH_PRIVATE_KEY_FILEPATH' => ows_auth_key_location,
      'OWS_AUTH_SHARED_SECRET' => secret
    ]

    # Cron job to update composer
    cron 'composer-update' do
      hour '1'
      user 'root'
      mailto node['apache']['contact']
      command 'php /usr/local/bin/composer self-update >/dev/null 2>&1'
    end

    # Configure SVN repositories
    svn_password = data_bag_item('secrets', 'svn_deploy_password')
    svn_deploy_password = svn_password['password'].chomp

    # Due to a Chef regression (https://github.com/chef/chef/issues/4050),
    # we must create the destination directories for svn before checking out.
    # These directories must also be empty as the time of the checkout or the
    # resource assumes that is has run correctly and will exit with no action.

    svn_directories = %w(
      /var/www/html_api
      /var/www/html_developer
      /var/www/html_epk
      /var/www/html_oa
      /var/www/html_player
      /var/www/html_scc
      /var/www/html_workstation
    )

    svn_directories.each do |directory_name|
      directory directory_name do
        owner 'deploy'
        group 'webdev'
        mode '0755'
        action :create
      end
    end

    subversion 'API' do
      repository 'http://svn.theorchard.com/svn/orchard/trunk'
      revision 'HEAD'
      destination '/var/www/html_api'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'Developer' do
      repository 'http://svn.theorchard.com/svn/orchard/trunk'
      revision 'HEAD'
      destination '/var/www/html_developer'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'EPK' do
      repository 'http://svn.theorchard.com/svn/misc/epk/trunk'
      revision 'HEAD'
      destination '/var/www/html_epk'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'OA' do
      repository 'http://svn.theorchard.com/svn/orchard/trunk'
      revision 'HEAD'
      destination '/var/www/html_oa'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'Player' do
      repository 'http://svn.theorchard.com/svn/misc/orchard_player/trunk'
      revision 'HEAD'
      destination '/var/www/html_player'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'SCC' do
      repository 'http://svn.theorchard.com/svn/misc/soundcloud/trunk'
      revision 'HEAD'
      destination '/var/www/html_scc'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    subversion 'Workstation' do
      repository 'http://svn.theorchard.com/svn/orchard/trunk'
      revision 'HEAD'
      destination '/var/www/html_workstation'
      svn_username 'prod-deploy'
      svn_password svn_deploy_password
      user 'deploy'
      group 'webdev'
      action :checkout
    end

    # Since initial checkout is at the HEAD, also create public directories
    # and seed healthcheck files for load balancer.

    svn_public_directories = %w(
      /var/www/html_api/public
      /var/www/html_developer/public
      /var/www/html_epk/public
      /var/www/html_oa/public
      /var/www/html_oa/public/oa
      /var/www/html_oa/public/oa/images
      /var/www/html_player/public
      /var/www/html_scc/public
      /var/www/html_workstation/public
      /var/www/html_workstation/public/images
    )

    svn_public_directories.each do |directory_name|
      directory directory_name do
        owner 'deploy'
        group 'webdev'
        mode '0755'
        action :create
      end
    end

    healthcheck_files = %w(
      /var/www/html_api/public/healthchk.php
      /var/www/html_developer/public/healthchk.php
      /var/www/html_epk/public/healthchk.php
      /var/www/html_oa/public/healthchk.php
      /var/www/html_player/public/healthchk.php
      /var/www/html_scc/public/healthchk.html
      /var/www/html_workstation/public/healthchk.php
    )

    healthcheck_files.each do |file_name|
      file file_name do
        content 'hello'
        owner 'deploy'
        group 'webdev'
        mode '0644'
        action :create
      end
    end

    # Ensure more open permissions for proxies directories
    proxies_directories = %w(
      /var/www/html_epk/application/Proxies
    )

    proxies_directories.each do |directory_name|
      directory directory_name do
        mode '0775'
        action :create
      end
    end

    # This is used by Workstation as a temporary thumbnail image location
    # Since the affected directories are only present after a managed
    # deployment, this effectively needs to run again after switching svn tags.
    public_image_dir = '/var/www/html_workstation/public/images/'
    if Dir[public_image_dir].empty?
      puts "#{public_image_dir} is empty. Deployment has not taken place."
    else
      Dir.entries(public_image_dir).each do |file|
        next unless file =~ /^coverart|^lg_coverart/
        directory public_image_dir + file do
          owner 'deploy'
          group 'webdev'
          mode '0775'
          action :create
        end
      end
    end

    # This by default references a template with a matching name
    apache_conf 'orchard' do
      enable true
    end

    # Firewall rules for additional Orchard vhosts
    firewall_rule 'http-81' do
      port 81
      protocol :tcp
      position 11
      command :allow
    end

    firewall_rule 'http-82' do
      port 82
      protocol :tcp
      position 12
      command :allow
    end

    firewall_rule 'http-83' do
      port 83
      protocol :tcp
      position 13
      command :allow
    end

    firewall_rule 'http-84' do
      port 84
      protocol :tcp
      position 14
      command :allow
    end

    firewall_rule 'http-85' do
      port 85
      protocol :tcp
      position 15
      command :allow
    end

    firewall_rule 'http-86' do
      port 86
      protocol :tcp
      position 16
      command :allow
    end

    # Ensure the default vhost is disabled
    apache_site 'default' do
      enabled false
    end

    # Explicitly disable the default site if it is active, as a failsafe.
    execute 'a2dissite default' do
      only_if do
        File.symlink?('/etc/httpd/sites-enabled/default.conf')
      end
      notifies :restart, 'service[apache2]'
    end

    # Vhost attributes are contained in roles
    node['webapps'].each do |vhost, vhost_info|
      web_app vhost do
        template 'vhost.conf.erb'
        port vhost_info['port']
        server_admin vhost_info['server_admin']
        server_name vhost_info['server_name']
        if defined?(vhost_info['server_aliases'])
          server_aliases vhost_info['server_aliases']
        end
        docroot vhost_info['docroot']
        if defined?(vhost_info['directory_options'])
          directory_options vhost_info['directory_options']
        end
        allow_override vhost_info['allow_override']
        if vhost_info['setenv_variables'] && !vhost_info['setenv_variables'].empty?
          # Optionally append additional environment variables
          params = vhost_info['setenv_variables']
          if vhost_info['setenv_use_secret_params'] == true
            params = setenv_secret_params.merge(params)
          end
          setenv params
        end
        newrelic vhost_info['newrelic'] if defined?(vhost_info['newrelic'])
      end
    end
  end
end
