Add a user creds database table and associate stacks with username.

This patch takes the credentials passed in from the context and allows
you to store them in the database in the 'user_creds' table for later
use with HA operations.  It also adds a 'username' to the stack table
for direct comparison and user validation to support per-user stacks.

Thanks to Angus for fixing the tests for me :)

Signed-off-by: Ian Main <imain@redhat.com>
This commit is contained in:
Ian Main 2012-06-14 17:46:12 -07:00
parent d36d8d38ba
commit b637eef5af
6 changed files with 160 additions and 9 deletions

View File

@ -103,6 +103,10 @@ def stack_get_all(context):
return IMPL.stack_get_all(context)
def stack_get_by_user(context):
return IMPL.stack_get_by_user(context)
def stack_create(context, values):
return IMPL.stack_create(context, values)
@ -111,6 +115,14 @@ def stack_delete(context, stack_name):
return IMPL.stack_delete(context, stack_name)
def user_creds_create(context):
return IMPL.user_creds_create(context)
def user_creds_get(context_id):
return IMPL.user_creds_get(context_id)
def event_get(context, event_id):
return IMPL.event_get(context, event_id)

View File

@ -126,6 +126,9 @@ def resource_get_all_by_stack(context, stack_id):
def stack_get(context, stack_id):
result = model_query(context, models.Stack).\
filter_by(name=stack_id).first()
if result is not None and context is not None and\
result.username != context.username:
return None
return result
@ -134,6 +137,12 @@ def stack_get_all(context):
return results
def stack_get_by_user(context):
results = model_query(context, models.Stack).\
filter_by(username=context.username).all()
return results
def stack_create(context, values):
stack_ref = models.Stack()
stack_ref.update(values)
@ -170,6 +179,20 @@ def stack_delete(context, stack_name):
session.flush()
def user_creds_create(values):
user_creds_ref = models.UserCreds()
user_creds_ref.update(values)
user_creds_ref.save()
return user_creds_ref
def user_creds_get(user_creds_id):
result = model_query(None, models.UserCreds).\
filter_by(id=user_creds_id).first()
return result
def event_get(context, event_id):
result = model_query(context, models.Event).\
filter_by(id=event_id).first()

View File

