Added trust for workbook runs

Change-Id: Id2afa200858ce1cf9481883134d3c3d524f44cd9
This commit is contained in:
Alexander Kuznetsov 2013-12-13 20:37:49 +04:00
parent a8acc1934d
commit cafa9fed0e
12 changed files with 185 additions and 8 deletions

1
.gitignore vendored
View File

@ -36,6 +36,7 @@ nosetests.xml
.project .project
.pydevproject .pydevproject
.idea .idea
.DS_Store
etc/mistral.conf etc/mistral.conf
tools/lintstack.head.py tools/lintstack.head.py
tools/pylint_exceptions tools/pylint_exceptions

View File

@ -33,3 +33,12 @@ rabbit_virtual_host = /
rabbit_task_queue = tasks rabbit_task_queue = tasks
rabbit_user = guest rabbit_user = guest
rabbit_password = guest rabbit_password = guest
[keystone_authtoken]
auth_uri=http://localhost:5000/v3
auth_host=localhost
auth_port=5000
admin_user=admin
admin_password=password
auth_protocol=http
admin_tenant_name=admin

View File

@ -23,6 +23,7 @@ from mistral.api.controllers.v1 import workbook_definition
from mistral.api.controllers.v1 import listener from mistral.api.controllers.v1 import listener
from mistral.api.controllers.v1 import execution from mistral.api.controllers.v1 import execution
from mistral.api.controllers import resource from mistral.api.controllers import resource
from mistral.services import workbooks
from mistral.openstack.common import log as logging from mistral.openstack.common import log as logging
from mistral.db import api as db_api from mistral.db import api as db_api
@ -45,7 +46,6 @@ class Workbooks(resource.Resource):
class WorkbooksController(rest.RestController): class WorkbooksController(rest.RestController):
definition = workbook_definition.WorkbookDefinitionController() definition = workbook_definition.WorkbookDefinitionController()
listeners = listener.ListenersController() listeners = listener.ListenersController()
executions = execution.ExecutionsController() executions = execution.ExecutionsController()
@ -72,7 +72,8 @@ class WorkbooksController(rest.RestController):
def post(self, workbook): def post(self, workbook):
LOG.debug("Create workbook [workbook=%s]" % workbook) LOG.debug("Create workbook [workbook=%s]" % workbook)
return Workbook.from_dict(db_api.workbook_create(workbook.to_dict())) wb = workbooks.create_workbook(workbook.to_dict())
return Workbook.from_dict(wb)
@wsme_pecan.wsexpose(None, wtypes.text, status_code=204) @wsme_pecan.wsexpose(None, wtypes.text, status_code=204)
def delete(self, name): def delete(self, name):

View File

@ -56,7 +56,6 @@ class BaseContext(object):
class MistralContext(BaseContext): class MistralContext(BaseContext):
_elements = set([ _elements = set([
"user_id", "user_id",
"project_id", "project_id",
@ -64,6 +63,7 @@ class MistralContext(BaseContext):
"service_catalog", "service_catalog",
"user_name", "user_name",
"project_name", "project_name",
"roles",
"is_admin", "is_admin",
]) ])
@ -127,12 +127,12 @@ def context_from_headers(headers):
auth_token=headers.get('X-Auth-Token'), auth_token=headers.get('X-Auth-Token'),
service_catalog=headers.get('X-Service-Catalog'), service_catalog=headers.get('X-Service-Catalog'),
user_name=headers.get('X-User-Name'), user_name=headers.get('X-User-Name'),
project_name=headers.get('X-Project-Name') project_name=headers.get('X-Project-Name'),
roles=headers.get('X-Roles', "").split(",")
) )
class ContextHook(PecanHook): class ContextHook(PecanHook):
def before(self, state): def before(self, state):
request_ctx = context_from_headers(state.request.headers).to_dict() request_ctx = context_from_headers(state.request.headers).to_dict()
set_ctx(request_ctx) set_ctx(request_ctx)

View File

@ -75,6 +75,8 @@ class Workbook(mb.MistralBase):
description = sa.Column(sa.String()) description = sa.Column(sa.String())
tags = sa.Column(st.JsonListType()) tags = sa.Column(st.JsonListType())
scope = sa.Column(sa.String()) scope = sa.Column(sa.String())
project_id = sa.Column(sa.String())
trust_id = sa.Column(sa.String())
class Task(mb.MistralBase): class Task(mb.MistralBase):

