Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Build deferred AWS hooks from the operator's own settings by SEPURI-SAI-KRISHNA · Pull Request #72171 · apache/airflow · GitHub
Skip to content

Build deferred AWS hooks from the operator's own settings - #72171

Open
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base
Open

Build deferred AWS hooks from the operator's own settings#72171
SEPURI-SAI-KRISHNA wants to merge 3 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:fix-aws-deferred-hook-config-base

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Addresses the bulk of the deferred hook-configuration gap tracked in #72144.

AwsBaseWaiterTrigger now builds the hook itself, from the parameters it already serializes, driven by an aws_hook_class attribute, the same arrangement AwsBaseHookMixin gives the operators. Subclasses name the hook they need instead of constructing it, so region_name, verify and botocore_config reach the triggerer by default rather than only where a
subclass remembered to thread them through.

That removes 40 bespoke hook() implementations, and takes the provider from 49 of 113 defer sites forwarding the full hook configuration to 110 of 113.

What is deliberately left out

Three services are reserved for the Contributors Workshop, at the request of the workshop organiser on #72144: sensors/batch.py, sensors/opensearch_serverless.py and operators/sagemaker_unified_studio_notebook.py. They are listed in PENDING_MIGRATION in the invariant test, which asserts each entry is still needed, a stale line fails the suite, so the allowlist cannot outlive the work it tracks.

SageMakerNotebookOperator defers to SageMakerNotebookJobTrigger, which is a plain BaseTrigger whose hook is addressed by execution name and takes no connection parameters at all. EksPodOperator defers to EksPodTrigger, a KubernetesPodTrigger that reaches the pod through a kubeconfig rather than a boto3 client. Neither is an instance of this bug; both are named explicitly in the test rather than passed over silently.

Invariant test

test_deferred_hook_configuration.py walks every self.defer(trigger=...) call in the provider and fails if one does not pass the hook configuration, plus asserts every AwsBaseWaiterTrigger subclass can actually build a hook. It resolves a trigger= expression to every construction it can evaluate to, so a trigger chosen in a conditional expression is checked on both branches, that is how the two EmrContainer sites were caught. A defer site whose trigger is a bare reference is asserted against an explicit allowlist rather than skipped. An operator added later that forgets the parameters fails in CI rather than in production.

Notes for review

  • Stacked on Use the operator's AWS settings for deferred Neptune, MWAA, SSM tasks #72098. No file overlaps, but the invariant test asserts every non-allowlisted site forwards the configuration, and 13 of them are fixed by that PR. This should merge after it.
  • aws_hook_class binds the hook at class definition, so the @patch("...triggers.<module>.<Hook>") idiom no longer intercepts it for migrated triggers. No existing test needed changing as a result.
  • EmrContainerTrigger's hook takes an extra virtual_cluster_id, so it overrides _hook_parameters rather than using the default, the escape hatch the base class keeps for exactly this.
  • EksDeleteClusterTrigger bypasses the base __init__ and rolls its own serialize(), so it sets and serializes the two new parameters explicitly.
  • Verified against a full run of the operator, sensor and trigger suites: 2463 passed, 3 skipped, with an identical list of 5 failures and 30 collection errors before and after the change (all missing optional dependencies in the local environment, airflow_shared, common.messaging, openlineage).

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

An AwsBaseOperator/AwsBaseSensor subclass resolves region_name, verify and
botocore_config in __init__, but did not hand them to the trigger it defers
to. The trigger builds its own hook, so the deferred half of the task reached
AWS with the default region, SSL verification silently re-enabled, and any
custom botocore timeouts or retries discarded.
The triggers already accept all three, so only the call sites were missing.
Every Neptune Analytics operator accepts `verify` through the shared AWS
base class, but none of the seven class docstrings mentioned it, so the
rendered provider docs gave users no way to discover it. Two of those
docstrings even carried a stray blank line where the entry belonged.
The deferral tests now compare the trigger's serialized payload rather
than its attributes. Serialization is what actually crosses into the
triggerer process, and it passes values through `prune_dict`, so an
attribute-level assertion can pass while the setting is silently dropped
on the way there. This matches the assertion style already used for the
Neptune cluster operators.
An AWS operator always carries region_name, verify and botocore_config, but
on deferral the trigger builds its own hook. Most triggers accepted none of
those parameters and constructed the hook from aws_conn_id alone, so the
triggerer silently fell back to boto3 defaults: a different region, default
SSL verification, and none of the configured timeouts or retry policy. The
task changed behaviour purely by virtue of deferring, and did so without any
error.
Fixing this service by service would have meant editing every trigger
signature as well as every call site, so the hook is now built in one place
from the parameters the base trigger already serializes. Subclasses name the
hook they need instead of constructing it, which is the same arrangement the
operators use.
The accompanying invariant test walks every defer site in the provider and
fails if one does not hand its hook configuration to the trigger, so an
operator added later cannot reintroduce the gap unnoticed.
Three services are deliberately left for the Contributors Workshop and are
named in the test's allowlist rather than skipped silently.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNAforce-pushed the fix-aws-deferred-hook-config-base branch from 6509b9e to d7f8a6eCompareAugust 31, 2026 07:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providersprovider:amazonAWS/Amazon - related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@SEPURI-SAI-KRISHNA