@ -0,0 +1,68 @@
from sqlalchemy import *
from migrate import *
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
user_creds = Table(
'user_creds', meta,
Column('id', Integer, primary_key=True),
Column('created_at', DateTime(timezone=False)),
Column('updated_at', DateTime(timezone=False)),
Column('username', String(length=255, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('password', String(length=255, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('service_user', String(length=255, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('service_password', String(length=255, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('tenant', String(length=1024, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('auth_url', Text()),
Column('aws_auth_url', Text()),
Column('tenant_id', String(length=256, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)),
Column('aws_creds', Text())
)
try:
user_creds.create()
except Exception:
meta.drop_all(tables=tables)
raise
stack = Table('stack', meta, autoload=True)
Column('username', String(length=256, convert_unicode=False,
assert_unicode=None,
unicode_error=None,
_warn_on_bytestring=False)).create(stack)
Column('user_creds_id', Integer, ForeignKey("user_creds.id"),
nullable=False).create(stack)
def downgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
watch_rule = Table('user_creds', meta, autoload=True)
watch_rule.drop()
stack = Table('stack', meta, autoload=True)
stack.c.username.drop()
stack.c.user_creds_id.drop()

View File

@ -141,6 +141,29 @@ class Stack(BASE, HeatBase):
nullable=False)
raw_template = relationship(RawTemplate,
backref=backref('stack'))
username = Column(String)
user_creds_id = Column(Integer, ForeignKey('user_creds.id'),
nullable=False)
class UserCreds(BASE, HeatBase):
"""
Represents user credentials and mirrors the 'context'
handed in by wsgi.
"""
__tablename__ = 'user_creds'
id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
service_user = Column(String)
service_password = Column(String)
tenant = Column(String)
auth_url = Column(String)
aws_auth_url = Column(String)
tenant_id = Column(String)
aws_creds = Column(String)
class Event(BASE, HeatBase):

View File

@ -118,7 +118,7 @@ class EngineManager(manager.Manager):
self._authenticate(context)
res = {'stacks': []}
stacks = db_api.stack_get_all(None)
stacks = db_api.stack_get_by_user(context)
if stacks is None:
return res
for s in stacks:
@ -146,7 +146,7 @@ class EngineManager(manager.Manager):
self._authenticate(context)
res = {'stacks': []}
s = db_api.stack_get(None, stack_name)
s = db_api.stack_get(context, stack_name)
if s:
ps = parser.Stack(context, s.name,
s.raw_template.parsed_template.template,
@ -212,10 +212,14 @@ class EngineManager(manager.Manager):
rt['stack_name'] = stack_name
new_rt = db_api.raw_template_create(None, rt)
new_creds = db_api.user_creds_create(context.to_dict())
s = {}
s['name'] = stack_name
s['raw_template_id'] = new_rt.id
new_s = db_api.stack_create(None, s)
s['user_creds_id'] = new_creds.id
s['username'] = context.username
new_s = db_api.stack_create(context, s)
stack.id = new_s.id
pt = {}

View File

@ -9,6 +9,7 @@ import sqlalchemy
from nose.plugins.attrib import attr
from nose import with_setup
from heat. common import context
from heat.tests.v1_1 import fakes
from heat.engine import instance as instances
import heat.db as db_api
@ -70,9 +71,14 @@ class stacksTest(unittest.TestCase):
rt['template'] = stack.t
rt['stack_name'] = stack.name
new_rt = db_api.raw_template_create(None, rt)
ct = {'username': 'fred',
'password': 'mentions_fruit'}
new_creds = db_api.user_creds_create(ct)
s = {}
s['name'] = stack.name
s['raw_template_id'] = new_rt.id
s['user_creds_id'] = new_creds.id
s['username'] = ct['username']
new_s = db_api.stack_create(None, s)
stack.id = new_s.id
pt = {}
@ -93,9 +99,14 @@ class stacksTest(unittest.TestCase):
rt['template'] = stack.t
rt['stack_name'] = stack.name
new_rt = db_api.raw_template_create(None, rt)
ct = {'username': 'fred',
'password': 'mentions_fruit'}
new_creds = db_api.user_creds_create(ct)
s = {}
s['name'] = stack.name
s['raw_template_id'] = new_rt.id
s['user_creds_id'] = new_creds.id
s['username'] = ct['username']
new_s = db_api.stack_create(None, s)
stack.id = new_s.id
pt = {}
@ -127,22 +138,32 @@ class stacksTest(unittest.TestCase):
assert(result['ResourceProperties']['InstanceType'] == 'm1.large')
def test_stack_list(self):
self.m.StubOutWithMock(manager.EngineManager, '_authenticate')
manager.EngineManager._authenticate(None).AndReturn(True)
stack = self.start_wordpress_stack('test_stack_list')
rt = {}
rt['template'] = stack.t
rt['stack_name'] = stack.name
new_rt = db_api.raw_template_create(None, rt)
ct = {'username': 'fred',
'password': 'mentions_fruit'}
new_creds = db_api.user_creds_create(ct)
ctx = context.get_admin_context()
self.m.StubOutWithMock(ctx, 'username')
ctx.username = 'fred'
self.m.StubOutWithMock(manager.EngineManager, '_authenticate')
manager.EngineManager._authenticate(ctx).AndReturn(True)
s = {}
s['name'] = stack.name
s['raw_template_id'] = new_rt.id
new_s = db_api.stack_create(None, s)
s['user_creds_id'] = new_creds.id
s['username'] = ct['username']
new_s = db_api.stack_create(ctx, s)
stack.id = new_s.id
pt = {}
pt['template'] = stack.t
pt['raw_template_id'] = new_rt.id
new_pt = db_api.parsed_template_create(None, pt)
new_pt = db_api.parsed_template_create(ctx, pt)
instances.Instance.nova().AndReturn(self.fc)
self.m.ReplayAll()
stack.create_blocking()
@ -152,10 +173,10 @@ class stacksTest(unittest.TestCase):
params = {}
parameters = {}
t['Parameters']['KeyName']['Value'] = 'test'
stack = parser.Stack(None, 'test_stack_list', t, 0, params)
stack = parser.Stack(ctx, 'test_stack_list', t, 0, params)
man = manager.EngineManager()
sl = man.list_stacks(None, params)
sl = man.list_stacks(ctx, params)
assert(len(sl) > 0)
for s in sl['stacks']: