Move CLI logic into redash.cli and uses manager for tests.

Otherwise the Flask wasn't created and tests were failing.
This commit is contained in:
Arik Fraimovich 2016-12-07 14:58:33 +02:00
parent b9024b18c1
commit a84c3e25f5
3 changed files with 119 additions and 129 deletions

View File

@ -2,75 +2,8 @@
"""
CLI to manage redash.
"""
import json
import click
from flask.cli import FlaskGroup, run_command
from redash import create_app, settings, __version__
from redash.cli import users, groups, database, data_sources, organization
from redash.monitor import get_status
def create(group):
app = create_app()
group.app = app
return app
@click.group(cls=FlaskGroup, create_app=create)
def manager():
"Management script for redash"
manager.add_command(database.manager, "database")
manager.add_command(users.manager, "users")
manager.add_command(groups.manager, "groups")
manager.add_command(data_sources.manager, "ds")
manager.add_command(organization.manager, "org")
manager.add_command(run_command, "runserver")
@manager.command()
def version():
"""Displays re:dash version."""
print __version__
@manager.command()
def status():
print json.dumps(get_status(), indent=2)
@manager.command()
def runworkers():
"""Start workers (deprecated)."""
print "** This command is deprecated. Please use Celery's CLI to control the workers. **"
@manager.command()
def check_settings():
"""Show the settings as re:dash sees them (useful for debugging)."""
for name, item in settings.all_settings().iteritems():
print "{} = {}".format(name, item)
@manager.command()
@click.argument('email', default=settings.MAIL_DEFAULT_SENDER, required=False)
def send_test_mail(email=None):
"""
Send test message to EMAIL (default: the address you defined in MAIL_DEFAULT_SENDER)
"""
from redash import mail
from flask_mail import Message
if email is None:
email = settings.MAIL_DEFAULT_SENDER
mail.send(Message(subject="Test Message from re:dash", recipients=[email],
body="Test message."))
from redash.cli import manager
if __name__ == '__main__':
manager()

View File

@ -0,0 +1,63 @@
import json
import click
from flask.cli import FlaskGroup, run_command
from redash import create_app, settings, __version__
from redash.cli import users, groups, database, data_sources, organization
from redash.monitor import get_status
def create(group):
app = create_app()
group.app = app
return app
@click.group(cls=FlaskGroup, create_app=create)
def manager():
"""Management script for Redash"""
manager.add_command(database.manager, "database")
manager.add_command(users.manager, "users")
manager.add_command(groups.manager, "groups")
manager.add_command(data_sources.manager, "ds")
manager.add_command(organization.manager, "org")
manager.add_command(run_command, "runserver")
@manager.command()
def version():
"""Displays Redash version."""
print __version__
@manager.command()
def status():
print json.dumps(get_status(), indent=2)
@manager.command()
def check_settings():
"""Show the settings as Redash sees them (useful for debugging)."""
for name, item in settings.all_settings().iteritems():
print "{} = {}".format(name, item)
@manager.command()
@click.argument('email', default=settings.MAIL_DEFAULT_SENDER, required=False)
def send_test_mail(email=None):
"""
Send test message to EMAIL (default: the address you defined in MAIL_DEFAULT_SENDER)
"""
from redash import mail
from flask_mail import Message
if email is None:
email = settings.MAIL_DEFAULT_SENDER
mail.send(Message(subject="Test Message from Redash", recipients=[email],
body="Test message."))

View File

@ -6,14 +6,15 @@ import mock
from tests import BaseTestCase
from redash.utils.configuration import ConfigurationContainer
from redash.query_runner import query_runners
from redash.cli.data_sources import (edit, delete as delete_ds,
list as list_ds, new, test)
from redash.cli.groups import (change_permissions, create as create_group,
list as list_group)
from redash.cli.organization import (list as list_org, set_google_apps_domains,
show_google_apps_domains)
from redash.cli.users import (create as create_user, delete as delete_user,
grant_admin, invite, list as list_user, password)
# from redash.cli.data_sources import (edit, delete as delete_ds,
# list as list_ds, new, test)
# from redash.cli.groups import (change_permissions, create as create_group,
# list as list_group)
# from redash.cli.organization import (list as list_org, set_google_apps_domains,
# show_google_apps_domains)
# from redash.cli.users import (create as create_user, delete as delete_user,
# grant_admin, invite, list as list_user, password)
from redash.cli import manager
from redash.models import DataSource, Group, Organization, User, db
@ -22,7 +23,8 @@ class DataSourceCommandTests(BaseTestCase):
runner = CliRunner()
pg_i = query_runners.keys().index('pg') + 1
result = runner.invoke(
new,
manager,
['ds', 'new'],
input="test\n%s\n\n\nexample.com\n\ntestdb\n" % (pg_i,))
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
@ -35,9 +37,11 @@ class DataSourceCommandTests(BaseTestCase):
def test_options_new(self):
runner = CliRunner()
result = runner.invoke(
new, ['test', '--options',
'{"host": "example.com", "dbname": "testdb"}',
'--type', 'pg'])
manager,
['ds', 'new',
'test',
'--options', '{"host": "example.com", "dbname": "testdb"}',
'--type', 'pg'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertEqual(DataSource.query.count(), 1)
@ -50,7 +54,7 @@ class DataSourceCommandTests(BaseTestCase):
def test_bad_type_new(self):
runner = CliRunner()
result = runner.invoke(
new, ['test', '--type', 'wrong'])
manager, ['ds', 'new', 'test', '--type', 'wrong'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('not supported', result.output)
@ -59,9 +63,9 @@ class DataSourceCommandTests(BaseTestCase):
def test_bad_options_new(self):
runner = CliRunner()
result = runner.invoke(
new, ['test', '--options',
'{"host": 12345, "dbname": "testdb"}',
'--type', 'pg'])
manager, ['ds', 'new', 'test', '--options',
'{"host": 12345, "dbname": "testdb"}',
'--type', 'pg'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('invalid configuration', result.output)
@ -76,7 +80,7 @@ class DataSourceCommandTests(BaseTestCase):
name='test2', type='sqlite',
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(list_ds)
result = runner.invoke(manager, ['ds', 'list'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
expected_output = """
@ -98,7 +102,7 @@ class DataSourceCommandTests(BaseTestCase):
name='test1', type='sqlite',
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(test, ['test1'])
result = runner.invoke(manager, ['ds', 'test', 'test1'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertIn('Success', result.output)
@ -108,7 +112,7 @@ class DataSourceCommandTests(BaseTestCase):
name='test1', type='sqlite',
options=ConfigurationContainer({"dbpath": __file__}))
runner = CliRunner()
result = runner.invoke(test, ['test1'])
result = runner.invoke(manager, ['ds', 'test', 'test1'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('Failure', result.output)
@ -118,7 +122,7 @@ class DataSourceCommandTests(BaseTestCase):
name='test1', type='sqlite',
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(delete_ds, ['test1'])
result = runner.invoke(manager, ['ds', 'delete', 'test1'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertIn('Deleting', result.output)
@ -129,7 +133,7 @@ class DataSourceCommandTests(BaseTestCase):
name='test1', type='sqlite',
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(delete_ds, ['wrong'])
result = runner.invoke(manager, ['ds', 'delete', 'wrong'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn("Couldn't find", result.output)
@ -141,10 +145,10 @@ class DataSourceCommandTests(BaseTestCase):
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(
edit, ['test1', '--options',
'{"host": "example.com", "dbname": "testdb"}',
'--name', 'test2',
'--type', 'pg'])
manager, ['ds', 'edit', 'test1', '--options',
'{"host": "example.com", "dbname": "testdb"}',
'--name', 'test2',
'--type', 'pg'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertEqual(DataSource.query.count(), 1)
@ -160,7 +164,7 @@ class DataSourceCommandTests(BaseTestCase):
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(
edit, ['test', '--type', 'wrong'])
manager, ['ds', 'edit', 'test', '--type', 'wrong'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('not supported', result.output)
@ -173,9 +177,9 @@ class DataSourceCommandTests(BaseTestCase):
options=ConfigurationContainer({"dbpath": "/tmp/test.db"}))
runner = CliRunner()
result = runner.invoke(
new, ['test', '--options',
'{"host": 12345, "dbname": "testdb"}',
'--type', 'pg'])
manager, ['ds', 'new', 'test', '--options',
'{"host": 12345, "dbname": "testdb"}',
'--type', 'pg'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('invalid configuration', result.output)
@ -185,13 +189,12 @@ class DataSourceCommandTests(BaseTestCase):
class GroupCommandTests(BaseTestCase):
def test_create(self):
gcount = Group.query.count()
perms = ['create_query', 'edit_query', 'view_query']
runner = CliRunner()
result = runner.invoke(
create_group, ['test', '--permissions', ','.join(perms)])
manager, ['groups', 'create', 'test', '--permissions', ','.join(perms)])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertEqual(Group.query.count(), gcount + 1)
@ -206,7 +209,7 @@ class GroupCommandTests(BaseTestCase):
perms = ['create_query', 'edit_query', 'view_query']
runner = CliRunner()
result = runner.invoke(
change_permissions, [str(g_id), '--permissions', ','.join(perms)])
manager, ['groups', 'change_permissions', str(g_id), '--permissions', ','.join(perms)])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
g = Group.query.filter(Group.id == g_id).first()
@ -215,7 +218,7 @@ class GroupCommandTests(BaseTestCase):
def test_list(self):
self.factory.create_group(name='test', permissions=['list_dashboards'])
runner = CliRunner()
result = runner.invoke(list_group, [])
result = runner.invoke(manager, ['groups', 'list'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
output = """
@ -242,10 +245,10 @@ class OrganizationCommandTests(BaseTestCase):
def test_set_google_apps_domains(self):
domains = ['example.org', 'example.com']
runner = CliRunner()
result = runner.invoke(set_google_apps_domains, [','.join(domains)])
result = runner.invoke(manager, ['org', 'set_google_apps_domains', ','.join(domains)])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
#db.session.
# db.session.
db.session.refresh(self.factory.org)
self.assertEqual(self.factory.org.google_apps_domains, domains)
@ -255,7 +258,7 @@ class OrganizationCommandTests(BaseTestCase):
db.session.add(self.factory.org)
db.session.commit()
runner = CliRunner()
result = runner.invoke(show_google_apps_domains, [])
result = runner.invoke(manager, ['org', 'show_google_apps_domains'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
output = """
@ -267,7 +270,7 @@ class OrganizationCommandTests(BaseTestCase):
def test_list(self):
self.factory.create_org(name='test', slug='test_org')
runner = CliRunner()
result = runner.invoke(list_org, [])
result = runner.invoke(manager, ['org', 'list'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
output = """
@ -287,7 +290,7 @@ class UserCommandTests(BaseTestCase):
def test_create_basic(self):
runner = CliRunner()
result = runner.invoke(
create_user, ['foobar@example.com', 'Fred Foobar'],
manager, ['users', 'create', 'foobar@example.com', 'Fred Foobar'],
input="password1\npassword1\n")
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
@ -299,20 +302,20 @@ class UserCommandTests(BaseTestCase):
def test_create_admin(self):
runner = CliRunner()
result = runner.invoke(
create_user, ['foobar@example.com', 'Fred Foobar',
'--password', 'password1', '--admin'])
manager, ['users', 'create', 'foobar@example.com', 'Fred Foobar',
'--password', 'password1', '--admin'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
u = User.query.filter(User.email == "foobar@example.com").first()
self.assertEqual(u.name, "Fred Foobar")
self.assertTrue(u.verify_password('password1'))
self.assertEqual(u.group_ids, [self.factory.default_group.id,
self.factory.admin_group.id])
self.factory.admin_group.id])
def test_create_googleauth(self):
runner = CliRunner()
result = runner.invoke(
create_user, ['foobar@example.com', 'Fred Foobar', '--google'])
manager, ['users', 'create', 'foobar@example.com', 'Fred Foobar', '--google'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
u = User.query.filter(User.email == "foobar@example.com").first()
@ -324,7 +327,7 @@ class UserCommandTests(BaseTestCase):
self.factory.create_user(email='foobar@example.com')
runner = CliRunner()
result = runner.invoke(
create_user, ['foobar@example.com', 'Fred Foobar'],
manager, ['users', 'create' 'foobar@example.com', 'Fred Foobar'],
input="password1\npassword1\n")
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
@ -334,27 +337,24 @@ class UserCommandTests(BaseTestCase):
self.factory.create_user(email='foobar@example.com')
ucount = User.query.count()
runner = CliRunner()
result = runner.invoke(
delete_user, ['foobar@example.com'])
result = runner.invoke(manager, ['users', 'delete', 'foobar@example.com'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertEqual(User.query.filter(User.email ==
"foobar@example.com").count(), 0)
"foobar@example.com").count(), 0)
self.assertEqual(User.query.count(), ucount - 1)
def test_delete_bad(self):
ucount = User.query.count()
runner = CliRunner()
result = runner.invoke(
delete_user, ['foobar@example.com'])
result = runner.invoke(manager, ['users', 'delete', 'foobar@example.com'])
self.assertIn('Deleted 0 users', result.output)
self.assertEqual(User.query.count(), ucount)
def test_password(self):
self.factory.create_user(email='foobar@example.com')
runner = CliRunner()
result = runner.invoke(
password, ['foobar@example.com', 'xyzzy'])
result = runner.invoke(manager, ['users', 'password', 'foobar@example.com', 'xyzzy'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
u = User.query.filter(User.email == "foobar@example.com").first()
@ -362,16 +362,14 @@ class UserCommandTests(BaseTestCase):
def test_password_bad(self):
runner = CliRunner()
result = runner.invoke(
password, ['foobar@example.com', 'xyzzy'])
result = runner.invoke(manager, ['users', 'password', 'foobar@example.com', 'xyzzy'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('not found', result.output)
def test_password_bad_org(self):
runner = CliRunner()
result = runner.invoke(
password, ['foobar@example.com', 'xyzzy', '--org', 'default'])
result = runner.invoke(manager, ['users', 'password', 'foobar@example.com', 'xyzzy', '--org', 'default'])
self.assertTrue(result.exception)
self.assertEqual(result.exit_code, 1)
self.assertIn('not found', result.output)
@ -380,9 +378,7 @@ class UserCommandTests(BaseTestCase):
admin = self.factory.create_user(email='redash-admin@example.com')
runner = CliRunner()
with mock.patch('redash.cli.users.invite_user') as iu:
result = runner.invoke(
invite, ['foobar@example.com', 'Fred Foobar',
'redash-admin@example.com'])
result = runner.invoke(manager, ['users', 'invite', 'foobar@example.com', 'Fred Foobar', 'redash-admin@example.com'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
self.assertTrue(iu.called)
@ -391,13 +387,12 @@ class UserCommandTests(BaseTestCase):
self.assertEqual(c[1].id, admin.id)
self.assertEqual(c[2].email, 'foobar@example.com')
def test_list(self):
self.factory.create_user(name='Fred Foobar',
email='foobar@example.com',
org=self.factory.org)
runner = CliRunner()
result = runner.invoke(list_user, [])
result = runner.invoke(manager, ['users', 'list'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
output = """
@ -415,8 +410,7 @@ class UserCommandTests(BaseTestCase):
org=self.factory.org,
group_ids=[self.factory.default_group.id])
runner = CliRunner()
result = runner.invoke(
grant_admin, ['foobar@example.com'])
result = runner.invoke(manager, ['users', 'grant_admin', 'foobar@example.com'])
self.assertFalse(result.exception)
self.assertEqual(result.exit_code, 0)
db.session.refresh(u)