<commit_before>
import unittest
import os
import signal
import logging
import tempfile
import uuid
import shutil
import hashlib
import logging
import subprocess
import socket
import datetime
import time
import copy
import traceback
from distutils.spawn import find_executable

import paasmaker
from paasmaker.util.configurationhelper import InvalidConfigurationParameterException
from paasmaker.util.configurationhelper import InvalidConfigurationFormatException
from paasmaker.util.configurationhelper import NoConfigurationFileException
from paasmaker.util.configurationhelper import StrictAboutExtraKeysColanderMappingSchema
from paasmaker.common.core import constants

from pubsub import pub
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import colander
import tornadoredis
from paasmaker.thirdparty.pika import TornadoConnection
import pika
import yaml

# For parsing command line options.
from tornado.options import define, options
import tornado.testing

# Set up logging for this module.
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

# Set up command line options.
define("debug", type=int, default=0, help="Enable Tornado debug mode. Also prevents Paasmaker from forking into the background.")
define("configfile", type=str, default="", help="Override configuration file.")

# Default ports.
DEFAULT_API_PORT = 42500

DEFAULT_ROUTER_REDIS_MASTER = 42510
DEFAULT_ROUTER_REDIS_SLAVE = 42511
DEFAULT_ROUTER_REDIS_STATS = 42512
DEFAULT_REDIS_JOBS = 42513

DEFAULT_NGINX_DIRECT = 42530
DEFAULT_NGINX_PORT80 = 42531
DEFAULT_NGINX_PORT443 = 42532

DEFAULT_APPLICATION_MIN = 42600
DEFAULT_APPLICATION_MAX = 42699

# The Configuration Schema.
class PluginSchema(StrictAboutExtraKeysColanderMappingSchema):
	name = colander.SchemaNode(colander.String(),
		title="Symbolic name",
		description="The symbolic name for this plugin, used to match it up in application configuration")
	klass = colander.SchemaNode(colander.String(),
		name="class",
		title="Plugin class",
		description="The class used to provide this plugin")
	title = colander.SchemaNode(colander.String(),
		title="Friendly name",
		description="The friendly name for this plugin")
	parameters = colander.SchemaNode(colander.Mapping(unknown='preserve'),
		title="Plugin Parameters",
		description="Parameters for this particular plugin",
		missing={},
		default={})

class PluginsSchema(colander.SequenceSchema):
	plugin = PluginSchema()

class PeriodicSchema(StrictAboutExtraKeysColanderMappingSchema):
	plugin = colander.SchemaNode(colander.String(),
		title="Periodic Plugin",
		description="The periodic plugin to run.")
	interval = colander.SchemaNode(colander.Integer(),
		title="Periodic Interval",
		description="How often to run this periodic plugin.")

class PeriodicsSchema(colander.SequenceSchema):
	periodic = PeriodicSchema()

class PeriodicsOnlySchema(StrictAboutExtraKeysColanderMappingSchema):
	periodics = PeriodicsSchema()

class ScmListerSchema(StrictAboutExtraKeysColanderMappingSchema):
	for_name = colander.SchemaNode(colander.String(),
		name="for",
		title="The SCM plugin that these listers are for.")
	plugins = colander.SchemaNode(colander.Sequence(),
		colander.SchemaNode(colander.String()),
		title="Plugins that list repositories.",
		default=[],
		missing=[])

class ScmListersSchema(colander.SequenceSchema):
	lister = ScmListerSchema()

class HealthPluginSchema(StrictAboutExtraKeysColanderMappingSchema):
	plugin = colander.SchemaNode(colander.String(),
		title="Plugin name",
		description="Plugin name for this particular health check.")
	order = colander.SchemaNode(colander.Integer(),
		title="Plugin order",
		description="The order of execution for this particular plugin. Plugins with the same order are run at the same time. Plugins with lower order numbers are run first. Order numbers do not need to be consecutive.")
	parameters = colander.SchemaNode(colander.Mapping(unknown='preserve'),
		title="Plugin Parameters",
		description="Parameters for this particular plugin",
		missing={},
		default={})

class HealthPluginsSchema(colander.SequenceSchema):
	health = HealthPluginSchema()

	@staticmethod
	def default():
		return {'plugins': []}

class HealthGroupSchema(StrictAboutExtraKeysColanderMappingSchema):
	name = colander.SchemaNode(colander.String(),
		title="Symbolic name",
		description="The symbolic name for this health check group.")
	title = colander.SchemaNode(colander.String(),
		title="Friendly name",
		description="The friendly name for this health check group.")
	period = colander.SchemaNode(colander.Integer(),
		title="Group recheck period",
		description="How often to run this health check group, in seconds.")
	plugins = HealthPluginsSchema(
		default=HealthPluginsSchema.default(),
		missing=HealthPluginsSchema.default()
	)

