Beispiel #1
0
def _register_sensor_container_opts(ignore_errors=False):
    logging_opts = [
        cfg.StrOpt(
            "logging",
            default="/etc/st2/logging.sensorcontainer.conf",
            help="location of the logging.conf file",
        )
    ]

    st2cfg.do_register_opts(logging_opts,
                            group="sensorcontainer",
                            ignore_errors=ignore_errors)

    # Partitioning options
    partition_opts = [
        cfg.StrOpt("sensor_node_name",
                   default="sensornode1",
                   help="name of the sensor node."),
        cfg.Opt(
            "partition_provider",
            type=types.Dict(value_type=types.String()),
            default={"name": DEFAULT_PARTITION_LOADER},
            help="Provider of sensor node partition config.",
        ),
    ]

    st2cfg.do_register_opts(partition_opts,
                            group="sensorcontainer",
                            ignore_errors=ignore_errors)

    # Other options
    other_opts = [
        cfg.BoolOpt(
            "single_sensor_mode",
            default=False,
            help=
            "Run in a single sensor mode where parent process exits when a sensor crashes / "
            "dies. This is useful in environments where partitioning, sensor process life "
            "cycle and failover is handled by a 3rd party service such as kubernetes.",
        )
    ]

    st2cfg.do_register_opts(other_opts,
                            group="sensorcontainer",
                            ignore_errors=ignore_errors)

    # CLI options
    cli_opts = [
        cfg.StrOpt(
            "sensor-ref",
            help=
            "Only run sensor with the provided reference. Value is of the form "
            "<pack>.<sensor-name> (e.g. linux.FileWatchSensor).",
        ),
        cfg.BoolOpt(
            "single-sensor-mode",
            default=False,
            help=
            "Run in a single sensor mode where parent process exits when a sensor crashes / "
            "dies. This is useful in environments where partitioning, sensor process life "
            "cycle and failover is handled by a 3rd party service such as kubernetes.",
        ),
    ]

    st2cfg.do_register_cli_opts(cli_opts, ignore_errors=ignore_errors)
Beispiel #2
0
 def test_not_equal_with_non_equal_custom_item_types(self):
     it1 = types.Integer()
     it2 = types.String()
     self.assertFalse(it1 == it2)
     self.assertFalse(types.List(it1) == types.List(it2))
Beispiel #3
0
 def test_dict_of_values_containing_commas(self):
     self.type_instance = types.Dict(types.String(quotes=True))
     self.assertConvertedValue('foo:"bar, baz",bam:quux', {
         'foo': 'bar, baz',
         'bam': 'quux'
     })
Beispiel #4
0
 def test_not_equal_to_other_class(self):
     self.assertFalse(types.Boolean() == types.String())
Beispiel #5
0
 def test_list_of_values_containing_commas(self):
     self.type_instance = types.List(types.String(quotes=True))
     self.assertConvertedValue('foo,"bar, baz",bam',
                               ['foo', 'bar, baz', 'bam'])
Beispiel #6
0
 def test_regex_and_ignore_case(self):
     self.type_instance = types.String(regex=re.compile("^[A-Z]"),
                                       ignore_case=True)
     self.assertConvertedValue("foo", "foo")
Beispiel #7
0
 def test_regex_preserve_flags(self):
     self.type_instance = types.String(regex=re.compile("^[A-Z]", re.I),
                                       ignore_case=False)
     self.assertConvertedValue("foo", "foo")
