diff --git a/devstack/lib/watcher b/devstack/lib/watcher index a0fd2c453..09658e5de 100644 --- a/devstack/lib/watcher +++ b/devstack/lib/watcher @@ -42,7 +42,7 @@ WATCHER_AUTH_CACHE_DIR=${WATCHER_AUTH_CACHE_DIR:-/var/cache/watcher} WATCHER_CONF_DIR=/etc/watcher WATCHER_CONF=$WATCHER_CONF_DIR/watcher.conf -WATCHER_POLICY_JSON=$WATCHER_CONF_DIR/policy.json +WATCHER_POLICY_YAML=$WATCHER_CONF_DIR/policy.yaml.sample WATCHER_DEVSTACK_DIR=$WATCHER_DIR/devstack WATCHER_DEVSTACK_FILES_DIR=$WATCHER_DEVSTACK_DIR/files @@ -106,7 +106,25 @@ function configure_watcher { # Put config files in ``/etc/watcher`` for everyone to find sudo install -d -o $STACK_USER $WATCHER_CONF_DIR - install_default_policy watcher + local project=watcher + local project_uc + project_uc=$(echo watcher|tr a-z A-Z) + local conf_dir="${project_uc}_CONF_DIR" + # eval conf dir to get the variable + conf_dir="${!conf_dir}" + local project_dir="${project_uc}_DIR" + # eval project dir to get the variable + project_dir="${!project_dir}" + local sample_conf_dir="${project_dir}/etc/${project}" + local sample_policy_dir="${project_dir}/etc/${project}/policy.d" + local sample_policy_generator="${project_dir}/etc/${project}/oslo-policy-generator/watcher-policy-generator.conf" + + # first generate policy.yaml + oslopolicy-sample-generator --config-file $sample_policy_generator + # then optionally copy over policy.d + if [[ -d $sample_policy_dir ]]; then + cp -r $sample_policy_dir $conf_dir/policy.d + fi # Rebuild the config file from scratch create_watcher_conf @@ -163,7 +181,7 @@ function create_watcher_conf { iniset $WATCHER_CONF api host "$WATCHER_SERVICE_HOST" iniset $WATCHER_CONF api port "$WATCHER_SERVICE_PORT" - iniset $WATCHER_CONF oslo_policy policy_file $WATCHER_POLICY_JSON + iniset $WATCHER_CONF oslo_policy policy_file $WATCHER_POLICY_YAML iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_userid $RABBIT_USERID iniset $WATCHER_CONF oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD diff --git a/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf b/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf new file mode 100644 index 000000000..445795d31 --- /dev/null +++ b/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf @@ -0,0 +1,3 @@ +[DEFAULT] +output_file = /etc/watcher/policy.yaml.sample +namespace = watcher diff --git a/etc/watcher/policy.json b/etc/watcher/policy.json deleted file mode 100644 index 5f9493164..000000000 --- a/etc/watcher/policy.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "admin_api": "role:admin or role:administrator", - "show_password": "!", - "default": "rule:admin_api", - - "action:detail": "rule:default", - "action:get": "rule:default", - "action:get_all": "rule:default", - - "action_plan:delete": "rule:default", - "action_plan:detail": "rule:default", - "action_plan:get": "rule:default", - "action_plan:get_all": "rule:default", - "action_plan:update": "rule:default", - - "audit:create": "rule:default", - "audit:delete": "rule:default", - "audit:detail": "rule:default", - "audit:get": "rule:default", - "audit:get_all": "rule:default", - "audit:update": "rule:default", - - "audit_template:create": "rule:default", - "audit_template:delete": "rule:default", - "audit_template:detail": "rule:default", - "audit_template:get": "rule:default", - "audit_template:get_all": "rule:default", - "audit_template:update": "rule:default", - - "goal:detail": "rule:default", - "goal:get": "rule:default", - "goal:get_all": "rule:default", - - "scoring_engine:detail": "rule:default", - "scoring_engine:get": "rule:default", - "scoring_engine:get_all": "rule:default", - - "strategy:detail": "rule:default", - "strategy:get": "rule:default", - "strategy:get_all": "rule:default", - - "service:detail": "rule:default", - "service:get": "rule:default", - "service:get_all": "rule:default" -} diff --git a/setup.cfg b/setup.cfg index df2bee1b1..588557179 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,12 @@ setup-hooks = oslo.config.opts = watcher = watcher.conf.opts:list_opts +oslo.policy.policies = + watcher = watcher.common.policies:list_rules + +oslo.policy.enforcer = + watcher = watcher.common.policy:get_enforcer + console_scripts = watcher-api = watcher.cmd.api:main watcher-db-manage = watcher.cmd.dbmanage:main diff --git a/tox.ini b/tox.ini index e1602cc1b..39b10db23 100644 --- a/tox.ini +++ b/tox.ini @@ -46,6 +46,10 @@ sitepackages = False commands = oslo-config-generator --config-file etc/watcher/oslo-config-generator/watcher.conf +[testenv:genpolicy] +commands = + oslopolicy-sample-generator --config-file etc/watcher/oslo-policy-generator/watcher-policy-generator.conf + [flake8] filename = *.py,app.wsgi show-source=True diff --git a/watcher/common/policies/__init__.py b/watcher/common/policies/__init__.py new file mode 100644 index 000000000..3a96fdc44 --- /dev/null +++ b/watcher/common/policies/__init__.py @@ -0,0 +1,37 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import itertools + +from watcher.common.policies import action +from watcher.common.policies import action_plan +from watcher.common.policies import audit +from watcher.common.policies import audit_template +from watcher.common.policies import base +from watcher.common.policies import goal +from watcher.common.policies import scoring_engine +from watcher.common.policies import service +from watcher.common.policies import strategy + + +def list_rules(): + return itertools.chain( + base.list_rules(), + action.list_rules(), + action_plan.list_rules(), + audit.list_rules(), + audit_template.list_rules(), + goal.list_rules(), + scoring_engine.list_rules(), + service.list_rules(), + strategy.list_rules(), + ) diff --git a/watcher/common/policies/action.py b/watcher/common/policies/action.py new file mode 100644 index 000000000..5e87d7c42 --- /dev/null +++ b/watcher/common/policies/action.py @@ -0,0 +1,57 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +ACTION = 'action:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=ACTION % 'detail', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of actions with detail.', + operations=[ + { + 'path': '/v1/actions/detail', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION % 'get', + check_str=base.RULE_ADMIN_API, + description='Retrieve information about a given action.', + operations=[ + { + 'path': '/v1/actions/{action_id}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of all actions.', + operations=[ + { + 'path': '/v1/actions', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/action_plan.py b/watcher/common/policies/action_plan.py new file mode 100644 index 000000000..613d4bcf7 --- /dev/null +++ b/watcher/common/policies/action_plan.py @@ -0,0 +1,79 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +ACTION_PLAN = 'action_plan:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=ACTION_PLAN % 'delete', + check_str=base.RULE_ADMIN_API, + description='Delete an action plan.', + operations=[ + { + 'path': '/v1/action_plans/{action_plan_uuid}', + 'method': 'DELETE' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION_PLAN % 'detail', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of action plans with detail.', + operations=[ + { + 'path': '/v1/action_plans/detail', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION_PLAN % 'get', + check_str=base.RULE_ADMIN_API, + description='Get an action plan.', + operations=[ + { + 'path': '/v1/action_plans/{action_plan_id}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION_PLAN % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Get all action plans.', + operations=[ + { + 'path': '/v1/action_plans', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=ACTION_PLAN % 'update', + check_str=base.RULE_ADMIN_API, + description='Update an action plans.', + operations=[ + { + 'path': '/v1/action_plans/{action_plan_uuid}', + 'method': 'PATCH' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/audit.py b/watcher/common/policies/audit.py new file mode 100644 index 000000000..479df4aa5 --- /dev/null +++ b/watcher/common/policies/audit.py @@ -0,0 +1,90 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +AUDIT = 'audit:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=AUDIT % 'create', + check_str=base.RULE_ADMIN_API, + description='Create a new audit.', + operations=[ + { + 'path': '/v1/audits', + 'method': 'POST' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT % 'delete', + check_str=base.RULE_ADMIN_API, + description='Delete an audit.', + operations=[ + { + 'path': '/v1/audits/{audit_uuid}', + 'method': 'DELETE' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT % 'detail', + check_str=base.RULE_ADMIN_API, + description='Retrieve audit list with details.', + operations=[ + { + 'path': '/v1/audits/detail', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT % 'get', + check_str=base.RULE_ADMIN_API, + description='Get an audit.', + operations=[ + { + 'path': '/v1/audits/{audit_uuid}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Get all audits.', + operations=[ + { + 'path': '/v1/audits', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT % 'update', + check_str=base.RULE_ADMIN_API, + description='Update an audit.', + operations=[ + { + 'path': '/v1/audits/{audit_uuid}', + 'method': 'PATCH' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/audit_template.py b/watcher/common/policies/audit_template.py new file mode 100644 index 000000000..71952298d --- /dev/null +++ b/watcher/common/policies/audit_template.py @@ -0,0 +1,90 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +AUDIT_TEMPLATE = 'audit_template:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'create', + check_str=base.RULE_ADMIN_API, + description='Create an audit template.', + operations=[ + { + 'path': '/v1/audit_templates', + 'method': 'POST' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'delete', + check_str=base.RULE_ADMIN_API, + description='Delete an audit template.', + operations=[ + { + 'path': '/v1/audit_templates/{audit_template_uuid}', + 'method': 'DELETE' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'detail', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of audit templates with details.', + operations=[ + { + 'path': '/v1/audit_templates/detail', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'get', + check_str=base.RULE_ADMIN_API, + description='Get an audit template.', + operations=[ + { + 'path': '/v1/audit_templates/{audit_template_uuid}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Get a list of all audit templates.', + operations=[ + { + 'path': '/v1/audit_templates', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=AUDIT_TEMPLATE % 'update', + check_str=base.RULE_ADMIN_API, + description='Update an audit template.', + operations=[ + { + 'path': '/v1/audit_templates/{audit_template_uuid}', + 'method': 'PATCH' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/base.py b/watcher/common/policies/base.py new file mode 100644 index 000000000..6e5dec7f2 --- /dev/null +++ b/watcher/common/policies/base.py @@ -0,0 +1,32 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +RULE_ADMIN_API = 'rule:admin_api' +ROLE_ADMIN_OR_ADMINISTRATOR = 'role:admin or role:administrator' +ALWAYS_DENY = '!' + +rules = [ + policy.RuleDefault( + name='admin_api', + check_str=ROLE_ADMIN_OR_ADMINISTRATOR + ), + policy.RuleDefault( + name='show_password', + check_str=ALWAYS_DENY + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/goal.py b/watcher/common/policies/goal.py new file mode 100644 index 000000000..6f422c945 --- /dev/null +++ b/watcher/common/policies/goal.py @@ -0,0 +1,57 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +GOAL = 'goal:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=GOAL % 'detail', + check_str=base.RULE_ADMIN_API, + description='Retrieve a list of goals with detail.', + operations=[ + { + 'path': '/v1/goals/detail', + 'method': 'DELETE' + } + ] + ), + policy.DocumentedRuleDefault( + name=GOAL % 'get', + check_str=base.RULE_ADMIN_API, + description='Get a goal.', + operations=[ + { + 'path': '/v1/goals/{goal_uuid}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=GOAL % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Get all goals.', + operations=[ + { + 'path': '/v1/goals', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/scoring_engine.py b/watcher/common/policies/scoring_engine.py new file mode 100644 index 000000000..e986b24d8 --- /dev/null +++ b/watcher/common/policies/scoring_engine.py @@ -0,0 +1,66 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +SCORING_ENGINE = 'scoring_engine:%s' + +rules = [ + # FIXME(lbragstad): Find someone from watcher to double check this + # information. This API isn't listed in watcher's API reference + # documentation. + policy.DocumentedRuleDefault( + name=SCORING_ENGINE % 'detail', + check_str=base.RULE_ADMIN_API, + description='List scoring engines with details.', + operations=[ + { + 'path': '/v1/scoring_engines/detail', + 'method': 'GET' + } + ] + ), + # FIXME(lbragstad): Find someone from watcher to double check this + # information. This API isn't listed in watcher's API reference + # documentation. + policy.DocumentedRuleDefault( + name=SCORING_ENGINE % 'get', + check_str=base.RULE_ADMIN_API, + description='Get a scoring engine.', + operations=[ + { + 'path': '/v1/scoring_engines/{scoring_engine_id}', + 'method': 'GET' + } + ] + ), + # FIXME(lbragstad): Find someone from watcher to double check this + # information. This API isn't listed in watcher's API reference + # documentation. + policy.DocumentedRuleDefault( + name=SCORING_ENGINE % 'get_all', + check_str=base.RULE_ADMIN_API, + description='Get all scoring engines.', + operations=[ + { + 'path': '/v1/scoring_engines', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/service.py b/watcher/common/policies/service.py new file mode 100644 index 000000000..f5ecae9b1 --- /dev/null +++ b/watcher/common/policies/service.py @@ -0,0 +1,57 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +SERVICE = 'service:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=SERVICE % 'detail', + check_str=base.RULE_ADMIN_API, + description='List services with detail.', + operations=[ + { + 'path': '/v1/services/', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=SERVICE % 'get', + check_str=base.RULE_ADMIN_API, + description='Get a specific service.', + operations=[ + { + 'path': '/v1/services/{service_id}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=SERVICE % 'get_all', + check_str=base.RULE_ADMIN_API, + description='List all services.', + operations=[ + { + 'path': '/v1/services/', + 'method': 'GET' + } + ] + ), +] + + +def list_rules(): + return rules diff --git a/watcher/common/policies/strategy.py b/watcher/common/policies/strategy.py new file mode 100644 index 000000000..9cdfc65fc --- /dev/null +++ b/watcher/common/policies/strategy.py @@ -0,0 +1,57 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_policy import policy + +from watcher.common.policies import base + +STRATEGY = 'strategy:%s' + +rules = [ + policy.DocumentedRuleDefault( + name=STRATEGY % 'detail', + check_str=base.RULE_ADMIN_API, + description='List strategies with detail.', + operations=[ + { + 'path': '/v1/strategies/detail', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=STRATEGY % 'get', + check_str=base.RULE_ADMIN_API, + description='Get a strategy.', + operations=[ + { + 'path': '/v1/strategies/{strategy_uuid}', + 'method': 'GET' + } + ] + ), + policy.DocumentedRuleDefault( + name=STRATEGY % 'get_all', + check_str=base.RULE_ADMIN_API, + description='List all strategies.', + operations=[ + { + 'path': '/v1/strategies', + 'method': 'GET' + } + ] + ) +] + + +def list_rules(): + return rules diff --git a/watcher/common/policy.py b/watcher/common/policy.py index 7d1458a28..d2d12acf4 100644 --- a/watcher/common/policy.py +++ b/watcher/common/policy.py @@ -15,11 +15,13 @@ """Policy Engine For Watcher.""" +import sys + from oslo_config import cfg from oslo_policy import policy from watcher.common import exception - +from watcher.common import policies _ENFORCER = None CONF = cfg.CONF @@ -56,6 +58,7 @@ def init(policy_file=None, rules=None, default_rule=default_rule, use_conf=use_conf, overwrite=overwrite) + _ENFORCER.register_defaults(policies.list_rules()) return _ENFORCER @@ -92,3 +95,23 @@ def enforce(context, rule=None, target=None, 'user_id': context.user_id} return enforcer.enforce(rule, target, credentials, do_raise=do_raise, exc=exc, *args, **kwargs) + + +def get_enforcer(): + # This method is for use by oslopolicy CLI scripts. Those scripts need the + # 'output-file' and 'namespace' options, but having those in sys.argv means + # loading the Watcher config options will fail as those are not expected + # to be present. So we pass in an arg list with those stripped out. + conf_args = [] + # Start at 1 because cfg.CONF expects the equivalent of sys.argv[1:] + i = 1 + while i < len(sys.argv): + if sys.argv[i].strip('-') in ['namespace', 'output-file']: + i += 2 + continue + conf_args.append(sys.argv[i]) + i += 1 + + cfg.CONF(conf_args, project='watcher') + init() + return _ENFORCER