class HealthGroupsSchema(colander.SequenceSchema):
	group = HealthGroupSchema()

class HealthGroupsOnlySchema(StrictAboutExtraKeysColanderMappingSchema):
	groups = HealthGroupsSchema()

class HealthCombinedSchema(StrictAboutExtraKeysColanderMappingSchema):
	groups = HealthGroupsSchema(
		missing=[],
		default=[]
	)
	enabled = colander.SchemaNode(colander.Boolean(),
		title="Run health checks",
		description="If true, run health checks on this node. If you have multiple pacemakers, you will only want to run this on one node. However, you could configure two pacemakers to perform different health checks.",
		missing=True,
		default=True)
	use_default_checks = colander.SchemaNode(colander.Boolean(),
		title="Include default health checks",
		description="Include default health checks. These are added to any groups. If you do enable this, you should not define a 'default' group.",
		missing=True,
		default=True)

	@staticmethod
	def default():
		return {'enabled': False, 'groups': []}

class PacemakerSchema(StrictAboutExtraKeysColanderMappingSchema):
	enabled = colander.SchemaNode(colander.Boolean(),
		title="Pacemaker enabled",
		description="Pacemaker is enabled for this node",
		missing=False,
		default=False)

	require_ssl = colander.SchemaNode(
		colander.Boolean(),
		title="Require SSL",
		description="If true, require SSL for access to the console and API.",
		missing=False,
		default=False
	)

	dsn = colander.SchemaNode(colander.String(),
		title="Database DSN",
		description="Database connection details for this pacemaker, in SQLAlchemy format")

	database_options = colander.SchemaNode(
		colander.Mapping(unknown='preserve'),
		title="Additional Database options",
		description="Additional Database options, passed as keyword arguments to engine_create. See http://docs.sqlalchemy.org/en/rel_0_7/core/engines.html#engine-creation-api for the available options. This can be used to tweak database connection details.",
		missing={},<commit_msg>Change the defaults for health checks; as this was causing health checks not to be run by default unless explicitly enabled.<commit_after>
import unittest
import os
import signal
import logging
import tempfile
import uuid
import shutil
import hashlib
import logging
import subprocess
import socket
import datetime
import time
import copy
import traceback
from distutils.spawn import find_executable

import paasmaker
from paasmaker.util.configurationhelper import InvalidConfigurationParameterException
from paasmaker.util.configurationhelper import InvalidConfigurationFormatException
from paasmaker.util.configurationhelper import NoConfigurationFileException
from paasmaker.util.configurationhelper import StrictAboutExtraKeysColanderMappingSchema
from paasmaker.common.core import constants

from pubsub import pub
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import colander
import tornadoredis
from paasmaker.thirdparty.pika import TornadoConnection
import pika
import yaml

# For parsing command line options.
from tornado.options import define, options
import tornado.testing

# Set up logging for this module.
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

# Set up command line options.
define("debug", type=int, default=0, help="Enable Tornado debug mode. Also prevents Paasmaker from forking into the background.")
define("configfile", type=str, default="", help="Override configuration file.")

# Default ports.
DEFAULT_API_PORT = 42500

DEFAULT_ROUTER_REDIS_MASTER = 42510
DEFAULT_ROUTER_REDIS_SLAVE = 42511
DEFAULT_ROUTER_REDIS_STATS = 42512
DEFAULT_REDIS_JOBS = 42513

DEFAULT_NGINX_DIRECT = 42530
DEFAULT_NGINX_PORT80 = 42531
DEFAULT_NGINX_PORT443 = 42532

DEFAULT_APPLICATION_MIN = 42600
DEFAULT_APPLICATION_MAX = 42699

# The Configuration Schema.
class PluginSchema(StrictAboutExtraKeysColanderMappingSchema):
	name = colander.SchemaNode(colander.String(),
		title="Symbolic name",
		description="The symbolic name for this plugin, used to match it up in application configuration")
	klass = colander.SchemaNode(colander.String(),
		name="class",
		title="Plugin class",
		description="The class used to provide this plugin")
	title = colander.SchemaNode(colander.String(),
		title="Friendly name",
		description="The friendly name for this plugin")
	parameters = colander.SchemaNode(colander.Mapping(unknown='preserve'),
		title="Plugin Parameters",
		description="Parameters for this particular plugin",
		missing={},
		default={})

class PluginsSchema(colander.SequenceSchema):
	plugin = PluginSchema()

class PeriodicSchema(StrictAboutExtraKeysColanderMappingSchema):
	plugin = colander.SchemaNode(colander.String(),
		title="Periodic Plugin",
		description="The periodic plugin to run.")
	interval = colander.SchemaNode(colander.Integer(),
		title="Periodic Interval",
		description="How often to run this periodic plugin.")

class PeriodicsSchema(colander.SequenceSchema):
	periodic = PeriodicSchema()

class PeriodicsOnlySchema(StrictAboutExtraKeysColanderMappingSchema):
	periodics = PeriodicsSchema()

class ScmListerSchema(StrictAboutExtraKeysColanderMappingSchema):
	for_name = colander.SchemaNode(colander.String(),
		name="for",
		title="The SCM plugin that these listers are for.")
	plugins = colander.SchemaNode(colander.Sequence(),
		colander.SchemaNode(colander.String()),
		title="Plugins that list repositories.",
		default=[],
		missing=[])

class ScmListersSchema(colander.SequenceSchema):
	lister = ScmListerSchema()

class HealthPluginSchema(StrictAboutExtraKeysColanderMappingSchema):
	plugin = colander.SchemaNode(colander.String(),
		title="Plugin name",
		description="Plugin name for this particular health check.")
	order = colander.SchemaNode(colander.Integer(),
		title="Plugin order",
		description="The order of execution for this particular plugin. Plugins with the same order are run at the same time. Plugins with lower order numbers are run first. Order numbers do not need to be consecutive.")
	parameters = colander.SchemaNode(colander.Mapping(unknown='preserve'),
		title="Plugin Parameters",
		description="Parameters for this particular plugin",
		missing={},
		default={})

class HealthPluginsSchema(colander.SequenceSchema):
	health = HealthPluginSchema()

	@staticmethod
	def default():
		return {'plugins': []}

class HealthGroupSchema(StrictAboutExtraKeysColanderMappingSchema):
	name = colander.SchemaNode(colander.String(),
		title="Symbolic name",
		description="The symbolic name for this health check group.")
	title = colander.SchemaNode(colander.String(),
		title="Friendly name",
		description="The friendly name for this health check group.")
	period = colander.SchemaNode(colander.Integer(),
		title="Group recheck period",
		description="How often to run this health check group, in seconds.")
	plugins = HealthPluginsSchema(
		default=HealthPluginsSchema.default(),
		missing=HealthPluginsSchema.default()
	)

class HealthGroupsSchema(colander.SequenceSchema):
	group = HealthGroupSchema()

class HealthGroupsOnlySchema(StrictAboutExtraKeysColanderMappingSchema):
	groups = HealthGroupsSchema()

class HealthCombinedSchema(StrictAboutExtraKeysColanderMappingSchema):
	groups = HealthGroupsSchema(
		missing=[],
		default=[]
	)
	enabled = colander.SchemaNode(colander.Boolean(),
		title="Run health checks",
		description="If true, run health checks on this node. If you have multiple pacemakers, you will only want to run this on one node. However, you could configure two pacemakers to perform different health checks.",
		missing=True,
		default=True)
	use_default_checks = colander.SchemaNode(colander.Boolean(),
		title="Include default health checks",
		description="Include default health checks. These are added to any groups. If you do enable this, you should not define a 'default' group.",
		missing=True,
		default=True)

	@staticmethod
	def default():
		return {'enabled': True, 'groups': [], 'use_default_checks': True}

class PacemakerSchema(StrictAboutExtraKeysColanderMappingSchema):
	enabled = colander.SchemaNode(colander.Boolean(),
		title="Pacemaker enabled",
		description="Pacemaker is enabled for this node",
		missing=False,
		default=False)

	require_ssl = colander.SchemaNode(
		colander.Boolean(),
		title="Require SSL",
		description="If true, require SSL for access to the console and API.",
		missing=False,
		default=False
	)

	dsn = colander.SchemaNode(colander.String(),
		title="Database DSN",
		description="Database connection details for this pacemaker, in SQLAlchemy format")

	database_options = colander.SchemaNode(
		colander.Mapping(unknown='preserve'),
		title="Additional Database options",
		description="Additional Database options, passed as keyword arguments to engine_create. See http://docs.sqlalchemy.org/en/rel_0_7/core/engines.html#engine-creation-api for the available options. This can be used to tweak database connection details.",
		missing={},
{'fraction_non_alphanumeric': 0.08784176847004072, 'fraction_numerical': 0.008435136707388016, 'mean_word_length': 6.531763417305586, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '970695', 'n_tokens_mistral': 3967, 'n_tokens_neox': 3675, 'n_words': 1123}