Beispiel #8
0
             help='Do not rebuild images present in the docker cache'),
 cfg.DictOpt('build-args',
             help='Set docker build time variables'),
 cfg.BoolOpt('keep', default=False,
             help='Keep failed intermediate containers'),
 cfg.BoolOpt('list-dependencies', short='l',
             help='Show image dependencies (filtering supported)'),
 cfg.BoolOpt('list-images',
             help='Show all available images (filtering supported)'),
 cfg.StrOpt('namespace', short='n', default='kolla',
            help='The Docker namespace name'),
 cfg.StrOpt('network_mode', default=None,
            help='The network mode for Docker build. Example: host'),
 cfg.BoolOpt('cache', default=True,
             help='Use the Docker cache when building'),
 cfg.MultiOpt('profile', types.String(), short='p',
              help=('Build a pre-defined set of images, see [profiles]'
                    ' section in config. The default profiles are:'
                    ' {}'.format(', '.join(
                        [opt.name for opt in _PROFILE_OPTS])
                    ))),
 cfg.BoolOpt('push', default=False,
             help='Push images after building'),
 cfg.IntOpt('push-threads', default=1, min=1,
            help=('The number of threads to user while pushing'
                  ' Images. Note: Docker can not handle threading'
                  ' push properly')),
 cfg.IntOpt('retries', short='r', default=3, min=0,
            help='The number of times to retry while building'),
 cfg.MultiOpt('regex', types.String(), positional=True,
              help=('Build only images matching regex and its'
Beispiel #9
0
             help='Keep failed intermediate containers'),
 cfg.BoolOpt('list-dependencies',
             short='l',
             help='Show image dependencies (filtering supported)'),
 cfg.BoolOpt('list-images', help='Show all available images'),
 cfg.StrOpt('namespace',
            short='n',
            default='kolla',
            help='The Docker namespace name'),
 cfg.BoolOpt(
     'cache',
     default=True,
     help='Use the Docker cache when building',
 ),
 cfg.MultiOpt('profile',
              types.String(),
              short='p',
              help=('Build a pre-defined set of images, see [profiles]'
                    ' section in config. The default profiles are:'
                    ' {}'.format(', '.join(
                        [opt.name for opt in _PROFILE_OPTS])))),
 cfg.BoolOpt('push', default=False, help='Push images after building'),
 cfg.IntOpt('push-threads',
            default=1,
            min=1,
            help=('The number of threads to user while pushing'
                  ' Images. Note: Docker can not handle threading'
                  ' push properly.')),
 cfg.IntOpt('retries',
            short='r',
            default=3,
Beispiel #10
0
            "back_window": self.back_window,
            "definition": self.definition,
            "aggregation_methods": self.aggregation_methods,
        }

    @property
    def max_block_size(self):
        # The biggest block size is the coarse grained archive definition
        return sorted(self.definition,
                      key=operator.attrgetter("granularity"))[-1].granularity


OPTS = [
    cfg.ListOpt(
        'default_aggregation_methods',
        item_type=types.String(
            choices=ArchivePolicy.VALID_AGGREGATION_METHODS),
        default=['mean', 'min', 'max', 'sum', 'std', 'count'],
        help='Default aggregation methods to use in created archive policies'),
]


class ArchivePolicyItem(dict):
    def __init__(self, granularity=None, points=None, timespan=None):
        if (granularity is not None and points is not None
                and timespan is not None):
            if timespan != granularity * points:
                raise ValueError(u"timespan ≠ granularity × points")

        if granularity is not None and granularity <= 0:
            raise ValueError("Granularity should be > 0")
Beispiel #11
0
                help="""
Operators can decide whether all instances or only those instances which
contain metadata key 'HA_Enabled=True' should be taken into account to
recover from instance failure events. When set to True, it will execute
instance failure recovery actions for an instance irrespective of whether
that particular instance contains metadata key 'HA_Enabled=True' or not.
When set to False, it will only execute instance failure recovery actions
for an instance which contain metadata key 'HA_Enabled=True'."""),
]

