You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@jaegwonseo Thanks for logging this and I have been able to replicate it. Basically this means that we cannot extract a BigQuery table to JSON delimited files with the extension .json. As a workaround I think you should be able to extract the table if you don't specify the extension.
This is expected behaviour - the BigQueryInsertJobOperator will treat anything in one of the template fields (configuration, job_id, impersonation_chain, project_id,) ending with .sql, or .json as a reference to a local file, which it will then try to load.
@SamWheating I wonder if it might be possible to prevent the renderer from attempting to load a file for named keys in configuration; in this case destinationUris.
@jaegwonseo Why not give it a try? I think we would still want the filenames in destinationUris to be rendered in case they look something like gs://my-project/my-bucket/{{ ds }}/*.json
I wonder if it might be possible to prevent the renderer from attempting to load a file for named keys in configuration; in this case destinationUris.
I think that this would get pretty complicated pretty fast, as a dict argument like configuration has no enforced structure, so we'd need some jq-like way of indicating which maybe-present fields should and should not be subjected to templating.
Additionally, we'd have to be really specific to only disable this on fields in which we know a user would never ever want to apply this sort of formatting. I think in the case of destinationURI (which accepts a list of URIs) there is a possible use-case for using a .json file rather than an inlined list of strings so I wouldn't want to disable this templating feature for everyone.
I think the simplest case would be to add a feature to disable templating engine - either for all fields or for specific fields or maybe just disable specific extensions. I think we could couple this with something that we should have for quite some time - i.e. ability to dynamically change list of templated fields and template extensions by overriding them in the instance of the task.
There is fundamentally no problem to disable or enable it selectively "per task". It could even be as simple as "template_fields", "template_ext" specified in the constructor of BaseOperator.
Ir's a little bit more complex than just overriding it in classes, it would also have to be overrideable in serialized form of dag - i.e. whe template_fields are rendered in the UI. But I do not think there is anything that would prevent us from doing it.
Also one more suggestion (not sure why I didn't think of this earlier today), I think that this simple fix allows you to selectively disable template fields and extensions on a task-by-task basis - since template_ext is an attribute on the operator class but not exposed in the __init__ method:
I tested it locally and it appeared to work just fine, both at run-time and when displaying the rendered-task-instances in the UI:
With this in mind, is there still need to surface overrides in the __init__ method? Or can we just recommend this as a workaround (and document it as such).
Yeah. Interesting approach.. I can't think of a bad side effect of it - this should not only work for parsing + execution of tasks, but it should also serialize well for the UI and appears to not have unintended side effects.
Appears to be a solution that we never thought of, but was always possible. And it's super-appealing to have a problem that can be solved by documenting it. Let me summon a few people what they think @dstandish@uranusjr@hussein-awala@eladkal - WDYT ?
I find it deceptively simple, but also - quite surprisingly - pretty workable. We had a number of discussions on whether we should make all fields templateable by default etc. but seems that this simple trick might do the job and we could make it "official".
BTW. No wonder @SamWheating you have not thought about it. It seems no-one did for the last few years I was around. I kept on explaining the users how easy it is to just extend existing operators and modify template_fields and template_exts but it never occured to me, that we could modify it in the tasks during dag construction. Apparently - we can.
I have absolutely No objections, even more, I would love that as an "official" way of modifying templated/template_ext fields on-the-flight - as long as we get a few more people say "well, indeed that does not seem to have some side effects" :D
How about LiteralValue?
It appears that I have successfully implemented it (link).
However, the true challenge is in ensuring its clear usage for users.
Activity
nathadfield commentedon Aug 24, 2023
@jaegwonseo Thanks for logging this and I have been able to replicate it. Basically this means that we cannot extract a BigQuery table to JSON delimited files with the extension
.json. As a workaround I think you should be able to extract the table if you don't specify the extension.SamWheating commentedon Aug 24, 2023
This is expected behaviour - the
BigQueryInsertJobOperatorwill treat anything in one of the template fields (configuration,job_id,impersonation_chain,project_id,) ending with.sql, or.jsonas a reference to a local file, which it will then try to load.This is defined here:
airflow/airflow/providers/google/cloud/operators/bigquery.py
Lines 2697 to 2706 in 46fa5a2
I'm not sure if there's a preferred way around this, but I would just subclass the operator and remove the extension:
nathadfield commentedon Aug 24, 2023
@SamWheating I wonder if it might be possible to prevent the renderer from attempting to load a file for named keys in
configuration; in this casedestinationUris.jaegwonseo commentedon Aug 24, 2023
how about add no_template_fields parameter to BaseOperator constructor ?
in this case no_template_fields = (configuration.extract.destinationUris)
and skip rendering from https://github.com/apache/airflow/blob/main/airflow/template/templater.py#L152
nathadfield commentedon Aug 24, 2023
@jaegwonseo Why not give it a try? I think we would still want the filenames in
destinationUristo be rendered in case they look something likegs://my-project/my-bucket/{{ ds }}/*.jsonSamWheating commentedon Aug 24, 2023
I think that this would get pretty complicated pretty fast, as a dict argument like
configurationhas no enforced structure, so we'd need some jq-like way of indicating which maybe-present fields should and should not be subjected to templating.Additionally, we'd have to be really specific to only disable this on fields in which we know a user would never ever want to apply this sort of formatting. I think in the case of
destinationURI(which accepts a list of URIs) there is a possible use-case for using a.jsonfile rather than an inlined list of strings so I wouldn't want to disable this templating feature for everyone.Thoughts?
potiuk commentedon Aug 24, 2023
I think the simplest case would be to add a feature to disable templating engine - either for all fields or for specific fields or maybe just disable specific extensions. I think we could couple this with something that we should have for quite some time - i.e. ability to dynamically change list of templated fields and template extensions by overriding them in the instance of the task.
There is fundamentally no problem to disable or enable it selectively "per task". It could even be as simple as "template_fields", "template_ext" specified in the constructor of BaseOperator.
Ir's a little bit more complex than just overriding it in classes, it would also have to be overrideable in serialized form of dag - i.e. whe template_fields are rendered in the UI. But I do not think there is anything that would prevent us from doing it.
SamWheating commentedon Aug 24, 2023
Also one more suggestion (not sure why I didn't think of this earlier today), I think that this simple fix allows you to selectively disable template fields and extensions on a task-by-task basis - since
template_extis an attribute on the operator class but not exposed in the__init__method:I tested it locally and it appeared to work just fine, both at run-time and when displaying the rendered-task-instances in the UI:
With this in mind, is there still need to surface overrides in the
__init__method? Or can we just recommend this as a workaround (and document it as such).potiuk commentedon Aug 24, 2023
Yeah. Interesting approach.. I can't think of a bad side effect of it - this should not only work for parsing + execution of tasks, but it should also serialize well for the UI and appears to not have unintended side effects.
Appears to be a solution that we never thought of, but was always possible. And it's super-appealing to have a problem that can be solved by documenting it. Let me summon a few people what they think @dstandish @uranusjr @hussein-awala @eladkal - WDYT ?
I find it deceptively simple, but also - quite surprisingly - pretty workable. We had a number of discussions on whether we should make all fields templateable by default etc. but seems that this simple trick might do the job and we could make it "official".
See #33694 (comment) comment by @SamWheating
potiuk commentedon Aug 24, 2023
BTW. No wonder @SamWheating you have not thought about it. It seems no-one did for the last few years I was around. I kept on explaining the users how easy it is to just extend existing operators and modify template_fields and template_exts but it never occured to me, that we could modify it in the tasks during dag construction. Apparently - we can.
SamWheating commentedon Aug 24, 2023
Any objection to just adding this to the documentation as a footnote under the Template Rendering section?
potiuk commentedon Aug 24, 2023
I have absolutely No objections, even more, I would love that as an "official" way of modifying templated/template_ext fields on-the-flight - as long as we get a few more people say "well, indeed that does not seem to have some side effects" :D
eladkal commentedon Aug 25, 2023
Didn't we have the exact same bug when we added json as templated ext for
KubernetesPodOperator?#16922
uranusjr commentedon Sep 6, 2023
Maybe the easiest way out would be to add a
Literallywrapper that disables rendering? So you can writePlease do bikeshed on the name. I’m intentionally avoiding
Literalto avoid confusion withtyping.Literal.potiuk commentedon Sep 7, 2023
I like the idea.
michalsosn commentedon Oct 17, 2023
How about
LiteralValue?It appears that I have successfully implemented it (link).
However, the true challenge is in ensuring its clear usage for users.