This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 0110b22a60 Fix `ComputeEngineInsertInstanceOperator` doesn't respect
jinja-templated instance name when given in body argument (#34171)
0110b22a60 is described below
commit 0110b22a603f86fbc6f1311ef1c9a23505ca6f87
Author: Aryeh Tiktinsky <[email protected]>
AuthorDate: Mon Sep 11 16:12:50 2023 +0300
Fix `ComputeEngineInsertInstanceOperator` doesn't respect jinja-templated
instance name when given in body argument (#34171)
---
.../providers/google/cloud/operators/compute.py | 4 +
.../google/cloud/operators/test_compute.py | 137 +++++++++++++++++++++
2 files changed, 141 insertions(+)
diff --git a/airflow/providers/google/cloud/operators/compute.py
b/airflow/providers/google/cloud/operators/compute.py
index 8379904f35..b2758e167a 100644
--- a/airflow/providers/google/cloud/operators/compute.py
+++ b/airflow/providers/google/cloud/operators/compute.py
@@ -127,6 +127,7 @@ class
ComputeEngineInsertInstanceOperator(ComputeEngineBaseOperator):
"gcp_conn_id",
"api_version",
"impersonation_chain",
+ "resource_id",
)
# [END gce_instance_insert_fields]
@@ -306,6 +307,7 @@ class
ComputeEngineInsertInstanceFromTemplateOperator(ComputeEngineBaseOperator)
"gcp_conn_id",
"api_version",
"impersonation_chain",
+ "resource_id",
)
# [END gce_instance_insert_from_template_fields]
@@ -869,6 +871,7 @@ class
ComputeEngineInsertInstanceTemplateOperator(ComputeEngineBaseOperator):
"gcp_conn_id",
"api_version",
"impersonation_chain",
+ "resource_id",
)
# [END gce_instance_template_insert_fields]
@@ -1452,6 +1455,7 @@ class
ComputeEngineInsertInstanceGroupManagerOperator(ComputeEngineBaseOperator)
"gcp_conn_id",
"api_version",
"impersonation_chain",
+ "resource_id",
)
# [END gce_igm_insert_fields]
diff --git a/tests/providers/google/cloud/operators/test_compute.py
b/tests/providers/google/cloud/operators/test_compute.py
index 44b57e5eb4..2ad1d5bddd 100644
--- a/tests/providers/google/cloud/operators/test_compute.py
+++ b/tests/providers/google/cloud/operators/test_compute.py
@@ -247,6 +247,41 @@ class TestGceInstanceInsert:
op.execute(context=mock.MagicMock())
mock_hook.assert_not_called()
+ @mock.patch(COMPUTE_ENGINE_HOOK_PATH)
+ def test_insert_instance_should_not_throw_ex_when_name_is_templated(self,
mock_hook):
+ get_instance_obj_mock = mock.MagicMock()
+ get_instance_obj_mock.__class__ = Instance
+ mock_hook.return_value.get_instance.side_effect = [
+ NotFound("Error message"),
+ get_instance_obj_mock,
+ ]
+ body_with_templated_name = deepcopy(GCE_INSTANCE_BODY_API_CALL)
+ body_with_templated_name["name"] = "{{ execution_date }}"
+ op = ComputeEngineInsertInstanceOperator(
+ project_id=GCP_PROJECT_ID,
+ resource_id=GCE_RESOURCE_ID,
+ body=body_with_templated_name,
+ zone=GCE_ZONE,
+ task_id=TASK_ID,
+ retry=RETRY,
+ timeout=TIMEOUT,
+ metadata=METADATA,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ op.execute(context=mock.MagicMock())
+ mock_hook.assert_called_once_with(
+ api_version=API_VERSION,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ mock_hook.return_value.insert_instance.assert_called_once_with(
+ project_id=GCP_PROJECT_ID,
+ body=body_with_templated_name,
+ zone=GCE_ZONE,
+ request_id=None,
+ )
+
class TestGceInstanceInsertFromTemplate:
@mock.patch(COMPUTE_ENGINE_HOOK_PATH)
@@ -400,6 +435,42 @@ class TestGceInstanceInsertFromTemplate:
op.execute(context=mock.MagicMock())
mock_hook.assert_not_called()
+ @mock.patch(COMPUTE_ENGINE_HOOK_PATH)
+ def
test_insert_instance_from_template_should_not_throw_ex_when_name_is_templated(self,
mock_hook):
+ get_instance_obj_mock = mock.MagicMock()
+ get_instance_obj_mock.__class__ = Instance
+ mock_hook.return_value.get_instance.side_effect = [
+ NotFound("Error message"),
+ get_instance_obj_mock,
+ ]
+ body_with_templated_name = deepcopy(GCP_INSTANCE_BODY_FROM_TEMPLATE)
+ body_with_templated_name["name"] = "{{ execution_date }}"
+ op = ComputeEngineInsertInstanceFromTemplateOperator(
+ project_id=GCP_PROJECT_ID,
+ source_instance_template=SOURCE_INSTANCE_TEMPLATE,
+ body=body_with_templated_name,
+ zone=GCE_ZONE,
+ task_id=TASK_ID,
+ retry=RETRY,
+ timeout=TIMEOUT,
+ metadata=METADATA,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ op.execute(context=mock.MagicMock())
+ mock_hook.assert_called_once_with(
+ api_version=API_VERSION,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ mock_hook.return_value.insert_instance.assert_called_once_with(
+ project_id=GCP_PROJECT_ID,
+ zone=GCE_ZONE,
+ body=body_with_templated_name,
+ source_instance_template=SOURCE_INSTANCE_TEMPLATE,
+ request_id=None,
+ )
+
class TestGceInstanceDelete:
@mock.patch(COMPUTE_ENGINE_HOOK_PATH)
@@ -962,6 +1033,38 @@ class TestGceTemplateInsert:
op.execute(context=mock.MagicMock())
mock_hook.assert_not_called()
+ @mock.patch(COMPUTE_ENGINE_HOOK_PATH)
+ def test_insert_template_should_not_throw_ex_when_name_is_templated(self,
mock_hook):
+ get_template_obj_mock = mock.MagicMock()
+ get_template_obj_mock.__class__ = InstanceTemplate
+ mock_hook.return_value.get_instance_template.side_effect = [
+ NotFound("Error message"),
+ get_template_obj_mock,
+ ]
+ body_with_templated_name =
deepcopy(GCE_INSTANCE_TEMPLATE_BODY_API_CALL)
+ body_with_templated_name["name"] = "{{ execution_date }}"
+ op = ComputeEngineInsertInstanceTemplateOperator(
+ project_id=GCP_PROJECT_ID,
+ body=body_with_templated_name,
+ task_id=TASK_ID,
+ retry=RETRY,
+ timeout=TIMEOUT,
+ metadata=METADATA,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ op.execute(context=mock.MagicMock())
+ mock_hook.assert_called_once_with(
+ api_version=API_VERSION,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+
mock_hook.return_value.insert_instance_template.assert_called_once_with(
+ project_id=GCP_PROJECT_ID,
+ body=body_with_templated_name,
+ request_id=None,
+ )
+
class TestGceTemplateDelete:
@mock.patch(COMPUTE_ENGINE_HOOK_PATH)
@@ -1598,6 +1701,40 @@ class TestGceInstanceGroupManagerInsert:
op.execute(context=get_instance_group_manager_obj_mock)
mock_hook.assert_not_called()
+ @mock.patch(COMPUTE_ENGINE_HOOK_PATH)
+ def test_insert_igm_should_not_throw_ex_when_name_is_templated(self,
mock_hook):
+ get_instance_group_manager_obj_mock = mock.MagicMock()
+ get_instance_group_manager_obj_mock.__class__ = InstanceGroupManager
+ mock_hook.return_value.get_instance_group_manager.side_effect = [
+ NotFound("Error message"),
+ get_instance_group_manager_obj_mock,
+ ]
+ body_with_templated_name =
deepcopy(GCE_INSTANCE_GROUP_MANAGER_BODY_API_CALL)
+ body_with_templated_name["name"] = "{{ execution_date }}"
+ op = ComputeEngineInsertInstanceGroupManagerOperator(
+ project_id=GCP_PROJECT_ID,
+ body=body_with_templated_name,
+ zone=GCE_ZONE,
+ task_id=TASK_ID,
+ retry=RETRY,
+ timeout=TIMEOUT,
+ metadata=METADATA,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+ op.execute(context=mock.MagicMock())
+ mock_hook.assert_called_once_with(
+ api_version=API_VERSION,
+ gcp_conn_id=GCP_CONN_ID,
+ impersonation_chain=IMPERSONATION_CHAIN,
+ )
+
mock_hook.return_value.insert_instance_group_manager.assert_called_once_with(
+ project_id=GCP_PROJECT_ID,
+ zone=GCE_ZONE,
+ body=body_with_templated_name,
+ request_id=None,
+ )
+
class TestGceInstanceGroupManagerDelete:
@mock.patch(COMPUTE_ENGINE_HOOK_PATH)