files/gitlab-cookbooks/package/libraries/helpers/services_helper.rb (107 lines of code) (raw):
#
# Copyright:: Copyright (c) 2017 GitLab Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
require_relative '../settings_dsl.rb'
module Services
ALL_SERVICES = 'all'.freeze
ALL_GROUPS = 'all-groups'.freeze
SYSTEM_GROUP = 'system'.freeze
DEFAULT_GROUP = 'default'.freeze
class Config
def self.list
@services.dup
end
def self.service(name, **config)
@services ||= {}
# A service config object always needs a group array
@services[name] = { groups: [] }.merge(config)
end
end
class << self
# Disables the group of services that were passed as arguments
#
# Excludes the groups provided in the *except* argument
# System services are ignored when disabling unless *include_system* is *true*.
#
# @example usage
# Services.disable_group('redis')
# Services.disable_group('monitoring', except: ['redis', 'postgres'])
# Services.disable_group(Services::ALL_GROUPS, except: 'redis')
#
# @param [Array] groups
# @param [Array<String>, String] except
# @param [Boolean] include_system
def disable_group(*groups, except: nil, include_system: false)
exceptions = [except].flatten
exceptions << SYSTEM_GROUP unless include_system
set_service_groups_status(false, *groups, except: exceptions)
end
# Enables the group of services that were passed as arguments
#
# Excludes the groups provided in the *except* argument
#
# @example usage
# Services.enable_group('redis')
# Services.enable_group('monitoring', except: ['redis', 'postgres'])
# Services.enable_group(Services::DEFAULT_GROUP, except: 'redis')
# @param [Array] groups
# @param [Array<String>, String] except
def enable_group(*groups, except: nil)
set_service_groups_status(true, *groups, except: except)
end
# Disables the services that were passed as arguments
#
# Excludes the services provided in the *except* argument
# System services are ignored when disabling unless *include_system* is *true*.
#
# @example usage
# Services.disable('mailroom')
# Services.disable(Services::ALL_SERVICES, except: ['redis', 'sentinel'])
#
# @param [Array] services
# @param [Array<String>, String] except
# @param [Boolean] include_system
def disable(*services, except: nil, include_system: false)
# Automatically excludes system services unless `include_system: true` is passed
exceptions = [*except]
exceptions.concat(system_services) unless include_system
set_services_status(false, *services, except: exceptions)
end
# Enables the services that were passed as arguments
#
# Excludes the services provided in the *except* argument
#
# @example usage
# Services.enable('mailroom')
# Services.enable(Services::ALL_SERVICES, except: ['monitoring'])
#
# @param [Array] services
# @param [Array<String>, String] except
def enable(*services, except: nil)
set_services_status(true, *services, except: except)
end
# Sets the enable status on the services that were passed as arguments
#
# Excludes the service provided in the *except* argument.
# System services are ignored when disabling unless *include_system* is *true*.
#
# @param [Array] services
# @param [Boolean] enable
# @param [Array<String>, String] except
# @param [Boolean] include_system
def set_status(*services, enable, except: nil, include_system: false)
if enable
enable(*services, except: except)
else
disable(*services, except: except, include_system: include_system)
end
end
# Sets the enable status on the service groups that were passed as arguments
#
# Excludes the service groups provided in the *except* argument
# System services are ignored when disabling unless *include_system* is *true*.
#
# @param [Array] groups
# @param [Boolean] enable
# @param [Array<String>, String] except
# @param [Boolean] include_system
def set_group_status(*groups, enable, except: nil, include_system: false)
if enable
enable_group(*groups, except: except)
else
disable_group(*groups, except: except, include_system: include_system)
end
end
# Return a list of system services
#
# @return [Array] list of services
def system_services
find_by_group(SYSTEM_GROUP)
end
# Find services by group
#
# @param [String] group
# @return [Array] list of services
def find_by_group(group)
service_list.select { |_, metadata| metadata[:groups].include?(group) }.keys
end
# List known services along with its associated `groups` metadata
#
# @return [Hash]
def service_list
@service_list ||= {}
end
# Add services from cookbooks
#
# @example usage
# Services.add_services('gitlab', Services::BaseServices.list)
#
# @param [String] cookbook
# @param [Hash] services
def add_services(cookbook, services)
cookbook_services[cookbook] = services
service_list.merge!(services)
end
# Reset stored cookbooks and their related services
#
# @note This is intended to be used in test environment only!
def reset_list!
@cookbook_services = nil
@service_list = nil
end
# Return whether a service is enabled or not
#
# If service status is set via configuration file that takes precedence, otherwise we
# use the computed value instead
#
# @param [String] service
# @return [Boolean] whether is enabled or not
def enabled?(service)
return false unless exist?(service)
user_config = Gitlab[service]['enable']
return user_config unless user_config.nil?
service_status(service)
end
# Return whether a specific service exist
#
# @note In CE distributions, some services may not exist as they are EE only
# @return [Boolean] whether service exist or not
def exist?(service)
!service_list[service].nil?
end
private
def cookbook_services
@cookbook_services ||= {}
end
# Return whether service is enabled or not
#
# @param [String] service
# @return [Boolean] whether enabled or not
def service_status(service)
Gitlab[:node].read(*service_attribute_path(service), 'enable')
end
# Set service enabled/disabled status
#
# @param [String] service
# @param [Boolean] enabled
def set_service_status(service, enabled)
Gitlab[:node].write(:default, *service_attribute_path(service), 'enable', enabled)
end
# Return internal path to manipulate service attributes
#
# @param [String] service_name
# @return [Array]
def service_attribute_path(service_name)
service = SettingsDSL::Utils.node_attribute_key(service_name)
return ['monitoring', service] if Gitlab[:node]['monitoring']&.attribute?(service)
return [service] if Gitlab[:node].attribute?(service)
['gitlab', service]
end
# Set status for a list of services considering provided exceptions
#
# @param [Boolean] enable
# @param [Array] services
# @param [Array<String>, String] except
def set_services_status(enable, *services, except: nil)
exceptions = [*except]
service_list.each do |name, _|
# Skip if service is in exceptions list
next if exceptions.include?(name)
# Skip if service does not *exist?*
next unless exist?(name)
# Set the service enable config if:
# The current service was requested to be set
# OR
# ALL_SERVICES was requested, so we are setting them all
set_service_status(name, enable) if services.include?(name) || services.include?(ALL_SERVICES)
end
end
# Set status for services related with provided groups considering provided exceptions
#
# @param [Boolean] enable
# @param [Array] groups
# @param [Array<String>, String] except
def set_service_groups_status(enable, *groups, except: nil)
exceptions = [*except]
service_list.each do |name, metadata|
# Skip if service is in exceptions list
next if (exceptions & metadata[:groups]).any?
# Skip if service does not *exist?*
next unless exist?(name)
# Find the matching groups among our passed arguments and our current service's groups
matching_groups = groups & metadata[:groups]
# Set the service enable config if:
# The current service has matching groups that were requested to be set
# OR
# ALL_GROUPS was requested, so we are setting them all
set_service_status(name, enable) if matching_groups.any? || groups.include?(ALL_GROUPS)
end
end
end
end