def call_error(config, module, exception, log): logger = hypernode.log.getLogger(__name__) common.check_vars(config, ["callback_url", "app_name"]) hash = hash_deployment_config(config) logger.info("Signaling back to control that module %s failed while applying the nodeconfig" % module.__name__) logger.debug("POSTing to %s" % config["callback_url"]) headers = {'User-Agent': 'nodeconfig/callback for %s' % config["app_name"]} r = requests.post(config["callback_url"], data={"applied_hash": hash, "error": exception, "module": module.__name__, "log": "\n".join(log) }, headers=headers, verify=True) if r.status_code == 200: logger.debug("Callback was received") else: logger.error("Callback was unsuccessful: %s" % r.status_code) logger.error(r.text) raise CallbackException("Error callback failed with HTTP status code %d: %s" % (r.status_code, r.text))
def apply_config(config): logger.debug("Checking configuration for php_options") common.check_vars(config, ["php_options"]) options = None extensions = {} logger.debug("Checking configuration for php_options.options") # Options is dict, and template determines which keys are valid if "options" in config["php_options"]: logger.debug("php_options.options found") options = config["php_options"]["options"] logger.debug("Checking configuration for php_options.extensions") # Extensions is a list. We'll map it to a dict here, to give it to the template if "extensions" in config["php_options"]: logger.debug("php_options.extensions found") for item in config["php_options"]["extensions"]: logger.debug("Enabling extension '%s'" % item) extensions[item] = True logger.info("Writing /etc/php5/mods-available/hypernode.ini") common.write_file("/etc/php5/mods-available/hypernode.ini", common.fill_template("/etc/hypernode/templates/20.phpini", {"options": options, "extensions": extensions})) logger.info("Enabling hypernode.ini using php5enmod") subprocess.call(["php5enmod", "hypernode/99"]) logger.info("Restarting PHP5-FPM daemon") subprocess.call(["service", "php5-fpm", "restart"])
def apply_config(config): # There are three cases that we might expect: # 1. All ssl-fields are present, filled out and represent a certificate # that passes the openssl-check. # 2. None of the ssl-fields are present. # 3. Other cases: not all of the ssl-fields are present, or they don't pass # the openssl-check # # These cases yield the following actions # 1. The certificate is written to disk, apache is restarted # 2. Any certificate present on disk will be removed, the apache- # configuration for the SSL-vhost will be removed, and apache will be # restarted # 3. This is an exception, and means that there is an error in the # configuration # We always need an app_name. Not found => exception common.check_vars(config, ["app_name"]) if "ssl_common_name" in config and "ssl_body" in config and "ssl_certificate" in config and "ssl_key_chain" in config: logger.debug("Configuring SSL") logger.debug("Verifying SSL key and certificate") verify_ssl(config["ssl_certificate"], config["ssl_body"], config["ssl_key_chain"]) template_vars = {'app_name': config['app_name'], 'servername': config['ssl_common_name'], 'crtpath': CRTPATH} if 'ssl_key_chain' in config and config['ssl_key_chain']: logger.info("Writing %s", CAPATH) common.write_file(CAPATH, config["ssl_key_chain"], umask=0077) template_vars['capath'] = CAPATH logger.info("Writing %s", CRTPATH) common.write_file(CRTPATH, "%s\n\n%s" % (config["ssl_certificate"], config["ssl_body"]), umask=0077) logger.info("Writing /etc/apache2/sites-enabled/default-ssl") common.write_file("/etc/apache2/sites-enabled/default-ssl", common.fill_template("/etc/hypernode/templates/05.ssl.default-ssl-vhost", vars=template_vars)) logger.info("Restarting apache2") subprocess.call(["service", "apache2", "restart"]) return elif "ssl_common_name" not in config and "ssl_body" not in config and "ssl_certificate" not in config and "ssl_key_chain" not in config: logger.debug("Disabling SSL") disable_ssl() return else: raise RuntimeError("Incomplete SSL parameters in configuration")
def apply_config(config): common.check_vars(config, ["public_keys"]) contents = PREAMBLE + "".join([("%s\n\n" % key) for key in config["public_keys"]]) # do not handle any errors here if not os.path.isdir(DOTSSH): logging.info("Creating .ssh directory") os.mkdir(DOTSSH, 0755) logging.info("Setting .ssh dir owner") os.chown(DOTSSH, 1000, 1000) logging.info("Write authorized_keys file") common.write_file(AUTHKEYS, contents, umask=0022)
def call_success(config): logger = hypernode.log.getLogger(__name__) common.check_vars(config, ["callback_url", "app_name"]) hash = hash_deployment_config(config) logger.info("Signaling back to control that we successfully applied nodeconfig with hash %s" % hash) logger.debug("POSTing to %s" % config["callback_url"]) headers = {'User-Agent': 'nodeconfig/callback for %s' % config["app_name"]} r = requests.post(config["callback_url"], data={"applied_hash": hash}, headers=headers, verify=True) if r.status_code == 200: logger.info("Callback was received") else: logger.error("Callback was unsuccessful: %s" % r.status_code) logger.error(r.text) raise Exception("Success callback failed with HTTP status code %d: %s" % (r.status_code, r.text))
def apply_config(config): logger.debug("Checking configuration for app_name and region") common.check_vars(config, ["app_name", "region"]) logger.info("Calling /usr/local/bin/cfn-init") subprocess.call( [ "/usr/local/bin/cfn-init", "-s", config["app_name"], "-r", "LaunchConfig", "--credential-file", "/etc/cfn/cfn-credentials", "--region", config["region"], ] )
def apply_config(config): common.check_vars(config, ["hostnames", "app_name"]) logger.debug("Setting hostname to %s" % config["app_name"]) logger.info("Writing /etc/hostname") common.write_file("/etc/hostname", config["app_name"]) logger.info("Writing /etc/hosts from template /etc/hypernode/templates/03.hostname.hosts") common.write_file("/etc/hosts", common.fill_template("/etc/hypernode/templates/03.hostname.hosts", {"hostnames": config["hostnames"], "app_name": config["app_name"]})) logger.info("Calling `hostname`") subprocess.call(["hostname", config["app_name"]]) logger.info("Restarting rsyslog") subprocess.call(["service", "rsyslog", "restart"])
def test_check_vars_raises_returns_nothing_if_all_keys_found(self): check_vars({}, []) check_vars({"a": "b"}, ["a"]) check_vars({"a": "b", "b": "c"}, ["a", "b"]) check_vars({"a": None}, ["a"])