Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix hooks in configs not running (#984) #985

Merged
merged 2 commits into from
Sep 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dbt/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def get_hook_dict(hook, index):


def get_hooks(model, hook_key):
hooks = model.get('config', {}).get(hook_key, [])
hooks = model.config.get(hook_key, [])

if not isinstance(hooks, (list, tuple)):
hooks = [hooks]
Expand Down
2 changes: 1 addition & 1 deletion dbt/parser/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def parse_node(cls, node, node_path, root_project_config,
parsed_node.config = config_dict

for hook_type in dbt.hooks.ModelHookType.Both:
parsed_node.config[hook_type] = dbt.hooks.get_hooks(node,
parsed_node.config[hook_type] = dbt.hooks.get_hooks(parsed_node,
hook_type)

parsed_node.validate()
Expand Down
63 changes: 63 additions & 0 deletions test/integration/014_hook_tests/configured-models/hooks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

{{
config({
"pre-hook": "\
insert into {{this.schema}}.on_model_hook (\
\"state\",\
\"target.dbname\",\
\"target.host\",\
\"target.name\",\
\"target.schema\",\
\"target.type\",\
\"target.user\",\
\"target.pass\",\
\"target.port\",\
\"target.threads\",\
\"run_started_at\",\
\"invocation_id\"\
) VALUES (\
'start',\
'{{ target.dbname }}',\
'{{ target.host }}',\
'{{ target.name }}',\
'{{ target.schema }}',\
'{{ target.type }}',\
'{{ target.user }}',\
'{{ target.pass }}',\
{{ target.port }},\
{{ target.threads }},\
'{{ run_started_at }}',\
'{{ invocation_id }}'\
)",
"post-hook": "\
insert into {{this.schema}}.on_model_hook (\
\"state\",\
\"target.dbname\",\
\"target.host\",\
\"target.name\",\
\"target.schema\",\
\"target.type\",\
\"target.user\",\
\"target.pass\",\
\"target.port\",\
\"target.threads\",\
\"run_started_at\",\
\"invocation_id\"\
) VALUES (\
'end',\
'{{ target.dbname }}',\
'{{ target.host }}',\
'{{ target.name }}',\
'{{ target.schema }}',\
'{{ target.type }}',\
'{{ target.user }}',\
'{{ target.pass }}',\
{{ target.port }},\
{{ target.threads }},\
'{{ run_started_at }}',\
'{{ invocation_id }}'\
)"
})
}}

select 3 as id
107 changes: 77 additions & 30 deletions test/integration/014_hook_tests/test_model_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@
)
"""


class TestPrePostModelHooks(DBTIntegrationTest):
class BaseTestPrePost(DBTIntegrationTest):
def setUp(self):
self.adapter_type = 'bigquery'
DBTIntegrationTest.setUp(self)
Expand All @@ -89,6 +88,35 @@ def setUp(self):
def schema(self):
return "model_hooks_014"

def get_ctx_vars(self, state, count):
field_list = ", ".join(['"{}"'.format(f) for f in self.fields])
query = "select {field_list} from {schema}.on_model_hook where state = '{state}'".format(field_list=field_list, schema=self.unique_schema(), state=state)

vals = self.run_sql(query, fetch='all')
self.assertFalse(len(vals) == 0, 'nothing inserted into hooks table')
self.assertFalse(len(vals) < count, 'too few rows in hooks table')
self.assertFalse(len(vals) > count, 'too many rows in hooks table')
return [{k: v for k, v in zip(self.fields, val)} for val in vals]

def check_hooks(self, state, count=1):
ctxs = self.get_ctx_vars(state, count=count)
for ctx in ctxs:
self.assertEqual(ctx['state'], state)
self.assertEqual(ctx['target.dbname'], 'dbt')
self.assertEqual(ctx['target.host'], 'database')
self.assertEqual(ctx['target.name'], 'default2')
self.assertEqual(ctx['target.port'], 5432)
self.assertEqual(ctx['target.schema'], self.unique_schema())
self.assertEqual(ctx['target.threads'], 4)
self.assertEqual(ctx['target.type'], 'postgres')
self.assertEqual(ctx['target.user'], 'root')
self.assertEqual(ctx['target.pass'], '')

self.assertTrue(ctx['run_started_at'] is not None and len(ctx['run_started_at']) > 0, 'run_started_at was not set')
self.assertTrue(ctx['invocation_id'] is not None and len(ctx['invocation_id']) > 0, 'invocation_id was not set')


class TestPrePostModelHooks(BaseTestPrePost):
@property
def project_config(self):
return {
Expand Down Expand Up @@ -118,34 +146,6 @@ def project_config(self):
def models(self):
return "test/integration/014_hook_tests/models"

def get_ctx_vars(self, state):
field_list = ", ".join(['"{}"'.format(f) for f in self.fields])
query = "select {field_list} from {schema}.on_model_hook where state = '{state}'".format(field_list=field_list, schema=self.unique_schema(), state=state)

vals = self.run_sql(query, fetch='all')
self.assertFalse(len(vals) == 0, 'nothing inserted into hooks table')
self.assertFalse(len(vals) > 1, 'too many rows in hooks table')
ctx = dict([(k,v) for (k,v) in zip(self.fields, vals[0])])

return ctx

def check_hooks(self, state):
ctx = self.get_ctx_vars(state)

self.assertEqual(ctx['state'], state)
self.assertEqual(ctx['target.dbname'], 'dbt')
self.assertEqual(ctx['target.host'], 'database')
self.assertEqual(ctx['target.name'], 'default2')
self.assertEqual(ctx['target.port'], 5432)
self.assertEqual(ctx['target.schema'], self.unique_schema())
self.assertEqual(ctx['target.threads'], 4)
self.assertEqual(ctx['target.type'], 'postgres')
self.assertEqual(ctx['target.user'], 'root')
self.assertEqual(ctx['target.pass'], '')

self.assertTrue(ctx['run_started_at'] is not None and len(ctx['run_started_at']) > 0, 'run_started_at was not set')
self.assertTrue(ctx['invocation_id'] is not None and len(ctx['invocation_id']) > 0, 'invocation_id was not set')

@attr(type='postgres')
def test_pre_and_post_model_hooks(self):
self.run_dbt(['run'])
Expand Down Expand Up @@ -183,3 +183,50 @@ def test_hooks_on_seeds(self):
res = self.run_dbt(['test'])
self.assertEqual(len(res), 1, 'Expected exactly one item')


class TestPrePostModelHooksInConfig(BaseTestPrePost):
@property
def project_config(self):
return {
'macro-paths': ['test/integration/014_hook_tests/macros'],
}

@property
def models(self):
return "test/integration/014_hook_tests/configured-models"

@attr(type='postgres')
def test_pre_and_post_model_hooks_model(self):
self.run_dbt(['run'])

self.check_hooks('start')
self.check_hooks('end')

@attr(type='postgres')
def test_pre_and_post_model_hooks_model_and_project(self):
self.use_default_project({
'models': {
'test': {
'pre-hook': [
# inside transaction (runs second)
MODEL_PRE_HOOK,

# outside transaction (runs first)
{"sql": "vacuum {{ this.schema }}.on_model_hook", "transaction": False},
],

'post-hook':[
# outside transaction (runs second)
{"sql": "vacuum {{ this.schema }}.on_model_hook", "transaction": False},

# inside transaction (runs first)
MODEL_POST_HOOK,
]
}
}
})
self.run_dbt(['run'])

self.check_hooks('start', count=2)
self.check_hooks('end', count=2)