#
# Cookbook Name:: docker-grid
# Recipe:: engine
#
# Copyright 2016-2017, whitestar
#
# 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.
#

# https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/

::Chef::Recipe.send(:include, PlatformUtils::VirtUtils)

bash 'systemctl_daemon-reload' do
  code <<-EOH
    systemctl daemon-reload
  EOH
  action :nothing
end

# https://docs.docker.com/engine/userguide/storagedriver/selectadriver/
if shell_out("cat /etc/mtab | grep -E '\s+/\s+zfs\s+'").exitstatus == 0
  if container_guest_node?
    Chef::Log.warn('This node is running in the Linux container with ZFS, set the storage-driver to vfs as a fallback.')
    node.override['docker-grid']['engine']['storage-driver'] = 'vfs'
  else
    Chef::Log.warn('This node is running on ZFS, set the storage-driver to zfs.')
    node.override['docker-grid']['engine']['storage-driver'] = 'zfs'
  end
end

if node['docker-grid']['engine']['storage-driver'] == 'overlay'
  bash 'load_overlayfs_kernel_module' do
    code <<-EOH
      modprobe overlay
    EOH
    not_if 'lsmod | grep overlay'
  end

  template '/etc/modules-load.d/overlay.conf' do
    source  'etc/modules-load.d/overlay.conf'
    owner 'root'
    group 'root'
    mode '0644'
  end
end

log 'reboot_message' do
  message 'Please reboot this machine because of kernel boot option modified.'
  level :warn
  action :nothing
end

userns_remap = node['docker-grid']['engine']['userns-remap']
if !userns_remap.nil? && !userns_remap.empty?
  unless Gem::Version.create(node['docker-grid']['engine']['version'].tr('~', '-')) >= Gem::Version.create('1.10')
    # tr('~', '-') for Ubuntu.
    Chef::Application.fatal!('Docker version must be 1.10 or later for userns-remap.')  # and exit.
  end
  # By default user namespace feature is inactive in RHEL family (>= 7.2).
  if node['platform_family'] == 'rhel' && !container_guest_node?
    unless Gem::Version.create(node['platform_version']) >= Gem::Version.create('7.2')
      Chef::Application.fatal!('Platform version must be 7.2 or later for kernel user namespace feature.')  # and exit.
    end

    bash 'enable_user_namespace_feature_of_kernerl' do
      code <<-"EOH"
        grubby --args='user_namespace.enable=1' --update-kernel=/boot/vmlinuz-#{node['kernel']['release']}
      EOH
      not_if "grubby --info=/boot/vmlinuz-#{node['kernel']['release']} | grep 'user_namespace.enable=1'"
      notifies :write, 'log[reboot_message]'
    end
  end

  remap_user = userns_remap == 'default' ? 'dockremap' : userns_remap
  notifies_conf = {
    'action' => :restart,
    'resource' => 'service[docker]',
    'timer' => :delayed,
  }
  ::Chef::Recipe.send(:include, PlatformUtils::Helper)
  append_subusers([remap_user], notifies_conf)
end

directory '/etc/systemd/system/docker.service.d' do
  owner 'root'
  group 'root'
  mode '0755'
  action :create
end

template '/etc/systemd/system/docker.service.d/override.conf' do
  source  'etc/systemd/system/docker.service.d/override.conf'
  owner 'root'
  group 'root'
  mode '0644'
  notifies :run, 'bash[systemctl_daemon-reload]', :immediately
  notifies :restart, 'service[docker]'
end

case node['platform_family']
when 'rhel'
  # https://dcos.io/docs/1.8/administration/installing/custom/system-requirements/install-docker-centos/
  template '/etc/yum.repos.d/docker.repo' do
    source  'etc/yum.repos.d/docker.repo'
    owner 'root'
    group 'root'
    mode '0644'
  end

  [
    'docker-engine-selinux',
    'docker-engine',
  ].each {|pkg|
    resources(package: pkg) rescue package pkg do
      action :install
      version node['docker-grid']['engine']['version']
      # dockerrepo is disabled by default to prevent automatic update.
      options '--enablerepo=dockerrepo'
    end
  }
when 'debian'
  # https://docs.docker.com/engine/installation/linux/ubuntulinux/
  pkgs = [
    'apt-transport-https',
    'ca-certificates',
  ]

  if node['docker-grid']['engine']['storage-driver'] == 'aufs' \
    && !container_guest_node?
    pkgs += [
      "linux-image-extra-#{node['os_version']}",
      'linux-image-extra-virtual',
    ]
  end

  pkgs.each {|pkg|
    resources(package: pkg) rescue package pkg do
      action :install
    end
  }

  apt_get_update = 'apt-get_update'
  resources(execute: apt_get_update) rescue execute apt_get_update do
    command 'apt-get update'
    action :nothing
  end

  apt_repo_config = node['docker-grid']['apt_repo']
  bash 'apt-key_adv_docker_tools_key' do
    code <<-"EOH"
      apt-key adv --keyserver #{apt_repo_config['keyserver']} --recv-keys #{apt_repo_config['recv-keys']}
      #apt-get update
    EOH
    action :nothing
    not_if 'apt-key list | grep -i docker'
  end

  template '/etc/apt/sources.list.d/docker.list' do
    source  'etc/apt/sources.list.d/docker.list'
    owner 'root'
    group 'root'
    mode '0644'
    notifies :run, 'bash[apt-key_adv_docker_tools_key]', :before
    notifies :run, "execute[#{apt_get_update}]", :immediately
  end

  # Pinning Docker version
  template '/etc/apt/preferences.d/docker.pref' do
    source  'etc/apt/preferences.d/docker.pref'
    owner 'root'
    group 'root'
    mode '0644'
  end

  [
    'docker-engine',
  ].each {|pkg|
    resources(package: pkg) rescue package pkg do
      action :install
      version node['docker-grid']['engine']['version']
    end
  }
end

service 'docker' do
  action [:start, :enable]
  subscribes :restart, 'execute[update-ca-certificates]', :delayed
end

users = node['docker-grid']['engine']['users_allow']
group 'docker' do
  members users unless users.empty?
  action :create
  append true
end
