|
Packit Service |
a04d08 |
# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Avishai Ish-Shalom <avishai@fewbytes.com>
|
|
Packit Service |
a04d08 |
# Author: Mike Moulton <mike@meltmedia.com>
|
|
Packit Service |
a04d08 |
# Author: Juerg Haefliger <juerg.haefliger@hp.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
751c4a |
"""Chef: module that configures, starts and installs chef."""
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import itertools
|
|
Packit Service |
a04d08 |
import json
|
|
Packit Service |
a04d08 |
import os
|
|
Packit Service |
751c4a |
from textwrap import dedent
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
751c4a |
from cloudinit import subp
|
|
Packit Service |
751c4a |
from cloudinit.config.schema import (
|
|
Packit Service |
751c4a |
get_schema_doc, validate_cloudconfig_schema)
|
|
Packit Service |
a04d08 |
from cloudinit import templater
|
|
Packit Service |
751c4a |
from cloudinit import temp_utils
|
|
Packit Service |
a04d08 |
from cloudinit import url_helper
|
|
Packit Service |
a04d08 |
from cloudinit import util
|
|
Packit Service |
751c4a |
from cloudinit.settings import PER_ALWAYS
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
RUBY_VERSION_DEFAULT = "1.8"
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
CHEF_DIRS = tuple([
|
|
Packit Service |
a04d08 |
'/etc/chef',
|
|
Packit Service |
a04d08 |
'/var/log/chef',
|
|
Packit Service |
a04d08 |
'/var/lib/chef',
|
|
Packit Service |
a04d08 |
'/var/cache/chef',
|
|
Packit Service |
a04d08 |
'/var/backups/chef',
|
|
Packit Service |
11b429 |
'/var/run/chef',
|
|
Packit Service |
a04d08 |
])
|
|
Packit Service |
a04d08 |
REQUIRED_CHEF_DIRS = tuple([
|
|
Packit Service |
a04d08 |
'/etc/chef',
|
|
Packit Service |
a04d08 |
])
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Used if fetching chef from a omnibus style package
|
|
Packit Service |
a04d08 |
OMNIBUS_URL = "https://www.chef.io/chef/install.sh"
|
|
Packit Service |
a04d08 |
OMNIBUS_URL_RETRIES = 5
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
CHEF_VALIDATION_PEM_PATH = '/etc/chef/validation.pem'
|
|
Packit Service |
751c4a |
CHEF_ENCRYPTED_DATA_BAG_PATH = '/etc/chef/encrypted_data_bag_secret'
|
|
Packit Service |
751c4a |
CHEF_ENVIRONMENT = '_default'
|
|
Packit Service |
a04d08 |
CHEF_FB_PATH = '/etc/chef/firstboot.json'
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_DEFAULTS = {
|
|
Packit Service |
a04d08 |
# These are ruby symbols...
|
|
Packit Service |
a04d08 |
'ssl_verify_mode': ':verify_none',
|
|
Packit Service |
a04d08 |
'log_level': ':info',
|
|
Packit Service |
a04d08 |
# These are not symbols...
|
|
Packit Service |
a04d08 |
'log_location': '/var/log/chef/client.log',
|
|
Packit Service |
a04d08 |
'validation_key': CHEF_VALIDATION_PEM_PATH,
|
|
Packit Service |
a04d08 |
'validation_cert': None,
|
|
Packit Service |
751c4a |
'client_key': '/etc/chef/client.pem',
|
|
Packit Service |
a04d08 |
'json_attribs': CHEF_FB_PATH,
|
|
Packit Service |
751c4a |
'file_cache_path': '/var/cache/chef',
|
|
Packit Service |
751c4a |
'file_backup_path': '/var/backups/chef',
|
|
Packit Service |
751c4a |
'pid_file': '/var/run/chef/client.pid',
|
|
Packit Service |
a04d08 |
'show_time': True,
|
|
Packit Service |
a04d08 |
'encrypted_data_bag_secret': None,
|
|
Packit Service |
a04d08 |
}
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_BOOL_KEYS = frozenset(['show_time'])
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_PATH_KEYS = frozenset([
|
|
Packit Service |
a04d08 |
'log_location',
|
|
Packit Service |
a04d08 |
'validation_key',
|
|
Packit Service |
a04d08 |
'client_key',
|
|
Packit Service |
a04d08 |
'file_cache_path',
|
|
Packit Service |
a04d08 |
'json_attribs',
|
|
Packit Service |
a04d08 |
'pid_file',
|
|
Packit Service |
a04d08 |
'encrypted_data_bag_secret',
|
|
Packit Service |
751c4a |
'chef_license',
|
|
Packit Service |
a04d08 |
])
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_KEYS = list(CHEF_RB_TPL_DEFAULTS.keys())
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_KEYS.extend(CHEF_RB_TPL_BOOL_KEYS)
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_KEYS.extend(CHEF_RB_TPL_PATH_KEYS)
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_KEYS.extend([
|
|
Packit Service |
a04d08 |
'server_url',
|
|
Packit Service |
a04d08 |
'node_name',
|
|
Packit Service |
a04d08 |
'environment',
|
|
Packit Service |
a04d08 |
'validation_name',
|
|
Packit Service |
a04d08 |
])
|
|
Packit Service |
a04d08 |
CHEF_RB_TPL_KEYS = frozenset(CHEF_RB_TPL_KEYS)
|
|
Packit Service |
a04d08 |
CHEF_RB_PATH = '/etc/chef/client.rb'
|
|
Packit Service |
a04d08 |
CHEF_EXEC_PATH = '/usr/bin/chef-client'
|
|
Packit Service |
a04d08 |
CHEF_EXEC_DEF_ARGS = tuple(['-d', '-i', '1800', '-s', '20'])
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
751c4a |
frequency = PER_ALWAYS
|
|
Packit Service |
751c4a |
distros = ["all"]
|
|
Packit Service |
751c4a |
schema = {
|
|
Packit Service |
751c4a |
'id': 'cc_chef',
|
|
Packit Service |
751c4a |
'name': 'Chef',
|
|
Packit Service |
751c4a |
'title': 'module that configures, starts and installs chef',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
This module enables chef to be installed (from packages,
|
|
Packit Service |
751c4a |
gems, or from omnibus). Before this occurs, chef configuration is
|
|
Packit Service |
751c4a |
written to disk (validation.pem, client.pem, firstboot.json,
|
|
Packit Service |
751c4a |
client.rb), and required directories are created (/etc/chef and
|
|
Packit Service |
751c4a |
/var/log/chef and so-on). If configured, chef will be
|
|
Packit Service |
751c4a |
installed and started in either daemon or non-daemon mode.
|
|
Packit Service |
751c4a |
If run in non-daemon mode, post run actions are executed to do
|
|
Packit Service |
751c4a |
finishing activities such as removing validation.pem."""),
|
|
Packit Service |
751c4a |
'distros': distros,
|
|
Packit Service |
751c4a |
'examples': [dedent("""
|
|
Packit Service |
751c4a |
chef:
|
|
Packit Service |
751c4a |
directories:
|
|
Packit Service |
751c4a |
- /etc/chef
|
|
Packit Service |
751c4a |
- /var/log/chef
|
|
Packit Service |
751c4a |
validation_cert: system
|
|
Packit Service |
751c4a |
install_type: omnibus
|
|
Packit Service |
751c4a |
initial_attributes:
|
|
Packit Service |
751c4a |
apache:
|
|
Packit Service |
751c4a |
prefork:
|
|
Packit Service |
751c4a |
maxclients: 100
|
|
Packit Service |
751c4a |
keepalive: off
|
|
Packit Service |
751c4a |
run_list:
|
|
Packit Service |
751c4a |
- recipe[apache2]
|
|
Packit Service |
751c4a |
- role[db]
|
|
Packit Service |
751c4a |
encrypted_data_bag_secret: /etc/chef/encrypted_data_bag_secret
|
|
Packit Service |
751c4a |
environment: _default
|
|
Packit Service |
751c4a |
log_level: :auto
|
|
Packit Service |
751c4a |
omnibus_url_retries: 2
|
|
Packit Service |
751c4a |
server_url: https://chef.yourorg.com:4000
|
|
Packit Service |
751c4a |
ssl_verify_mode: :verify_peer
|
|
Packit Service |
751c4a |
validation_name: yourorg-validator""")],
|
|
Packit Service |
751c4a |
'frequency': frequency,
|
|
Packit Service |
751c4a |
'type': 'object',
|
|
Packit Service |
751c4a |
'properties': {
|
|
Packit Service |
751c4a |
'chef': {
|
|
Packit Service |
751c4a |
'type': 'object',
|
|
Packit Service |
751c4a |
'additionalProperties': False,
|
|
Packit Service |
751c4a |
'properties': {
|
|
Packit Service |
751c4a |
'directories': {
|
|
Packit Service |
751c4a |
'type': 'array',
|
|
Packit Service |
751c4a |
'items': {
|
|
Packit Service |
751c4a |
'type': 'string'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'uniqueItems': True,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Create the necessary directories for chef to run. By
|
|
Packit Service |
751c4a |
default, it creates the following directories:
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
{chef_dirs}""").format(
|
|
Packit Service |
751c4a |
chef_dirs="\n".join(
|
|
Packit Service |
751c4a |
[" - ``{}``".format(d) for d in CHEF_DIRS]
|
|
Packit Service |
751c4a |
)
|
|
Packit Service |
751c4a |
)
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'validation_cert': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Optional string to be written to file validation_key.
|
|
Packit Service |
751c4a |
Special value ``system`` means set use existing file.
|
|
Packit Service |
751c4a |
""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'validation_key': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_VALIDATION_PEM_PATH,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Optional path for validation_cert. default to
|
|
Packit Service |
751c4a |
``{}``.""".format(CHEF_VALIDATION_PEM_PATH))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'firstboot_path': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_FB_PATH,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Path to write run_list and initial_attributes keys that
|
|
Packit Service |
751c4a |
should also be present in this configuration, defaults
|
|
Packit Service |
751c4a |
to ``{}``.""".format(CHEF_FB_PATH))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'exec': {
|
|
Packit Service |
751c4a |
'type': 'boolean',
|
|
Packit Service |
751c4a |
'default': False,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
define if we should run or not run chef (defaults to
|
|
Packit Service |
751c4a |
false, unless a gem installed is requested where this
|
|
Packit Service |
751c4a |
will then default to true).""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'client_key': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['client_key'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Optional path for client_cert. default to
|
|
Packit Service |
751c4a |
``{}``.""".format(CHEF_RB_TPL_DEFAULTS['client_key']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'encrypted_data_bag_secret': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': None,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies the location of the secret key used by chef
|
|
Packit Service |
751c4a |
to encrypt data items. By default, this path is set
|
|
Packit Service |
751c4a |
to None, meaning that chef will have to look at the
|
|
Packit Service |
751c4a |
path ``{}`` for it.
|
|
Packit Service |
751c4a |
""".format(CHEF_ENCRYPTED_DATA_BAG_PATH))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'environment': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_ENVIRONMENT,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies which environment chef will use. By default,
|
|
Packit Service |
751c4a |
it will use the ``{}`` configuration.
|
|
Packit Service |
751c4a |
""".format(CHEF_ENVIRONMENT))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'file_backup_path': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['file_backup_path'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies the location in which backup files are
|
|
Packit Service |
751c4a |
stored. By default, it uses the
|
|
Packit Service |
751c4a |
``{}`` location.""".format(
|
|
Packit Service |
751c4a |
CHEF_RB_TPL_DEFAULTS['file_backup_path']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'file_cache_path': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['file_cache_path'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies the location in which chef cache files will
|
|
Packit Service |
751c4a |
be saved. By default, it uses the ``{}``
|
|
Packit Service |
751c4a |
location.""".format(
|
|
Packit Service |
751c4a |
CHEF_RB_TPL_DEFAULTS['file_cache_path']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'json_attribs': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_FB_PATH,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies the location in which some chef json data is
|
|
Packit Service |
751c4a |
stored. By default, it uses the
|
|
Packit Service |
751c4a |
``{}`` location.""".format(CHEF_FB_PATH))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'log_level': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['log_level'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Defines the level of logging to be stored in the log
|
|
Packit Service |
751c4a |
file. By default this value is set to ``{}``.
|
|
Packit Service |
751c4a |
""".format(CHEF_RB_TPL_DEFAULTS['log_level']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'log_location': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['log_location'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specifies the location of the chef lof file. By
|
|
Packit Service |
751c4a |
default, the location is specified at
|
|
Packit Service |
751c4a |
``{}``.""".format(
|
|
Packit Service |
751c4a |
CHEF_RB_TPL_DEFAULTS['log_location']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'node_name': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
The name of the node to run. By default, we will
|
|
Packit Service |
751c4a |
use th instance id as the node name.""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'omnibus_url': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': OMNIBUS_URL,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Omnibus URL if chef should be installed through
|
|
Packit Service |
751c4a |
Omnibus. By default, it uses the
|
|
Packit Service |
751c4a |
``{}``.""".format(OMNIBUS_URL))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'omnibus_url_retries': {
|
|
Packit Service |
751c4a |
'type': 'integer',
|
|
Packit Service |
751c4a |
'default': OMNIBUS_URL_RETRIES,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
The number of retries that will be attempted to reach
|
|
Packit Service |
751c4a |
the Omnibus URL""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'omnibus_version': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Optional version string to require for omnibus
|
|
Packit Service |
751c4a |
install.""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'pid_file': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['pid_file'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
The location in which a process identification
|
|
Packit Service |
751c4a |
number (pid) is saved. By default, it saves
|
|
Packit Service |
751c4a |
in the ``{}`` location.""".format(
|
|
Packit Service |
751c4a |
CHEF_RB_TPL_DEFAULTS['pid_file']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'server_url': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': 'The URL for the chef server'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'show_time': {
|
|
Packit Service |
751c4a |
'type': 'boolean',
|
|
Packit Service |
751c4a |
'default': True,
|
|
Packit Service |
751c4a |
'description': 'Show time in chef logs'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'ssl_verify_mode': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': CHEF_RB_TPL_DEFAULTS['ssl_verify_mode'],
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Set the verify mode for HTTPS requests. We can have
|
|
Packit Service |
751c4a |
two possible values for this parameter:
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
- ``:verify_none``: No validation of SSL \
|
|
Packit Service |
751c4a |
certificates.
|
|
Packit Service |
751c4a |
- ``:verify_peer``: Validate all SSL certificates.
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
By default, the parameter is set as ``{}``.
|
|
Packit Service |
751c4a |
""".format(CHEF_RB_TPL_DEFAULTS['ssl_verify_mode']))
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'validation_name': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
The name of the chef-validator key that Chef Infra
|
|
Packit Service |
751c4a |
Client uses to access the Chef Infra Server during
|
|
Packit Service |
751c4a |
the initial Chef Infra Client run.""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'force_install': {
|
|
Packit Service |
751c4a |
'type': 'boolean',
|
|
Packit Service |
751c4a |
'default': False,
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
If set to ``True``, forces chef installation, even
|
|
Packit Service |
751c4a |
if it is already installed.""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'initial_attributes': {
|
|
Packit Service |
751c4a |
'type': 'object',
|
|
Packit Service |
751c4a |
'items': {
|
|
Packit Service |
751c4a |
'type': 'string'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
Specify a list of initial attributes used by the
|
|
Packit Service |
751c4a |
cookbooks.""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'install_type': {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'default': 'packages',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
The type of installation for chef. It can be one of
|
|
Packit Service |
751c4a |
the following values:
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
- ``packages``
|
|
Packit Service |
751c4a |
- ``gems``
|
|
Packit Service |
751c4a |
- ``omnibus``""")
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'run_list': {
|
|
Packit Service |
751c4a |
'type': 'array',
|
|
Packit Service |
751c4a |
'items': {
|
|
Packit Service |
751c4a |
'type': 'string'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
'description': 'A run list for a first boot json.'
|
|
Packit Service |
751c4a |
},
|
|
Packit Service |
751c4a |
"chef_license": {
|
|
Packit Service |
751c4a |
'type': 'string',
|
|
Packit Service |
751c4a |
'description': dedent("""\
|
|
Packit Service |
751c4a |
string that indicates if user accepts or not license
|
|
Packit Service |
751c4a |
related to some of chef products""")
|
|
Packit Service |
751c4a |
}
|
|
Packit Service |
751c4a |
}
|
|
Packit Service |
751c4a |
}
|
|
Packit Service |
751c4a |
}
|
|
Packit Service |
751c4a |
}
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
__doc__ = get_schema_doc(schema)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def post_run_chef(chef_cfg, log):
|
|
Packit Service |
a04d08 |
delete_pem = util.get_cfg_option_bool(chef_cfg,
|
|
Packit Service |
a04d08 |
'delete_validation_post_exec',
|
|
Packit Service |
a04d08 |
default=False)
|
|
Packit Service |
a04d08 |
if delete_pem and os.path.isfile(CHEF_VALIDATION_PEM_PATH):
|
|
Packit Service |
a04d08 |
os.unlink(CHEF_VALIDATION_PEM_PATH)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def get_template_params(iid, chef_cfg, log):
|
|
Packit Service |
a04d08 |
params = CHEF_RB_TPL_DEFAULTS.copy()
|
|
Packit Service |
a04d08 |
# Allow users to overwrite any of the keys they want (if they so choose),
|
|
Packit Service |
a04d08 |
# when a value is None, then the value will be set to None and no boolean
|
|
Packit Service |
a04d08 |
# or string version will be populated...
|
|
Packit Service |
a04d08 |
for (k, v) in chef_cfg.items():
|
|
Packit Service |
a04d08 |
if k not in CHEF_RB_TPL_KEYS:
|
|
Packit Service |
a04d08 |
log.debug("Skipping unknown chef template key '%s'", k)
|
|
Packit Service |
a04d08 |
continue
|
|
Packit Service |
a04d08 |
if v is None:
|
|
Packit Service |
a04d08 |
params[k] = None
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
# This will make the value a boolean or string...
|
|
Packit Service |
a04d08 |
if k in CHEF_RB_TPL_BOOL_KEYS:
|
|
Packit Service |
a04d08 |
params[k] = util.get_cfg_option_bool(chef_cfg, k)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
params[k] = util.get_cfg_option_str(chef_cfg, k)
|
|
Packit Service |
a04d08 |
# These ones are overwritten to be exact values...
|
|
Packit Service |
a04d08 |
params.update({
|
|
Packit Service |
a04d08 |
'generated_by': util.make_header(),
|
|
Packit Service |
a04d08 |
'node_name': util.get_cfg_option_str(chef_cfg, 'node_name',
|
|
Packit Service |
a04d08 |
default=iid),
|
|
Packit Service |
a04d08 |
'environment': util.get_cfg_option_str(chef_cfg, 'environment',
|
|
Packit Service |
a04d08 |
default='_default'),
|
|
Packit Service |
a04d08 |
# These two are mandatory...
|
|
Packit Service |
a04d08 |
'server_url': chef_cfg['server_url'],
|
|
Packit Service |
a04d08 |
'validation_name': chef_cfg['validation_name'],
|
|
Packit Service |
a04d08 |
})
|
|
Packit Service |
a04d08 |
return params
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def handle(name, cfg, cloud, log, _args):
|
|
Packit Service |
a04d08 |
"""Handler method activated by cloud-init."""
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# If there isn't a chef key in the configuration don't do anything
|
|
Packit Service |
a04d08 |
if 'chef' not in cfg:
|
|
Packit Service |
a04d08 |
log.debug(("Skipping module named %s,"
|
|
Packit Service |
a04d08 |
" no 'chef' key in configuration"), name)
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
validate_cloudconfig_schema(cfg, schema)
|
|
Packit Service |
a04d08 |
chef_cfg = cfg['chef']
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Ensure the chef directories we use exist
|
|
Packit Service |
a04d08 |
chef_dirs = util.get_cfg_option_list(chef_cfg, 'directories')
|
|
Packit Service |
a04d08 |
if not chef_dirs:
|
|
Packit Service |
a04d08 |
chef_dirs = list(CHEF_DIRS)
|
|
Packit Service |
a04d08 |
for d in itertools.chain(chef_dirs, REQUIRED_CHEF_DIRS):
|
|
Packit Service |
a04d08 |
util.ensure_dir(d)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
vkey_path = chef_cfg.get('validation_key', CHEF_VALIDATION_PEM_PATH)
|
|
Packit Service |
a04d08 |
vcert = chef_cfg.get('validation_cert')
|
|
Packit Service |
a04d08 |
# special value 'system' means do not overwrite the file
|
|
Packit Service |
a04d08 |
# but still render the template to contain 'validation_key'
|
|
Packit Service |
a04d08 |
if vcert:
|
|
Packit Service |
a04d08 |
if vcert != "system":
|
|
Packit Service |
a04d08 |
util.write_file(vkey_path, vcert)
|
|
Packit Service |
a04d08 |
elif not os.path.isfile(vkey_path):
|
|
Packit Service |
a04d08 |
log.warning("chef validation_cert provided as 'system', but "
|
|
Packit Service |
a04d08 |
"validation_key path '%s' does not exist.",
|
|
Packit Service |
a04d08 |
vkey_path)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Create the chef config from template
|
|
Packit Service |
a04d08 |
template_fn = cloud.get_template_filename('chef_client.rb')
|
|
Packit Service |
a04d08 |
if template_fn:
|
|
Packit Service |
a04d08 |
iid = str(cloud.datasource.get_instance_id())
|
|
Packit Service |
a04d08 |
params = get_template_params(iid, chef_cfg, log)
|
|
Packit Service |
a04d08 |
# Do a best effort attempt to ensure that the template values that
|
|
Packit Service |
751c4a |
# are associated with paths have their parent directory created
|
|
Packit Service |
a04d08 |
# before they are used by the chef-client itself.
|
|
Packit Service |
a04d08 |
param_paths = set()
|
|
Packit Service |
a04d08 |
for (k, v) in params.items():
|
|
Packit Service |
a04d08 |
if k in CHEF_RB_TPL_PATH_KEYS and v:
|
|
Packit Service |
a04d08 |
param_paths.add(os.path.dirname(v))
|
|
Packit Service |
a04d08 |
util.ensure_dirs(param_paths)
|
|
Packit Service |
a04d08 |
templater.render_to_file(template_fn, CHEF_RB_PATH, params)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
log.warning("No template found, not rendering to %s",
|
|
Packit Service |
a04d08 |
CHEF_RB_PATH)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Set the firstboot json
|
|
Packit Service |
a04d08 |
fb_filename = util.get_cfg_option_str(chef_cfg, 'firstboot_path',
|
|
Packit Service |
a04d08 |
default=CHEF_FB_PATH)
|
|
Packit Service |
a04d08 |
if not fb_filename:
|
|
Packit Service |
a04d08 |
log.info("First boot path empty, not writing first boot json file")
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
initial_json = {}
|
|
Packit Service |
a04d08 |
if 'run_list' in chef_cfg:
|
|
Packit Service |
a04d08 |
initial_json['run_list'] = chef_cfg['run_list']
|
|
Packit Service |
a04d08 |
if 'initial_attributes' in chef_cfg:
|
|
Packit Service |
a04d08 |
initial_attributes = chef_cfg['initial_attributes']
|
|
Packit Service |
a04d08 |
for k in list(initial_attributes.keys()):
|
|
Packit Service |
a04d08 |
initial_json[k] = initial_attributes[k]
|
|
Packit Service |
a04d08 |
util.write_file(fb_filename, json.dumps(initial_json))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# Try to install chef, if its not already installed...
|
|
Packit Service |
a04d08 |
force_install = util.get_cfg_option_bool(chef_cfg,
|
|
Packit Service |
a04d08 |
'force_install', default=False)
|
|
Packit Service |
751c4a |
installed = subp.is_exe(CHEF_EXEC_PATH)
|
|
Packit Service |
751c4a |
if not installed or force_install:
|
|
Packit Service |
a04d08 |
run = install_chef(cloud, chef_cfg, log)
|
|
Packit Service |
751c4a |
elif installed:
|
|
Packit Service |
a04d08 |
run = util.get_cfg_option_bool(chef_cfg, 'exec', default=False)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
run = False
|
|
Packit Service |
a04d08 |
if run:
|
|
Packit Service |
a04d08 |
run_chef(chef_cfg, log)
|
|
Packit Service |
a04d08 |
post_run_chef(chef_cfg, log)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def run_chef(chef_cfg, log):
|
|
Packit Service |
a04d08 |
log.debug('Running chef-client')
|
|
Packit Service |
a04d08 |
cmd = [CHEF_EXEC_PATH]
|
|
Packit Service |
a04d08 |
if 'exec_arguments' in chef_cfg:
|
|
Packit Service |
a04d08 |
cmd_args = chef_cfg['exec_arguments']
|
|
Packit Service |
a04d08 |
if isinstance(cmd_args, (list, tuple)):
|
|
Packit Service |
a04d08 |
cmd.extend(cmd_args)
|
|
Packit Service |
751c4a |
elif isinstance(cmd_args, str):
|
|
Packit Service |
a04d08 |
cmd.append(cmd_args)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
log.warning("Unknown type %s provided for chef"
|
|
Packit Service |
a04d08 |
" 'exec_arguments' expected list, tuple,"
|
|
Packit Service |
a04d08 |
" or string", type(cmd_args))
|
|
Packit Service |
a04d08 |
cmd.extend(CHEF_EXEC_DEF_ARGS)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
cmd.extend(CHEF_EXEC_DEF_ARGS)
|
|
Packit Service |
751c4a |
subp.subp(cmd, capture=False)
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
def subp_blob_in_tempfile(blob, *args, **kwargs):
|
|
Packit Service |
751c4a |
"""Write blob to a tempfile, and call subp with args, kwargs. Then cleanup.
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
'basename' as a kwarg allows providing the basename for the file.
|
|
Packit Service |
751c4a |
The 'args' argument to subp will be updated with the full path to the
|
|
Packit Service |
751c4a |
filename as the first argument.
|
|
Packit Service |
751c4a |
"""
|
|
Packit Service |
751c4a |
basename = kwargs.pop('basename', "subp_blob")
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
if len(args) == 0 and 'args' not in kwargs:
|
|
Packit Service |
751c4a |
args = [tuple()]
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
# Use tmpdir over tmpfile to avoid 'text file busy' on execute
|
|
Packit Service |
751c4a |
with temp_utils.tempdir(needs_exe=True) as tmpd:
|
|
Packit Service |
751c4a |
tmpf = os.path.join(tmpd, basename)
|
|
Packit Service |
751c4a |
if 'args' in kwargs:
|
|
Packit Service |
751c4a |
kwargs['args'] = [tmpf] + list(kwargs['args'])
|
|
Packit Service |
751c4a |
else:
|
|
Packit Service |
751c4a |
args = list(args)
|
|
Packit Service |
751c4a |
args[0] = [tmpf] + args[0]
|
|
Packit Service |
751c4a |
|
|
Packit Service |
751c4a |
util.write_file(tmpf, blob, mode=0o700)
|
|
Packit Service |
751c4a |
return subp.subp(*args, **kwargs)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def install_chef_from_omnibus(url=None, retries=None, omnibus_version=None):
|
|
Packit Service |
a04d08 |
"""Install an omnibus unified package from url.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
@param url: URL where blob of chef content may be downloaded. Defaults to
|
|
Packit Service |
a04d08 |
OMNIBUS_URL.
|
|
Packit Service |
a04d08 |
@param retries: Number of retries to perform when attempting to read url.
|
|
Packit Service |
a04d08 |
Defaults to OMNIBUS_URL_RETRIES
|
|
Packit Service |
a04d08 |
@param omnibus_version: Optional version string to require for omnibus
|
|
Packit Service |
a04d08 |
install.
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
if url is None:
|
|
Packit Service |
a04d08 |
url = OMNIBUS_URL
|
|
Packit Service |
a04d08 |
if retries is None:
|
|
Packit Service |
a04d08 |
retries = OMNIBUS_URL_RETRIES
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
if omnibus_version is None:
|
|
Packit Service |
a04d08 |
args = []
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
args = ['-v', omnibus_version]
|
|
Packit Service |
a04d08 |
content = url_helper.readurl(url=url, retries=retries).contents
|
|
Packit Service |
751c4a |
return subp_blob_in_tempfile(
|
|
Packit Service |
a04d08 |
blob=content, args=args,
|
|
Packit Service |
a04d08 |
basename='chef-omnibus-install', capture=False)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def install_chef(cloud, chef_cfg, log):
|
|
Packit Service |
a04d08 |
# If chef is not installed, we install chef based on 'install_type'
|
|
Packit Service |
a04d08 |
install_type = util.get_cfg_option_str(chef_cfg, 'install_type',
|
|
Packit Service |
a04d08 |
'packages')
|
|
Packit Service |
a04d08 |
run = util.get_cfg_option_bool(chef_cfg, 'exec', default=False)
|
|
Packit Service |
a04d08 |
if install_type == "gems":
|
|
Packit Service |
a04d08 |
# This will install and run the chef-client from gems
|
|
Packit Service |
a04d08 |
chef_version = util.get_cfg_option_str(chef_cfg, 'version', None)
|
|
Packit Service |
a04d08 |
ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version',
|
|
Packit Service |
a04d08 |
RUBY_VERSION_DEFAULT)
|
|
Packit Service |
a04d08 |
install_chef_from_gems(ruby_version, chef_version, cloud.distro)
|
|
Packit Service |
a04d08 |
# Retain backwards compat, by preferring True instead of False
|
|
Packit Service |
a04d08 |
# when not provided/overriden...
|
|
Packit Service |
a04d08 |
run = util.get_cfg_option_bool(chef_cfg, 'exec', default=True)
|
|
Packit Service |
a04d08 |
elif install_type == 'packages':
|
|
Packit Service |
a04d08 |
# This will install and run the chef-client from packages
|
|
Packit Service |
a04d08 |
cloud.distro.install_packages(('chef',))
|
|
Packit Service |
a04d08 |
elif install_type == 'omnibus':
|
|
Packit Service |
a04d08 |
omnibus_version = util.get_cfg_option_str(chef_cfg, "omnibus_version")
|
|
Packit Service |
a04d08 |
install_chef_from_omnibus(
|
|
Packit Service |
a04d08 |
url=util.get_cfg_option_str(chef_cfg, "omnibus_url"),
|
|
Packit Service |
a04d08 |
retries=util.get_cfg_option_int(chef_cfg, "omnibus_url_retries"),
|
|
Packit Service |
a04d08 |
omnibus_version=omnibus_version)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
log.warning("Unknown chef install type '%s'", install_type)
|
|
Packit Service |
a04d08 |
run = False
|
|
Packit Service |
a04d08 |
return run
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def get_ruby_packages(version):
|
|
Packit Service |
a04d08 |
# return a list of packages needed to install ruby at version
|
|
Packit Service |
a04d08 |
pkgs = ['ruby%s' % version, 'ruby%s-dev' % version]
|
|
Packit Service |
a04d08 |
if version == "1.8":
|
|
Packit Service |
a04d08 |
pkgs.extend(('libopenssl-ruby1.8', 'rubygems1.8'))
|
|
Packit Service |
a04d08 |
return pkgs
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def install_chef_from_gems(ruby_version, chef_version, distro):
|
|
Packit Service |
a04d08 |
distro.install_packages(get_ruby_packages(ruby_version))
|
|
Packit Service |
a04d08 |
if not os.path.exists('/usr/bin/gem'):
|
|
Packit Service |
a04d08 |
util.sym_link('/usr/bin/gem%s' % ruby_version, '/usr/bin/gem')
|
|
Packit Service |
a04d08 |
if not os.path.exists('/usr/bin/ruby'):
|
|
Packit Service |
a04d08 |
util.sym_link('/usr/bin/ruby%s' % ruby_version, '/usr/bin/ruby')
|
|
Packit Service |
a04d08 |
if chef_version:
|
|
Packit Service |
751c4a |
subp.subp(['/usr/bin/gem', 'install', 'chef',
|
|
Packit Service |
a04d08 |
'-v %s' % chef_version, '--no-ri',
|
|
Packit Service |
a04d08 |
'--no-rdoc', '--bindir', '/usr/bin', '-q'], capture=False)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
751c4a |
subp.subp(['/usr/bin/gem', 'install', 'chef',
|
|
Packit Service |
a04d08 |
'--no-ri', '--no-rdoc', '--bindir',
|
|
Packit Service |
a04d08 |
'/usr/bin', '-q'], capture=False)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# vi: ts=4 expandtab
|