Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 292 lines (247 sloc) 9.54 kb
#!/usr/bin/env ruby
require 'rake'
require 'yaml'
require 'set'
require 'pp'
$LOAD_PATH.unshift(File.dirname(__FILE__))
class JobManager
ALL = "all"
NATS = "nats_server"
ROUTER = "router"
STAGER = "stager"
CC = "cloud_controller"
CCDB = "ccdb"
CF = "cloudfoundry"
HM = "health_manager"
DEA = "dea"
UAA = "uaa"
UAADB = "uaadb"
ACM = "acm"
ACMDB = "acmdb"
SERVICES_REDIS= "services_redis"
SERVICE_LIFECYCLE = ["serialization_data_server"]
SERVICES = ["redis", "mysql", "mongodb", "neo4j", "rabbitmq", "postgresql", "vblob", "memcached", "elasticsearch", "couchdb", "echo"]
SERVICES_LIFECYCLE_ENABLED = ["redis", "mysql", "mongodb", "postgresql"]
SERVICES_AUXILIARY = ["service_broker"]
SERVICES_NODE = SERVICES.map do |service|
"#{service}_node"
end
SERVICES_GATEWAY = SERVICES.map do |service|
"#{service}_gateway"
end
SERVICES_WORKER = SERVICES_LIFECYCLE_ENABLED.map do |service|
"#{service}_worker"
end
SERVICES_GATEWAY << "filesystem_gateway"
SERVICES_NODE.each do |node|
# Service name constant e.g. REDIS_NODE -> "redis_node"
const_set(node.upcase, node)
end
SERVICE_TOOLS = ["backup_manager", "snapshot_manager"]
# All supported jobs
JOBS = [ALL, NATS, ROUTER, STAGER, CF, CC, HM, DEA, CCDB, UAA, UAADB, SERVICES_REDIS] + SERVICE_LIFECYCLE + SERVICES_NODE + SERVICES_GATEWAY + SERVICES_AUXILIARY + SERVICE_TOOLS + SERVICES_WORKER
SYSTEM_JOB = [CF]
# List of the required properties for jobs
INSTALLED_JOB_PROPERTIES = {NATS => ["host"], CC => ["service_api_uri"],
CCDB => ["host"]}
INSTALL_JOB_PROPERTIES = {CC => ["builtin_services"], MYSQL_NODE => ["index"], MONGODB_NODE => ["index"], REDIS_NODE => ["index"], NEO4J_NODE => ["index"], POSTGRESQL_NODE => ["index"], RABBITMQ_NODE => ["index"], VBLOB_NODE => ["index"], MEMCACHED_NODE => ["index"], ELASTICSEARCH_NODE => ["index"], COUCHDB_NODE => ["index"], ECHO_NODE => ["index"]}
# Dependency between JOBS and components that are consumed by "vcap_dev" when cf is started or
# stopped
SERVICE_LIFECYCLE_RUN_COMPONENTS = Hash.new
SERVICE_LIFECYCLE.each do |lifecycle|
SERVICE_LIFECYCLE_RUN_COMPONENTS[lifecycle] = lifecycle
end
SERVICE_NODE_RUN_COMPONENTS = Hash.new
SERVICES_NODE.each do |node|
SERVICE_NODE_RUN_COMPONENTS[node] = node
end
SERVICE_GATEWAY_RUN_COMPONENTS = Hash.new
SERVICES_GATEWAY.each do |gateway|
SERVICE_GATEWAY_RUN_COMPONENTS[gateway] = gateway
end
SERVICE_WORKER_RUN_COMPONENTS = Hash.new
SERVICES_WORKER.each do |worker|
SERVICE_WORKER_RUN_COMPONENTS[worker] = worker
end
SERVICE_AUXILIARY_RUN_COMPONENTS = Hash.new
SERVICES_AUXILIARY.each do |service|
SERVICE_AUXILIARY_RUN_COMPONENTS[service] = service
end
SERVICE_TOOL_RUN_COMPONENTS = Hash.new
SERVICE_TOOLS.each do |tool|
SERVICE_TOOL_RUN_COMPONENTS[tool] = tool
end
RUN_COMPONENTS = {ROUTER => ROUTER, STAGER => STAGER, CC => CC, HM => HM, DEA => DEA, UAA => UAA, SERVICES_REDIS => SERVICES_REDIS}.update(SERVICE_LIFECYCLE_RUN_COMPONENTS).update(SERVICE_NODE_RUN_COMPONENTS).update(SERVICE_GATEWAY_RUN_COMPONENTS).update(SERVICE_AUXILIARY_RUN_COMPONENTS).update(SERVICE_TOOL_RUN_COMPONENTS).update(SERVICE_WORKER_RUN_COMPONENTS)
class << self
if defined?(Rake::DSL)
include Rake::DSL
end
# Take user input and create a Hash that has the job name as the key and its
# properties as value.
#
# Allows the user to specify jobs as either
# jobs:
# install:
# - redis
# - mysql
# OR
# jobs:
# install:
# redis:
# mysql:
#
def sanitize_jobs(type)
return nil if @config["jobs"][type].nil?
jobs = {}
config_jobs = @config["jobs"][type]
config_jobs.each do |element|
case element
when String
jobs[element] = nil
when Hash
if element.length > 1
puts "Bad input, #{element.pretty_inspect} should have only one key, please fix your yaml file."
exit 1
end
element.each do |job, properties|
jobs[job] = properties.nil? ? nil : properties.dup
end
else
puts "Unsupported type for Installed or Install job #{element}"
exit 1
end
end
# validate jobs
given_jobs = Set.new(jobs.keys)
if (intersect = @valid_jobs.intersection(given_jobs)) != given_jobs
puts "Input Error: Please provide valid #{type} jobs, following jobs are not recognized\n#{(given_jobs - intersect).pretty_inspect}"
exit 1
end
jobs
end
def detect_duplicate_jobs
if !@config["jobs"]["install"].nil? && !@config["jobs"]["installed"].nil?
install_jobs = Set.new(@config["jobs"]["install"].keys)
installed_jobs = Set.new(@config["jobs"]["installed"].keys)
common = install_jobs.intersection(installed_jobs)
unless common.empty?
puts "Input error, The following jobs are specified in both the install and installed list.\n#{common.pretty_inspect}"
exit 1
end
end
end
def validate_properties(jobs, required_properties)
return if jobs.nil?
missing_keys = {}
jobs.each do |job, properties|
# Check if this job needs properties
next if required_properties[job].nil?
expected = Set.new(required_properties[job])
given = properties.nil? ? Set.new : Set.new(properties.keys)
# Check if all the required properties are given
if !expected.subset?(given)
missing_keys[job] ||= []
missing_keys[job] << (expected - given).to_a
end
end
if !missing_keys.empty?
puts "Input Error: The following mandatory job properties are missing #{missing_keys.pretty_inspect}"
exit 1
end
end
# Gets called by rake tasks for each job.
# The possibilities for each job are as follows.
# 1. It is already installed
# 2. It is in the install list
# 3. It is not on the install list or the installed list
#
# Case 1, propogate the properties of the installed job to the spec
# so dependent jobs can use these properties.
# Case 2, add the required chef role to the chef run list, add default/given
# properties to the spec
# Case 3, is a dependecy failure.
def install(job)
unless @all_install
if !@config["jobs"]["installed"].nil? && !@config["jobs"]["installed"][job].nil?
@spec[job] = @config["jobs"]["installed"][job].dup
return
end
unless @config["jobs"]["install"].has_key?(job) || SYSTEM_JOB.include?(job)
puts "Dependecy check error: job #{job} is needed by one of the jobs in the install list, please add job #{job} to the install or installed list"
exit 1
end
if !@config["jobs"]["install"][job].nil?
@spec[job] = @config["jobs"]["install"][job].dup
end
end
# Prepare the run list for this job
if RUN_COMPONENTS.has_key?(job)
case RUN_COMPONENTS[job]
when String
@run_list << RUN_COMPONENTS[job]
when Array
RUN_COMPONENTS[job].each do |component|
@run_list << component
end
end
end
if job == "snapshot_manager"
@spec["service_lifecycle"] = { :enable => true }
end
@roles << job
end
def process_jobs
# Default to all jobs
if @config["jobs"].nil?
# Install all jobs
@all_install = true
Rake.application[ALL].invoke
return
end
# Make sure that the "install" and "installed" jobs specified are valid
@config["jobs"]["install"] = sanitize_jobs("install")
@config["jobs"]["installed"] = sanitize_jobs("installed")
if @config["jobs"]["install"].nil?
puts "You have not selected any jobs to install."
exit 0
end
# Make sure that the "install" and "installed" jobs do not intersect
detect_duplicate_jobs
if @config["jobs"]["install"].include?("all")
# Install all jobs
if !@config["jobs"]["installed"].nil?
puts "Please correct your config file. You are trying to install all jobs, but you have also specified an 'installed' section"
exit 1
end
if @config["jobs"]["install"].length != 1
puts "Please correct your config file. You are trying to install all jobs, remove all other jobs from the 'install' list"
exit 1
end
@all_install = true
Rake.application[ALL].invoke
return
end
# Sanity check the given properties
validate_properties(@config["jobs"]["installed"], INSTALLED_JOB_PROPERTIES)
validate_properties(@config["jobs"]["install"], INSTALL_JOB_PROPERTIES)
# Let the install rake task do the dependency management
@config["jobs"]["install"].keys.each do |job|
Rake.application[job].invoke
end
end
def go(config)
@spec = {}
@roles = []
@run_list = Set.new
@valid_jobs = Set.new(JOBS)
@config = config.dup
@all_install = false
# Load the job dependecies
Rake.application.rake_require("job_dependency")
process_jobs
# All dependencies are resolved, return the job property spec, chef
# roles and the vcap run list
return @spec, @roles, @run_list.to_a
end
end
end
Jump to Line
Something went wrong with that request. Please try again.