View File

@ -0,0 +1,82 @@
# Copyright (c) 2013 Mirantis Inc.
#
# 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.config import cfg
from mistral.utils.openstack import keystone
from mistral import context
from mistral.db import api as db_api
CONF = cfg.CONF
def create_trust(workbook):
client = keystone.client()
ctx = context.current()
admin_user = CONF.keystone_authtoken.admin_user
admin_password = CONF.keystone_authtoken.admin_password
admin_tenant_name = CONF.keystone_authtoken.admin_tenant_name
trustee_id = keystone.client_for_trusts(
admin_user,
admin_password,
project_name=admin_tenant_name).user_id
trust = client.trusts.create(trustor_user=client.user_id,
trustee_user=trustee_id,
impersonation=True,
role_names=ctx['roles'],
project=ctx['project_id'])
return db_api.workbook_update(workbook['name'],
{'trust_id': trust.id,
'project_id': ctx['project_id']})
def create_context(workbook):
if not workbook.trust_id:
return
admin_user = CONF.keystone_authtoken.admin_user
admin_password = CONF.keystone_authtoken.admin_password
client = keystone.client_for_trusts(
admin_user,
admin_password,
trust_id=workbook['trust_id'],
project_id=workbook['project_id'])
return context.MistralContext(
user_id=client.user_id,
project_id=workbook['project_id'],
auth_token=client.auth_token
)
def delete_trust(workbook):
if workbook.trust_id:
return
admin_user = CONF.keystone_authtoken.admin_user
admin_password = CONF.keystone_authtoken.admin_password
keystone_client = keystone.client_for_trusts(
admin_user,
admin_password,
workbook.trust_id)
keystone_client.trusts.delete(workbook.trust_id)

View File

@ -0,0 +1,26 @@
# Copyright (c) 2013 Mirantis Inc.
#
# 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 mistral.db import api as db_api
from mistral.services import trusts
def create_workbook(values):
workbook = db_api.workbook_create(values)
workbook = trusts.create_trust(workbook)
##TODO(akuznetsov) filter fields
##TODO(akuznetsov) create events
return workbook

View File

@ -67,8 +67,10 @@ class TestWorkbooksController(base.FunctionalTest):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertDictEqual(updated_workbook, resp.json) self.assertDictEqual(updated_workbook, resp.json)
def test_post(self): @mock.patch("mistral.services.trusts.create_trust")
def test_post(self, create_trust):
db_api.workbook_create = mock.MagicMock(return_value=WORKBOOKS[0]) db_api.workbook_create = mock.MagicMock(return_value=WORKBOOKS[0])
create_trust.return_value = WORKBOOKS[0]
resp = self.app.post_json('/v1/workbooks', WORKBOOKS[0]) resp = self.app.post_json('/v1/workbooks', WORKBOOKS[0])

View File

@ -79,7 +79,9 @@ WORKBOOKS = [
"definition": u'empty', "definition": u'empty',
"tags": [u'mc'], "tags": [u'mc'],
"scope": u'public', "scope": u'public',
"updated_at": None "updated_at": None,
"project_id": '123',
"trust_id": '1234'
}, },
{ {
"id": u'2', "id": u'2',
@ -88,7 +90,9 @@ WORKBOOKS = [
"definition": u'empty', "definition": u'empty',
"tags": [u'mc'], "tags": [u'mc'],
"scope": u'public', "scope": u'public',
"updated_at": None "updated_at": None,
"project_id": '1233',
"trust_id": '12345'
}, },
] ]

View File

View File

@ -0,0 +1,50 @@
# Copyright (c) 2013 Mirantis Inc.
#
# 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 keystoneclient.v3 import client as keystone_client
from oslo.config import cfg
from mistral import context
CONF = cfg.CONF
def client():
ctx = context.current()
auth_url = CONF.keystone_authtoken.auth_uri
keystone = keystone_client.Client(username=ctx['user_name'],
token=ctx['auth_token'],
tenant_id=ctx['project_id'],
auth_url=auth_url)
keystone.management_url = auth_url
return keystone
def client_for_trusts(username, password,
project_name=None,
trust_id=None,
project_id=None):
auth_url = CONF.keystone_authtoken.auth_uri
keystone = keystone_client.Client(username=username,
password=password,
tenant_name=project_name,
tenant_id=project_id,
auth_url=auth_url,
trust_id=trust_id)
keystone.management_url = auth_url
return keystone