taskflow_driver_recovery_flows = [
    cfg.Opt('host_auto_failure_recovery_tasks',
            type=types.Dict(bounds=False,
                            value_type=types.List(
                                bounds=True,
                                item_type=types.String(quotes=True))),
            default={
                'pre': ['disable_compute_service_task'],
                'main': ['prepare_HA_enabled_instances_task'],
                'post': ['evacuate_instances_task']
            },
            help=("""
This option allows operator to customize tasks to be executed for host failure
auto recovery workflow.

Provide list of strings reflecting to the task classes that should be included
to the host failure recovery workflow. The full classname path of all task
classes should be defined in the 'masakari.task_flow.tasks' of setup.cfg and
these classes may be implemented by OpenStack Masaskari project team, deployer
or third party.
Beispiel #12
0
            deprecated_reason=('Use a footer block within a template'
                               ' overrides file instead'),
            help=('Path to custom file to be added at '
                  'end of Dockerfiles for final images')),
 cfg.BoolOpt('keep', default=False,
             help='Keep failed intermediate containers'),
 cfg.BoolOpt('list-dependencies', short='l',
             help='Show image dependencies (filtering supported)'),
 cfg.BoolOpt('list-images',
             help='Show all available images'),
 cfg.StrOpt('namespace', short='n', default='kolla',
            help='The Docker namespace name'),
 cfg.BoolOpt('cache', default=True,
             help='Use the Docker cache when building',
             ),
 cfg.MultiOpt('profile', types.String(), short='p',
              help=('Build a pre-defined set of images, see [profiles]'
                    ' section in config. The default profiles are:'
                    ' {}'.format(', '.join(
                        [opt.name for opt in _PROFILE_OPTS])
                    ))),
 cfg.BoolOpt('push', default=False,
             help='Push images after building'),
 cfg.IntOpt('push-threads', default=1, min=1,
            help=('The number of threads to user while pushing'
                  ' Images. Note: Docker can not handle threading'
                  ' push properly.')),
 cfg.IntOpt('retries', short='r', default=3, min=0,
            help='The number of times to retry while building'),
 cfg.MultiOpt('regex', types.String(), positional=True,
              help=('Build only images matching regex and its'
Beispiel #13
0
The VNC proxy is an OpenStack component that enables compute service
users to access their instances through VNC clients. noVNC provides
VNC support through a websocket-based client.

This option sets the private port to which the noVNC console proxy
service should bind to.

Related options:

* novncproxy_host
* novncproxy_base_url
"""),
    cfg.ListOpt('auth_schemes',
                item_type=types.String(choices=(
                    ('none', 'Allow connection without authentication'),
                    ('vencrypt', 'Use VeNCrypt authentication scheme'),
                )),
                default=['none'],
                help="""
The authentication schemes to use with the compute node.

Control what RFB authentication schemes are permitted for connections between
the proxy and the compute host. If multiple schemes are enabled, the first
matching scheme will be used, thus the strongest schemes should be listed
first.

Related options:

* ``[vnc]vencrypt_client_key``, ``[vnc]vencrypt_client_cert``: must also be set
"""),
    cfg.StrOpt('vencrypt_client_key',
Beispiel #14
0
from glare.common import exception
from glare.i18n import _, _LE
from glare.objects import base

CONF = cfg.CONF

LOG = logging.getLogger(__name__)

registry_options = [
    cfg.ListOpt('enabled_artifact_types',
                default=[
                    'heat_templates', 'heat_environments', 'murano_packages',
                    'tosca_templates', 'images'
                ],
                item_type=types.String(),
                help=_("List of enabled artifact types that will be "
                       "available to user")),
    cfg.ListOpt('custom_artifact_types_modules',
                default=[],
                item_type=types.String(),
                help=_("List of custom user modules with artifact types that "
                       "will be uploaded by Glare dynamically during service "
                       "startup."))
]
CONF.register_opts(registry_options, group='glare')


def import_submodules(module):
    """Import all submodules of a module
Beispiel #15
0
 def test_ignore_case(self):
     self.type_instance = types.String(choices=['foo', 'bar'],
                                       ignore_case=True)
     self.assertConvertedValue('Foo', 'Foo')
     self.assertConvertedValue('bAr', 'bAr')
Beispiel #16
0
 def test_not_equal_with_different_choices(self):
     t1 = types.String(choices=['foo', 'bar'])
     t2 = types.String(choices=['foo', 'baz'])
     self.assertFalse(t1 == t2)
Beispiel #17
0
 def test_ignore_case_raises(self):
     self.type_instance = types.String(choices=['foo', 'bar'],
                                       ignore_case=False)
     self.assertRaises(ValueError, self.assertConvertedValue, 'Foo', 'Foo')
Beispiel #18
0
 def test_equal_with_equal_quote_falgs(self):
     t1 = types.String(quotes=True)
     t2 = types.String(quotes=True)
     self.assertTrue(t1 == t2)
Beispiel #19
0
 def test_regex_and_ignore_case_str(self):
     self.type_instance = types.String(regex="^[A-Z]", ignore_case=True)
     self.assertConvertedValue("foo", "foo")
Beispiel #20
0
 def test_not_equal_with_different_quote_falgs(self):
     t1 = types.String(quotes=False)
     t2 = types.String(quotes=True)
     self.assertFalse(t1 == t2)
Beispiel #21
0
 def test_max_length(self):
     self.type_instance = types.String(max_length=5)
     self.assertInvalid('123456')
     self.assertConvertedValue('12345', '12345')
Beispiel #22
0
 def test_regex_matches_uncompiled(self):
     self.type_instance = types.String(regex="^[A-Z]")
     self.assertConvertedValue("Foo", "Foo")
Beispiel #23
0
 def test_not_equal_to_other_class(self):
     self.assertFalse(types.Integer() == types.String())
Beispiel #24
0
 def test_regex_fails(self):
     self.type_instance = types.String(regex=re.compile("^[A-Z]"))
     self.assertInvalid("foo")
Beispiel #25
0
 def test_list_of_lists(self):
     self.type_instance = types.List(types.List(types.String(),
                                                bounds=True))
     self.assertConvertedValue('[foo],[bar, baz],[bam]',
                               [['foo'], ['bar', 'baz'], ['bam']])
Beispiel #26
0
 def test_equal_with_same_regex(self):
     t1 = types.String(regex=re.compile("^[A-Z]"))
     t2 = types.String(regex=re.compile("^[A-Z]"))
     self.assertTrue(t1 == t2)
Beispiel #27
0
class StringTypeTests(TypeTestHelper, unittest.TestCase):
    type = types.String()

    def test_empty_string_passes(self):
        self.assertConvertedValue('', '')

    def test_should_return_same_string_if_valid(self):
        self.assertConvertedValue('foo bar', 'foo bar')

    def test_listed_value(self):
        self.type_instance = types.String(choices=['foo', 'bar'])
        self.assertConvertedValue('foo', 'foo')

    def test_unlisted_value(self):
        self.type_instance = types.String(choices=['foo', 'bar'])
        self.assertInvalid('baz')

    def test_with_no_values_returns_error(self):
        self.type_instance = types.String(choices=[])
        self.assertInvalid('foo')

    def test_string_with_non_closed_quote_is_invalid(self):
        self.type_instance = types.String(quotes=True)
        self.assertInvalid('"foo bar')
        self.assertInvalid("'bar baz")

    def test_quotes_are_stripped(self):
        self.type_instance = types.String(quotes=True)
        self.assertConvertedValue('"foo bar"', 'foo bar')

    def test_trailing_quote_is_ok(self):
        self.type_instance = types.String(quotes=True)
        self.assertConvertedValue('foo bar"', 'foo bar"')

    def test_repr(self):
        t = types.String()
        self.assertEqual('String', repr(t))

    def test_repr_with_choices(self):
        t = types.String(choices=['foo', 'bar'])
        self.assertEqual('String(choices=[\'foo\', \'bar\'])', repr(t))

    def test_equal(self):
        self.assertTrue(types.String() == types.String())

    def test_equal_with_same_choices(self):
        t1 = types.String(choices=['foo', 'bar'])
        t2 = types.String(choices=['foo', 'bar'])
        t3 = types.String(choices=('foo', 'bar'))
        t4 = types.String(choices=['bar', 'foo'])
        self.assertTrue(t1 == t2)
        self.assertTrue(t1 == t3)
        self.assertTrue(t1 == t4)

    def test_not_equal_with_different_choices(self):
        t1 = types.String(choices=['foo', 'bar'])
        t2 = types.String(choices=['foo', 'baz'])
        self.assertFalse(t1 == t2)

    def test_equal_with_equal_quote_falgs(self):
        t1 = types.String(quotes=True)
        t2 = types.String(quotes=True)
        self.assertTrue(t1 == t2)

    def test_not_equal_with_different_quote_falgs(self):
        t1 = types.String(quotes=False)
        t2 = types.String(quotes=True)
        self.assertFalse(t1 == t2)

    def test_not_equal_to_other_class(self):
        self.assertFalse(types.String() == types.Integer())

    def test_regex_matches(self):
        self.type_instance = types.String(regex=re.compile("^[A-Z]"))
        self.assertConvertedValue("Foo", "Foo")

    def test_regex_matches_uncompiled(self):
        self.type_instance = types.String(regex="^[A-Z]")
        self.assertConvertedValue("Foo", "Foo")

    def test_regex_fails(self):
        self.type_instance = types.String(regex=re.compile("^[A-Z]"))
        self.assertInvalid("foo")

    def test_regex_and_choices_raises(self):
        self.assertRaises(ValueError,
                          types.String,
                          regex=re.compile("^[A-Z]"),
                          choices=["Foo", "Bar", "baz"])

    def test_equal_with_same_regex(self):
        t1 = types.String(regex=re.compile("^[A-Z]"))
        t2 = types.String(regex=re.compile("^[A-Z]"))
        self.assertTrue(t1 == t2)

    def test_not_equal_with_different_regex(self):
        t1 = types.String(regex=re.compile("^[A-Z]"))
        t2 = types.String(regex=re.compile("^[a-z]"))
        self.assertFalse(t1 == t2)

    def test_ignore_case(self):
        self.type_instance = types.String(choices=['foo', 'bar'],
                                          ignore_case=True)
        self.assertConvertedValue('Foo', 'Foo')
        self.assertConvertedValue('bAr', 'bAr')

    def test_ignore_case_raises(self):
        self.type_instance = types.String(choices=['foo', 'bar'],
                                          ignore_case=False)
        self.assertRaises(ValueError, self.assertConvertedValue, 'Foo', 'Foo')

    def test_regex_and_ignore_case(self):
        self.type_instance = types.String(regex=re.compile("^[A-Z]"),
                                          ignore_case=True)
        self.assertConvertedValue("foo", "foo")

    def test_regex_and_ignore_case_str(self):
        self.type_instance = types.String(regex="^[A-Z]", ignore_case=True)
        self.assertConvertedValue("foo", "foo")

    def test_regex_preserve_flags(self):
        self.type_instance = types.String(regex=re.compile("^[A-Z]", re.I),
                                          ignore_case=False)
        self.assertConvertedValue("foo", "foo")

    def test_max_length(self):
        self.type_instance = types.String(max_length=5)
        self.assertInvalid('123456')
        self.assertConvertedValue('12345', '12345')
Beispiel #28
0
 def test_not_equal_with_different_regex(self):
     t1 = types.String(regex=re.compile("^[A-Z]"))
     t2 = types.String(regex=re.compile("^[a-z]"))
     self.assertFalse(t1 == t2)
Beispiel #29
0
 def test_bounds_parsing(self):
     self.type_instance = types.Dict(types.String(), bounds=True)
     self.assertConvertedValue('{foo:bar,baz:123}', {
         'foo': 'bar',
         'baz': '123'
     })
Beispiel #30
0
class GeneratorTestCase(base.BaseTestCase):

    groups = {
        'group1':
        cfg.OptGroup(name='group1',
                     help='Lorem ipsum dolor sit amet, consectetur '
                     'adipisicing elit, sed do eiusmod tempor '
                     'incididunt ut labore et dolore magna '
                     'aliqua. Ut enim ad minim veniam, quis '
                     'nostrud exercitation ullamco laboris '
                     'nisi ut aliquip ex ea commodo '
                     'consequat. Duis aute irure dolor in.'),
        'group2':
        cfg.OptGroup(name='group2', title='Group 2'),
        'foo':
        cfg.OptGroup(name='foo', title='Foo Title', help='foo help'),
    }

    opts = {
        'foo':
        cfg.StrOpt('foo', help='foo option'),
        'bar':
        cfg.StrOpt('bar', help='bar option'),
        'foo-bar':
        cfg.StrOpt('foo-bar', help='foobar'),
        'no_help':
        cfg.StrOpt('no_help'),
        'long_help':
        cfg.StrOpt('long_help',
                   help='Lorem ipsum dolor sit amet, consectetur '
                   'adipisicing elit, sed do eiusmod tempor '
                   'incididunt ut labore et dolore magna '
                   'aliqua. Ut enim ad minim veniam, quis '
                   'nostrud exercitation ullamco laboris '
                   'nisi ut aliquip ex ea commodo '
                   'consequat. Duis aute irure dolor in '
                   'reprehenderit in voluptate velit esse '
                   'cillum dolore eu fugiat nulla '
                   'pariatur. Excepteur sint occaecat '
                   'cupidatat non proident, sunt in culpa '
                   'qui officia deserunt mollit anim id est '
                   'laborum.'),
        'long_help_pre':
        cfg.StrOpt('long_help_pre',
                   help='This is a very long help text which '
                   'is preformatted with line breaks. '
                   'It should break when it is too long '
                   'but also keep the specified line '
                   'breaks. This makes it possible to '
                   'create lists with items:\n'
                   '\n'
                   '* item 1\n'
                   '* item 2\n'
                   '\n'
                   'and should increase the '
                   'readability.'),
        'choices_opt':
        cfg.StrOpt('choices_opt',
                   default='a',
                   choices=(None, '', 'a', 'b', 'c'),
                   help='a string with choices'),
        'deprecated_opt_without_deprecated_group':
        cfg.StrOpt('bar', deprecated_name='foobar', help='deprecated'),
        'deprecated_for_removal_opt':
        cfg.StrOpt('bar',
                   deprecated_for_removal=True,
                   help='deprecated for removal'),
        'deprecated_reason_opt':
        cfg.BoolOpt(
            'turn_off_stove',
            default=False,
            deprecated_for_removal=True,
            deprecated_reason='This was supposed to work but it really, '
            'really did not. Always buy house insurance.',
            help='DEPRECATED: Turn off stove'),
        'deprecated_opt_with_deprecated_group':
        cfg.StrOpt('bar',
                   deprecated_name='foobar',
                   deprecated_group='group1',
                   help='deprecated'),
        # Unknown Opt default must be a string
        'unknown_type':
        cfg.Opt('unknown_opt',
                default='123',
                help='unknown',
                type=types.String(type_name='unknown type')),
        'str_opt':
        cfg.StrOpt('str_opt', default='foo bar', help='a string'),
        'str_opt_sample_default':
        cfg.StrOpt('str_opt', default='fooishbar', help='a string'),
        'str_opt_with_space':
        cfg.StrOpt('str_opt',
                   default='  foo bar  ',
                   help='a string with spaces'),
        'bool_opt':
        cfg.BoolOpt('bool_opt', default=False, help='a boolean'),
        'int_opt':
        cfg.IntOpt('int_opt', default=10, min=1, max=20, help='an integer'),
        'int_opt_min_0':
        cfg.IntOpt('int_opt_min_0',
                   default=10,
                   min=0,
                   max=20,
                   help='an integer'),
        'int_opt_max_0':
        cfg.IntOpt('int_opt_max_0', default=-1, max=0, help='an integer'),
        'float_opt':
        cfg.FloatOpt('float_opt', default=0.1, help='a float'),
        'list_opt':
        cfg.ListOpt('list_opt', default=['1', '2', '3'], help='a list'),
        'dict_opt':
        cfg.DictOpt('dict_opt', default={
            '1': 'yes',
            '2': 'no'
        }, help='a dict'),
        'ip_opt':
        cfg.IPOpt('ip_opt', default='127.0.0.1', help='an ip address'),
        'port_opt':
        cfg.PortOpt('port_opt', default=80, help='a port'),
        'hostname_opt':
        cfg.HostnameOpt('hostname_opt',
                        default='compute01.nova.site1',
                        help='a hostname'),
        'multi_opt':
        cfg.MultiStrOpt('multi_opt',
                        default=['1', '2', '3'],
                        help='multiple strings'),
        'multi_opt_none':
        cfg.MultiStrOpt('multi_opt_none', help='multiple strings'),
        'multi_opt_empty':
        cfg.MultiStrOpt('multi_opt_empty', default=[],
                        help='multiple strings'),
        'multi_opt_sample_default':
        cfg.MultiStrOpt('multi_opt',
                        default=['1', '2', '3'],
                        sample_default=['5', '6'],
                        help='multiple strings'),
        'string_type_with_bad_default':
        cfg.Opt('string_type_with_bad_default',
                help='string with bad default',
                default=4096),
        'custom_type':
        cfg.Opt('custom_type', help='custom help', type=type('string')),
        'custom_type_name':
        cfg.Opt('custom_opt_type',
                type=types.Integer(type_name='port'
                                   ' number'),
                default=5511,
                help='this is a port'),
    }

    content_scenarios = [
        ('empty', dict(opts=[], expected='''[DEFAULT]
''')),
        ('single_namespace',
         dict(opts=[('test', [(None, [opts['foo']])])],
              expected='''[DEFAULT]

#
# From test
#

# foo option (string value)
#foo = <None>
''')),
        ('multiple_namespaces',
         dict(opts=[('test', [(None, [opts['foo']])]),
                    ('other', [(None, [opts['bar']])])],
              expected='''[DEFAULT]

#
# From other
#

# bar option (string value)
#bar = <None>

#
# From test
#

# foo option (string value)
#foo = <None>
''')),
        ('group',
         dict(opts=[('test', [(groups['group1'], [opts['foo']])])],
              expected='''[DEFAULT]


[group1]
# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
# aliquip ex ea commodo consequat. Duis aute irure dolor in.

#
# From test
#

# foo option (string value)
#foo = <None>
''')),
        ('empty_group',
         dict(opts=[('test', [(groups['group1'], [])])],
              expected='''[DEFAULT]
''')),
        ('multiple_groups',
         dict(opts=[('test', [(groups['group1'], [opts['foo']]),
                              (groups['group2'], [opts['bar']])])],
              expected='''[DEFAULT]


[group1]
# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
# aliquip ex ea commodo consequat. Duis aute irure dolor in.

#
# From test
#

# foo option (string value)
#foo = <None>


[group2]

#
# From test
#

# bar option (string value)
#bar = <None>
''')),
        ('group_in_multiple_namespaces',
         dict(opts=[('test', [(groups['group1'], [opts['foo']])]),
                    ('other', [(groups['group1'], [opts['bar']])])],
              expected='''[DEFAULT]


[group1]
# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
# aliquip ex ea commodo consequat. Duis aute irure dolor in.

#
# From other
#

# bar option (string value)
#bar = <None>

#
# From test
#

# foo option (string value)
#foo = <None>
''')),
        ('hyphenated_name',
         dict(opts=[('test', [(None, [opts['foo-bar']])])],
              expected='''[DEFAULT]

#
# From test
#

# foobar (string value)
#foo_bar = <None>
''')),
        ('no_help',
         dict(opts=[('test', [(None, [opts['no_help']])])],
              log_warning=('"%s" is missing a help string', 'no_help'),
              expected='''[DEFAULT]

#
# From test
#

# (string value)
#no_help = <None>
''')),
        ('long_help',
         dict(opts=[('test', [(None, [opts['long_help']])])],
              expected='''[DEFAULT]

#
# From test
#

# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
# aliquip ex ea commodo consequat. Duis aute irure dolor in
# reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
# pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
# culpa qui officia deserunt mollit anim id est laborum. (string
# value)
#long_help = <None>
''')),
        ('long_help_wrap_at_40',
         dict(opts=[('test', [(None, [opts['long_help']])])],
              wrap_width=40,
              expected='''[DEFAULT]

#
# From test
#

# Lorem ipsum dolor sit amet,
# consectetur adipisicing elit, sed do
# eiusmod tempor incididunt ut labore et
# dolore magna aliqua. Ut enim ad minim
# veniam, quis nostrud exercitation
# ullamco laboris nisi ut aliquip ex ea
# commodo consequat. Duis aute irure
# dolor in reprehenderit in voluptate
# velit esse cillum dolore eu fugiat
# nulla pariatur. Excepteur sint
# occaecat cupidatat non proident, sunt
# in culpa qui officia deserunt mollit
# anim id est laborum. (string value)
#long_help = <None>
''')),
        (
            'long_help_no_wrapping',
            dict(
                opts=[('test', [(None, [opts['long_help']])])],
                wrap_width=0,
                expected='''[DEFAULT]

#
# From test
#

'''

                # noqa
                '# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod '
                'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, '
                'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo '
                'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse '
                'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '
                'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. '
                '(string value)'
                '''
#long_help = <None>
''')),
        ('long_help_with_preformatting',
         dict(opts=[('test', [(None, [opts['long_help_pre']])])],
              wrap_width=70,
              expected='''[DEFAULT]

#
# From test
#

# This is a very long help text which is preformatted with line
# breaks. It should break when it is too long but also keep the
# specified line breaks. This makes it possible to create lists with
# items:
#
# * item 1
# * item 2
#
# and should increase the readability. (string value)
#long_help_pre = <None>
''')),
        ('choices_opt',
         dict(opts=[('test', [(None, [opts['choices_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a string with choices (string value)
# Allowed values: <None>, '', a, b, c
#choices_opt = a
''')),
        ('deprecated opt without deprecated group',
         dict(opts=[('test', [
             (groups['foo'], [opts['deprecated_opt_without_deprecated_group']])
         ])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From test
#

# deprecated (string value)
# Deprecated group/name - [foo]/foobar
#bar = <None>
''')),
        ('deprecated_for_removal',
         dict(opts=[('test', [(groups['foo'],
                               [opts['deprecated_for_removal_opt']])])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From test
#

# DEPRECATED: deprecated for removal (string value)
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
#bar = <None>
''')),
        ('deprecated_reason',
         dict(opts=[('test', [(groups['foo'], [opts['deprecated_reason_opt']])
                              ])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From test
#

# DEPRECATED: Turn off stove (boolean value)
# This option is deprecated for removal.
# Its value may be silently ignored in the future.
# Reason: This was supposed to work but it really, really did not.
# Always buy house insurance.
#turn_off_stove = false
''')),
        ('deprecated_opt_with_deprecated_group',
         dict(opts=[('test', [
             (groups['foo'], [opts['deprecated_opt_with_deprecated_group']])
         ])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From test
#

# deprecated (string value)
# Deprecated group/name - [group1]/foobar
#bar = <None>
''')),
        ('unknown_type',
         dict(opts=[('test', [(None, [opts['unknown_type']])])],
              expected='''[DEFAULT]

#
# From test
#

# unknown (unknown type)
#unknown_opt = 123
''')),
        ('str_opt',
         dict(opts=[('test', [(None, [opts['str_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a string (string value)
#str_opt = foo bar
''')),
        ('str_opt_with_space',
         dict(opts=[('test', [(None, [opts['str_opt_with_space']])])],
              expected='''[DEFAULT]

#
# From test
#

# a string with spaces (string value)
#str_opt = "  foo bar  "
''')),
        ('bool_opt',
         dict(opts=[('test', [(None, [opts['bool_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a boolean (boolean value)
#bool_opt = false
''')),
        ('int_opt',
         dict(opts=[('test', [(None, [opts['int_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# an integer (integer value)
# Minimum value: 1
# Maximum value: 20
#int_opt = 10
''')),
        ('int_opt_min_0',
         dict(opts=[('test', [(None, [opts['int_opt_min_0']])])],
              expected='''[DEFAULT]

#
# From test
#

# an integer (integer value)
# Minimum value: 0
# Maximum value: 20
#int_opt_min_0 = 10
''')),
        ('int_opt_max_0',
         dict(opts=[('test', [(None, [opts['int_opt_max_0']])])],
              expected='''[DEFAULT]

#
# From test
#

# an integer (integer value)
# Maximum value: 0
#int_opt_max_0 = -1
''')),
        ('float_opt',
         dict(opts=[('test', [(None, [opts['float_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a float (floating point value)
#float_opt = 0.1
''')),
        ('list_opt',
         dict(opts=[('test', [(None, [opts['list_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a list (list value)
#list_opt = 1,2,3
''')),
        ('dict_opt',
         dict(opts=[('test', [(None, [opts['dict_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a dict (dict value)
#dict_opt = 1:yes,2:no
''')),
        ('ip_opt',
         dict(opts=[('test', [(None, [opts['ip_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# an ip address (IP address value)
#ip_opt = 127.0.0.1
''')),
        ('port_opt',
         dict(opts=[('test', [(None, [opts['port_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a port (port value)
# Minimum value: 0
# Maximum value: 65535
#port_opt = 80
''')),
        ('hostname_opt',
         dict(opts=[('test', [(None, [opts['hostname_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# a hostname (hostname value)
#hostname_opt = compute01.nova.site1
''')),
        ('multi_opt',
         dict(opts=[('test', [(None, [opts['multi_opt']])])],
              expected='''[DEFAULT]

#
# From test
#

# multiple strings (multi valued)
#multi_opt = 1
#multi_opt = 2
#multi_opt = 3
''')),
        ('multi_opt_none',
         dict(opts=[('test', [(None, [opts['multi_opt_none']])])],
              expected='''[DEFAULT]

#
# From test
#

# multiple strings (multi valued)
#multi_opt_none =
''')),
        ('multi_opt_empty',
         dict(opts=[('test', [(None, [opts['multi_opt_empty']])])],
              expected='''[DEFAULT]

#
# From test
#

# multiple strings (multi valued)
#multi_opt_empty =
''')),
        ('str_opt_sample_default',
         dict(opts=[('test', [(None, [opts['str_opt_sample_default']])])],
              expected='''[DEFAULT]

#
# From test
#

# a string (string value)
#str_opt = fooishbar
''')),
        ('multi_opt_sample_default',
         dict(opts=[('test', [(None, [opts['multi_opt_sample_default']])])],
              expected='''[DEFAULT]

#
# From test
#

# multiple strings (multi valued)
#multi_opt = 5
#multi_opt = 6
''')),
        ('custom_type_name',
         dict(opts=[('test', [(None, [opts['custom_type_name']])])],
              expected='''[DEFAULT]

#
# From test
#

# this is a port (port number)
#custom_opt_type = 5511
''')),
        ('custom_type',
         dict(opts=[('test', [(None, [opts['custom_type']])])],
              expected='''[DEFAULT]

#
# From test
#

# custom help (unknown value)
#custom_type = <None>
''')),
        ('string_type_with_bad_default',
         dict(opts=[('test', [(None, [opts['string_type_with_bad_default']])])
                    ],
              expected='''[DEFAULT]

#
# From test
#

# string with bad default (string value)
#string_type_with_bad_default = 4096
''')),
        ('str_opt_str_group',
         dict(opts=[('test', [('foo', [opts['str_opt']]),
                              (groups['foo'], [opts['int_opt']])]),
                    ('foo', [('foo', [opts['bool_opt']])])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From foo
#

# a boolean (boolean value)
#bool_opt = false

#
# From test
#

# a string (string value)
#str_opt = foo bar

#
# From test
#

# an integer (integer value)
# Minimum value: 1
# Maximum value: 20
#int_opt = 10
''')),
        ('opt_str_opt_group',
         dict(opts=[('test', [(groups['foo'], [opts['int_opt']]),
                              ('foo', [opts['str_opt']])]),
                    ('foo', [(groups['foo'], [opts['bool_opt']])])],
              expected='''[DEFAULT]


[foo]
# foo help

#
# From foo
#

# a boolean (boolean value)
#bool_opt = false

#
# From test
#

# an integer (integer value)
# Minimum value: 1
# Maximum value: 20
#int_opt = 10

#
# From test
#

# a string (string value)
#str_opt = foo bar
''')),
    ]

    output_file_scenarios = [
        ('stdout', dict(stdout=True, output_file=None)),
        ('output_file', dict(output_file='sample.conf', stdout=False)),
    ]

    @classmethod
    def generate_scenarios(cls):
        cls.scenarios = testscenarios.multiply_scenarios(
            cls.content_scenarios, cls.output_file_scenarios)

    def setUp(self):
        super(GeneratorTestCase, self).setUp()

        self.conf = cfg.ConfigOpts()
        self.config_fixture = config_fixture.Config(self.conf)
        self.config = self.config_fixture.config
        self.useFixture(self.config_fixture)

        self.tempdir = self.useFixture(fixtures.TempDir())

    def _capture_stream(self, stream_name):
        self.useFixture(
            fixtures.MonkeyPatch("sys.%s" % stream_name, moves.StringIO()))
        return getattr(sys, stream_name)

    def _capture_stdout(self):
        return self._capture_stream('stdout')

    @mock.patch.object(generator, '_get_raw_opts_loaders')
    @mock.patch.object(generator, 'LOG')
    def test_generate(self, mock_log, raw_opts_loader):
        generator.register_cli_opts(self.conf)

        namespaces = [i[0] for i in self.opts]
        self.config(namespace=namespaces)

        for group in self.groups.values():
            self.conf.register_group(group)

        wrap_width = getattr(self, 'wrap_width', None)
        if wrap_width is not None:
            self.config(wrap_width=wrap_width)

        if self.stdout:
            stdout = self._capture_stdout()
        else:
            output_file = self.tempdir.join(self.output_file)
            self.config(output_file=output_file)

        # We have a static data structure matching what should be
        # returned by _list_opts() but we're mocking out a lower level
        # function that needs to return a namespace and a callable to
        # return options from that namespace. We have to pass opts to
        # the lambda to cache a reference to the name because the list
        # comprehension changes the thing pointed to by the name each
        # time through the loop.
        raw_opts_loader.return_value = [(ns, lambda opts=opts: opts)
                                        for ns, opts in self.opts]

        generator.generate(self.conf)

        if self.stdout:
            self.assertEqual(self.expected, stdout.getvalue())
        else:
            with open(output_file, 'r') as f:
                actual = f.read()
            self.assertEqual(self.expected, actual)

        log_warning = getattr(self, 'log_warning', None)
        if log_warning is not None:
            mock_log.warning.assert_called_once_with(*log_warning)
        else:
            self.assertFalse(mock_log.warning.called)