From e5144e476abe33838b1cca5a129938735c6730b9 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Sat, 12 Nov 2022 15:34:56 +0530 Subject: [PATCH 01/11] Changing atlassian JIRA SDK to official atlassian-python-api SDK --- .../atlassian/{jira => }/CHANGELOG.rst | 0 .../atlassian/{jira => }/hooks/__init__.py | 0 .../atlassian/{jira => }/hooks/jira.py | 51 ++++++++++--------- airflow/providers/atlassian/jira/__init__.py | 12 +++++ .../{jira => }/operators/__init__.py | 0 .../atlassian/{jira => }/operators/jira.py | 15 ++---- .../atlassian/{jira => }/provider.yaml | 10 ++-- .../atlassian/{jira => }/sensors/__init__.py | 0 .../atlassian/{jira => }/sensors/jira.py | 25 ++++----- .../atlassian/{jira => hooks}/__init__.py | 0 .../atlassian/{jira => }/hooks/test_jira.py | 4 +- .../atlassian/jira/sensors/__init__.py | 16 ------ .../{jira/hooks => operators}/__init__.py | 0 .../{jira => }/operators/test_jira.py | 22 ++++---- .../{jira/operators => sensors}/__init__.py | 0 .../atlassian/{jira => }/sensors/test_jira.py | 30 ++++------- 16 files changed, 84 insertions(+), 101 deletions(-) rename airflow/providers/atlassian/{jira => }/CHANGELOG.rst (100%) rename airflow/providers/atlassian/{jira => }/hooks/__init__.py (100%) rename airflow/providers/atlassian/{jira => }/hooks/jira.py (66%) rename airflow/providers/atlassian/{jira => }/operators/__init__.py (100%) rename airflow/providers/atlassian/{jira => }/operators/jira.py (81%) rename airflow/providers/atlassian/{jira => }/provider.yaml (85%) rename airflow/providers/atlassian/{jira => }/sensors/__init__.py (100%) rename airflow/providers/atlassian/{jira => }/sensors/jira.py (83%) rename tests/providers/atlassian/{jira => hooks}/__init__.py (100%) rename tests/providers/atlassian/{jira => }/hooks/test_jira.py (92%) delete mode 100644 tests/providers/atlassian/jira/sensors/__init__.py rename tests/providers/atlassian/{jira/hooks => operators}/__init__.py (100%) rename tests/providers/atlassian/{jira => }/operators/test_jira.py (77%) rename tests/providers/atlassian/{jira/operators => sensors}/__init__.py (100%) rename tests/providers/atlassian/{jira => }/sensors/test_jira.py (80%) diff --git a/airflow/providers/atlassian/jira/CHANGELOG.rst b/airflow/providers/atlassian/CHANGELOG.rst similarity index 100% rename from airflow/providers/atlassian/jira/CHANGELOG.rst rename to airflow/providers/atlassian/CHANGELOG.rst diff --git a/airflow/providers/atlassian/jira/hooks/__init__.py b/airflow/providers/atlassian/hooks/__init__.py similarity index 100% rename from airflow/providers/atlassian/jira/hooks/__init__.py rename to airflow/providers/atlassian/hooks/__init__.py diff --git a/airflow/providers/atlassian/jira/hooks/jira.py b/airflow/providers/atlassian/hooks/jira.py similarity index 66% rename from airflow/providers/atlassian/jira/hooks/jira.py rename to airflow/providers/atlassian/hooks/jira.py index 7ce1a9e80a16a..2f1409b180cba 100644 --- a/airflow/providers/atlassian/jira/hooks/jira.py +++ b/airflow/providers/atlassian/hooks/jira.py @@ -18,10 +18,10 @@ """Hook for JIRA""" from __future__ import annotations +import warnings from typing import Any -from jira import JIRA -from jira.exceptions import JIRAError +from atlassian import Jira from airflow.exceptions import AirflowException from airflow.hooks.base import BaseHook @@ -29,7 +29,7 @@ class JiraHook(BaseHook): """ - Jira interaction hook, a Wrapper around JIRA Python SDK. + Jira interaction hook, a Wrapper around Atlassian Jira Python SDK. :param jira_conn_id: reference to a pre-defined Jira Connection """ @@ -43,16 +43,14 @@ def __init__(self, jira_conn_id: str = default_conn_name, proxies: Any | None = super().__init__() self.jira_conn_id = jira_conn_id self.proxies = proxies - self.client: JIRA | None = None + self.client: Jira | None = None self.get_conn() - def get_conn(self) -> JIRA: + def get_conn(self) -> Jira: if not self.client: self.log.debug("Creating Jira client for conn_id: %s", self.jira_conn_id) - get_server_info = True - validate = True - extra_options = {} + verify = True if not self.jira_conn_id: raise AirflowException("Failed to create jira client. no jira_conn_id provided") @@ -60,31 +58,36 @@ def get_conn(self) -> JIRA: if conn.extra is not None: extra_options = conn.extra_dejson # only required attributes are taken for now, - # more can be added ex: async, logging, max_retries + # more can be added ex: timeout, cloud, session # verify if "verify" in extra_options and extra_options["verify"].lower() == "false": - extra_options["verify"] = False + verify = False # validate - if "validate" in extra_options and extra_options["validate"].lower() == "false": - validate = False - - if "get_server_info" in extra_options and extra_options["get_server_info"].lower() == "false": - get_server_info = False + if "validate" in extra_options: + warnings.warn( + f"Passing 'validate' in the connection is no longer supported.", + DeprecationWarning, + stacklevel=2, + ) + + if "get_server_info" in extra_options: + warnings.warn( + f"Passing 'get_server_info' in the connection is no longer supported.", + DeprecationWarning, + stacklevel=2, + ) try: - self.client = JIRA( - conn.host, - options=extra_options, - basic_auth=(conn.login, conn.password), - get_server_info=get_server_info, - validate=validate, + self.client = Jira( + url=conn.host, + username=conn.login, + password=conn.password, + verify_ssl=verify, proxies=self.proxies, ) - except JIRAError as jira_error: + except Exception as jira_error: raise AirflowException(f"Failed to create jira client, jira error: {str(jira_error)}") - except Exception as e: - raise AirflowException(f"Failed to create jira client, error: {str(e)}") return self.client diff --git a/airflow/providers/atlassian/jira/__init__.py b/airflow/providers/atlassian/jira/__init__.py index 13a83393a9124..2220730a90cd9 100644 --- a/airflow/providers/atlassian/jira/__init__.py +++ b/airflow/providers/atlassian/jira/__init__.py @@ -14,3 +14,15 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +"""This module is deprecated. Please use :mod:`airflow.providers.atlassian.operators.jira`.""" +from __future__ import annotations + +import warnings + +from airflow.providers.atlassian.operators.jira import JiraOperator # noqa + +warnings.warn( + "This module is deprecated. Please use `airflow.providers.atlassian.operators.jira`.", + DeprecationWarning, + stacklevel=2, +) diff --git a/airflow/providers/atlassian/jira/operators/__init__.py b/airflow/providers/atlassian/operators/__init__.py similarity index 100% rename from airflow/providers/atlassian/jira/operators/__init__.py rename to airflow/providers/atlassian/operators/__init__.py diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/operators/jira.py similarity index 81% rename from airflow/providers/atlassian/jira/operators/jira.py rename to airflow/providers/atlassian/operators/jira.py index b1fe7bb05cd65..b8954f1d501da 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/operators/jira.py @@ -21,7 +21,7 @@ from airflow.exceptions import AirflowException from airflow.models import BaseOperator -from airflow.providers.atlassian.jira.hooks.jira import JIRAError, JiraHook +from airflow.providers.atlassian.hooks.jira import JiraHook if TYPE_CHECKING: from airflow.utils.context import Context @@ -30,10 +30,10 @@ class JiraOperator(BaseOperator): """ JiraOperator to interact and perform action on Jira issue tracking system. - This operator is designed to use Jira Python SDK: http://jira.readthedocs.io + This operator is designed to use Atlassian Python SDK: https://atlassian-python-api.readthedocs.io/jira.html :param jira_conn_id: reference to a pre-defined Jira Connection - :param jira_method: method name from Jira Python SDK to be called + :param jira_method: method name from Atlassian Jira Python SDK to be called :param jira_method_args: required method parameters for the jira_method. (templated) :param result_processor: function to further process the response from Jira :param get_jira_resource_method: function or operator to get jira resource @@ -64,9 +64,9 @@ def execute(self, context: Context) -> Any: if self.get_jira_resource_method is not None: # if get_jira_resource_method is provided, jira_method will be executed on # resource returned by executing the get_jira_resource_method. - # This makes all the provided methods of JIRA sdk accessible and usable + # This makes all the provided methods of atlassian-python-api JIRA sdk accessible and usable # directly at the JiraOperator without additional wrappers. - # ref: http://jira.readthedocs.io/en/latest/api.html + # ref: https://atlassian-python-api.readthedocs.io/jira.html if isinstance(self.get_jira_resource_method, JiraOperator): resource = self.get_jira_resource_method.execute(**context) else: @@ -76,16 +76,11 @@ def execute(self, context: Context) -> Any: hook = JiraHook(jira_conn_id=self.jira_conn_id) resource = hook.client - # Current Jira-Python SDK (1.0.7) has issue with pickling the jira response. - # ex: self.xcom_push(context, key='operator_response', value=jira_response) - # This could potentially throw error if jira_result is not picklable jira_result = getattr(resource, self.method_name)(**self.jira_method_args) if self.result_processor: return self.result_processor(context, jira_result) return jira_result - except JIRAError as jira_error: - raise AirflowException(f"Failed to execute jiraOperator, error: {str(jira_error)}") except Exception as e: raise AirflowException(f"Jira operator error: {str(e)}") diff --git a/airflow/providers/atlassian/jira/provider.yaml b/airflow/providers/atlassian/provider.yaml similarity index 85% rename from airflow/providers/atlassian/jira/provider.yaml rename to airflow/providers/atlassian/provider.yaml index 3e68f29ec4bd8..0cd99a3be0b95 100644 --- a/airflow/providers/atlassian/jira/provider.yaml +++ b/airflow/providers/atlassian/provider.yaml @@ -27,7 +27,7 @@ versions: dependencies: - apache-airflow>=2.3.0 - - JIRA>1.0.7 + - atlassian-python-api>=1.14.2 integrations: - integration-name: Atlassian Jira @@ -38,18 +38,18 @@ integrations: operators: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.jira.operators.jira + - airflow.providers.atlassian.operators.jira sensors: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.jira.sensors.jira + - airflow.providers.atlassian.sensors.jira hooks: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.jira.hooks.jira + - airflow.providers.atlassian.hooks.jira connection-types: - - hook-class-name: airflow.providers.atlassian.jira.hooks.jira.JiraHook + - hook-class-name: airflow.providers.atlassian.hooks.jira.JiraHook connection-type: jira diff --git a/airflow/providers/atlassian/jira/sensors/__init__.py b/airflow/providers/atlassian/sensors/__init__.py similarity index 100% rename from airflow/providers/atlassian/jira/sensors/__init__.py rename to airflow/providers/atlassian/sensors/__init__.py diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/sensors/jira.py similarity index 83% rename from airflow/providers/atlassian/jira/sensors/jira.py rename to airflow/providers/atlassian/sensors/jira.py index cd3af90dab2ae..55544c11f6930 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/sensors/jira.py @@ -19,10 +19,7 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence -from jira.resources import Issue, Resource - -from airflow.providers.atlassian.jira.hooks.jira import JiraHook -from airflow.providers.atlassian.jira.operators.jira import JIRAError +from airflow.providers.atlassian.hooks.jira import JiraHook from airflow.sensors.base import BaseSensorOperator if TYPE_CHECKING: @@ -34,7 +31,7 @@ class JiraSensor(BaseSensorOperator): Monitors a jira ticket for any change. :param jira_conn_id: reference to a pre-defined Jira Connection - :param method_name: method name from jira-python-sdk to be execute + :param method_name: method name from atlassian-python-api jira-sdk to execute :param method_params: parameters for the method method_name :param result_processor: function that return boolean and act as a sensor response """ @@ -96,29 +93,31 @@ def __init__( if field_checker_func is None: field_checker_func = self.issue_field_checker - super().__init__(jira_conn_id=jira_conn_id, result_processor=field_checker_func, **kwargs) + super().__init__( + jira_conn_id=jira_conn_id, method_name="issue", result_processor=field_checker_func, **kwargs + ) def poke(self, context: Context) -> Any: self.log.info("Jira Sensor checking for change in ticket: %s", self.ticket_id) self.method_name = "issue" - self.method_params = {"id": self.ticket_id, "fields": self.field} + self.method_params = {"key": self.ticket_id, "fields": self.field} return JiraSensor.poke(self, context=context) - def issue_field_checker(self, issue: Issue) -> bool | None: + def issue_field_checker(self, jira_result: dict) -> bool | None: """Check issue using different conditions to prepare to evaluate sensor.""" result = None try: - if issue is not None and self.field is not None and self.expected_value is not None: + if jira_result is not None and self.field is not None and self.expected_value is not None: - field_val = getattr(issue.fields, self.field) + field_val = jira_result.get("fields", {}).get(self.field, None) if field_val is not None: if isinstance(field_val, list): result = self.expected_value in field_val elif isinstance(field_val, str): result = self.expected_value.lower() == field_val.lower() - elif isinstance(field_val, Resource) and getattr(field_val, "name"): - result = self.expected_value.lower() == field_val.name.lower() + elif isinstance(field_val, dict) and field_val.get("name", None): + result = self.expected_value.lower() == field_val.get("name").lower() else: self.log.warning( "Not implemented checker for issue field %s which " @@ -126,8 +125,6 @@ def issue_field_checker(self, issue: Issue) -> bool | None: self.field, ) - except JIRAError as jira_error: - self.log.error("Jira error while checking with expected value: %s", jira_error) except Exception: self.log.exception("Error while checking with expected value %s:", self.expected_value) if result is True: diff --git a/tests/providers/atlassian/jira/__init__.py b/tests/providers/atlassian/hooks/__init__.py similarity index 100% rename from tests/providers/atlassian/jira/__init__.py rename to tests/providers/atlassian/hooks/__init__.py diff --git a/tests/providers/atlassian/jira/hooks/test_jira.py b/tests/providers/atlassian/hooks/test_jira.py similarity index 92% rename from tests/providers/atlassian/jira/hooks/test_jira.py rename to tests/providers/atlassian/hooks/test_jira.py index a8069357b4555..dd8e86bea7adc 100644 --- a/tests/providers/atlassian/jira/hooks/test_jira.py +++ b/tests/providers/atlassian/hooks/test_jira.py @@ -20,7 +20,7 @@ from unittest.mock import Mock, patch from airflow.models import Connection -from airflow.providers.atlassian.jira.hooks.jira import JiraHook +from airflow.providers.atlassian.hooks.jira import JiraHook from airflow.utils import db jira_client_mock = Mock(name="jira_client") @@ -38,7 +38,7 @@ def setup_method(self): ) ) - @patch("airflow.providers.atlassian.jira.hooks.jira.JIRA", autospec=True, return_value=jira_client_mock) + @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True, return_value=jira_client_mock) def test_jira_client_connection(self, jira_mock): jira_hook = JiraHook() diff --git a/tests/providers/atlassian/jira/sensors/__init__.py b/tests/providers/atlassian/jira/sensors/__init__.py deleted file mode 100644 index 13a83393a9124..0000000000000 --- a/tests/providers/atlassian/jira/sensors/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. diff --git a/tests/providers/atlassian/jira/hooks/__init__.py b/tests/providers/atlassian/operators/__init__.py similarity index 100% rename from tests/providers/atlassian/jira/hooks/__init__.py rename to tests/providers/atlassian/operators/__init__.py diff --git a/tests/providers/atlassian/jira/operators/test_jira.py b/tests/providers/atlassian/operators/test_jira.py similarity index 77% rename from tests/providers/atlassian/jira/operators/test_jira.py rename to tests/providers/atlassian/operators/test_jira.py index 76db8a7d692c2..f11c4035e5227 100644 --- a/tests/providers/atlassian/jira/operators/test_jira.py +++ b/tests/providers/atlassian/operators/test_jira.py @@ -21,7 +21,7 @@ from airflow.models import Connection from airflow.models.dag import DAG -from airflow.providers.atlassian.jira.operators.jira import JiraOperator +from airflow.providers.atlassian.operators.jira import JiraOperator from airflow.utils import db, timezone DEFAULT_DATE = timezone.datetime(2017, 1, 1) @@ -53,35 +53,35 @@ def setup_method(self): ) ) - @patch("airflow.providers.atlassian.jira.hooks.jira.JIRA", autospec=True, return_value=jira_client_mock) + @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True, return_value=jira_client_mock) def test_issue_search(self, jira_mock): jql_str = "issuekey=TEST-1226" - jira_mock.return_value.search_issues.return_value = minimal_test_ticket + jira_mock.return_value.jql_get_list_of_tickets.return_value = minimal_test_ticket jira_ticket_search_operator = JiraOperator( task_id="search-ticket-test", - jira_method="search_issues", - jira_method_args={"jql_str": jql_str, "maxResults": "1"}, + jira_method="jql_get_list_of_tickets", + jira_method_args={"jql": jql_str, "limit": "1"}, dag=self.dag, ) jira_ticket_search_operator.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE, ignore_ti_state=True) assert jira_mock.called - assert jira_mock.return_value.search_issues.called + assert jira_mock.return_value.jql_get_list_of_tickets.called - @patch("airflow.providers.atlassian.jira.hooks.jira.JIRA", autospec=True, return_value=jira_client_mock) + @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True, return_value=jira_client_mock) def test_update_issue(self, jira_mock): - jira_mock.return_value.add_comment.return_value = True + jira_mock.return_value.issue_add_comment.return_value = True add_comment_operator = JiraOperator( task_id="add_comment_test", - jira_method="add_comment", - jira_method_args={"issue": minimal_test_ticket.get("key"), "body": "this is test comment"}, + jira_method="issue_add_comment", + jira_method_args={"issue_key": minimal_test_ticket.get("key"), "comment": "this is test comment"}, dag=self.dag, ) add_comment_operator.run(start_date=DEFAULT_DATE, end_date=DEFAULT_DATE, ignore_ti_state=True) assert jira_mock.called - assert jira_mock.return_value.add_comment.called + assert jira_mock.return_value.issue_add_comment.called diff --git a/tests/providers/atlassian/jira/operators/__init__.py b/tests/providers/atlassian/sensors/__init__.py similarity index 100% rename from tests/providers/atlassian/jira/operators/__init__.py rename to tests/providers/atlassian/sensors/__init__.py diff --git a/tests/providers/atlassian/jira/sensors/test_jira.py b/tests/providers/atlassian/sensors/test_jira.py similarity index 80% rename from tests/providers/atlassian/jira/sensors/test_jira.py rename to tests/providers/atlassian/sensors/test_jira.py index ecd63ab3acb7b..011ed4f325588 100644 --- a/tests/providers/atlassian/jira/sensors/test_jira.py +++ b/tests/providers/atlassian/sensors/test_jira.py @@ -21,28 +21,21 @@ from airflow.models import Connection from airflow.models.dag import DAG -from airflow.providers.atlassian.jira.sensors.jira import JiraTicketSensor +from airflow.providers.atlassian.sensors.jira import JiraTicketSensor from airflow.utils import db, timezone DEFAULT_DATE = timezone.datetime(2017, 1, 1) jira_client_mock = Mock(name="jira_client_for_test") - -class _MockJiraTicket(dict): - class _TicketFields: - labels = ["test-label-1", "test-label-2"] - description = "this is a test description" - - fields = _TicketFields - - -minimal_test_ticket = _MockJiraTicket( - { - "id": "911539", - "self": "https://sandbox.localhost/jira/rest/api/2/issue/911539", - "key": "TEST-1226", - } -) +minimal_test_ticket = { + "id": "911539", + "self": "https://sandbox.localhost/jira/rest/api/2/issue/911539", + "key": "TEST-1226", + "fields": { + "labels": ["test-label-1", "test-label-2"], + "description": "this is a test description", + }, +} class TestJiraSensor: @@ -60,12 +53,11 @@ def setup_method(self): ) ) - @patch("airflow.providers.atlassian.jira.hooks.jira.JIRA", autospec=True, return_value=jira_client_mock) + @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True, return_value=jira_client_mock) def test_issue_label_set(self, jira_mock): jira_mock.return_value.issue.return_value = minimal_test_ticket ticket_label_sensor = JiraTicketSensor( - method_name="issue", task_id="search-ticket-test", ticket_id="TEST-1226", field="labels", From df350120e1f9d5e8618bd8a8e9dbb986c8af6389 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Sat, 12 Nov 2022 16:23:29 +0530 Subject: [PATCH 02/11] Changing atlassian JIRA SDK to official atlassian-python-api SDK --- .../providers/atlassian/{ => jira}/CHANGELOG.rst | 0 airflow/providers/atlassian/jira/__init__.py | 12 ------------ .../atlassian/{ => jira}/hooks/__init__.py | 0 .../providers/atlassian/{ => jira}/hooks/jira.py | 4 ++-- .../atlassian/{ => jira}/operators/__init__.py | 0 .../atlassian/{ => jira}/operators/jira.py | 4 ++-- .../providers/atlassian/{ => jira}/provider.yaml | 8 ++++---- .../atlassian/{ => jira}/sensors/__init__.py | 0 .../atlassian/{ => jira}/sensors/jira.py | 4 ++-- .../atlassian/{hooks => jira}/__init__.py | 0 .../{operators => jira/hooks}/__init__.py | 0 .../atlassian/{ => jira}/hooks/test_jira.py | 2 +- .../{sensors => jira/operators}/__init__.py | 0 .../atlassian/{ => jira}/operators/test_jira.py | 2 +- .../providers/atlassian/jira/sensors/__init__.py | 16 ++++++++++++++++ .../atlassian/{ => jira}/sensors/test_jira.py | 2 +- 16 files changed, 29 insertions(+), 25 deletions(-) rename airflow/providers/atlassian/{ => jira}/CHANGELOG.rst (100%) rename airflow/providers/atlassian/{ => jira}/hooks/__init__.py (100%) rename airflow/providers/atlassian/{ => jira}/hooks/jira.py (94%) rename airflow/providers/atlassian/{ => jira}/operators/__init__.py (100%) rename airflow/providers/atlassian/{ => jira}/operators/jira.py (95%) rename airflow/providers/atlassian/{ => jira}/provider.yaml (86%) rename airflow/providers/atlassian/{ => jira}/sensors/__init__.py (100%) rename airflow/providers/atlassian/{ => jira}/sensors/jira.py (98%) rename tests/providers/atlassian/{hooks => jira}/__init__.py (100%) rename tests/providers/atlassian/{operators => jira/hooks}/__init__.py (100%) rename tests/providers/atlassian/{ => jira}/hooks/test_jira.py (96%) rename tests/providers/atlassian/{sensors => jira/operators}/__init__.py (100%) rename tests/providers/atlassian/{ => jira}/operators/test_jira.py (97%) create mode 100644 tests/providers/atlassian/jira/sensors/__init__.py rename tests/providers/atlassian/{ => jira}/sensors/test_jira.py (97%) diff --git a/airflow/providers/atlassian/CHANGELOG.rst b/airflow/providers/atlassian/jira/CHANGELOG.rst similarity index 100% rename from airflow/providers/atlassian/CHANGELOG.rst rename to airflow/providers/atlassian/jira/CHANGELOG.rst diff --git a/airflow/providers/atlassian/jira/__init__.py b/airflow/providers/atlassian/jira/__init__.py index 2220730a90cd9..13a83393a9124 100644 --- a/airflow/providers/atlassian/jira/__init__.py +++ b/airflow/providers/atlassian/jira/__init__.py @@ -14,15 +14,3 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -"""This module is deprecated. Please use :mod:`airflow.providers.atlassian.operators.jira`.""" -from __future__ import annotations - -import warnings - -from airflow.providers.atlassian.operators.jira import JiraOperator # noqa - -warnings.warn( - "This module is deprecated. Please use `airflow.providers.atlassian.operators.jira`.", - DeprecationWarning, - stacklevel=2, -) diff --git a/airflow/providers/atlassian/hooks/__init__.py b/airflow/providers/atlassian/jira/hooks/__init__.py similarity index 100% rename from airflow/providers/atlassian/hooks/__init__.py rename to airflow/providers/atlassian/jira/hooks/__init__.py diff --git a/airflow/providers/atlassian/hooks/jira.py b/airflow/providers/atlassian/jira/hooks/jira.py similarity index 94% rename from airflow/providers/atlassian/hooks/jira.py rename to airflow/providers/atlassian/jira/hooks/jira.py index 2f1409b180cba..de5a2fbc38c7f 100644 --- a/airflow/providers/atlassian/hooks/jira.py +++ b/airflow/providers/atlassian/jira/hooks/jira.py @@ -67,14 +67,14 @@ def get_conn(self) -> Jira: # validate if "validate" in extra_options: warnings.warn( - f"Passing 'validate' in the connection is no longer supported.", + "Passing 'validate' in the connection is no longer supported.", DeprecationWarning, stacklevel=2, ) if "get_server_info" in extra_options: warnings.warn( - f"Passing 'get_server_info' in the connection is no longer supported.", + "Passing 'get_server_info' in the connection is no longer supported.", DeprecationWarning, stacklevel=2, ) diff --git a/airflow/providers/atlassian/operators/__init__.py b/airflow/providers/atlassian/jira/operators/__init__.py similarity index 100% rename from airflow/providers/atlassian/operators/__init__.py rename to airflow/providers/atlassian/jira/operators/__init__.py diff --git a/airflow/providers/atlassian/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py similarity index 95% rename from airflow/providers/atlassian/operators/jira.py rename to airflow/providers/atlassian/jira/operators/jira.py index b8954f1d501da..c1852cbbf779e 100644 --- a/airflow/providers/atlassian/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -21,7 +21,7 @@ from airflow.exceptions import AirflowException from airflow.models import BaseOperator -from airflow.providers.atlassian.hooks.jira import JiraHook +from airflow.providers.atlassian.jira.hooks.jira import JiraHook if TYPE_CHECKING: from airflow.utils.context import Context @@ -30,7 +30,7 @@ class JiraOperator(BaseOperator): """ JiraOperator to interact and perform action on Jira issue tracking system. - This operator is designed to use Atlassian Python SDK: https://atlassian-python-api.readthedocs.io/jira.html + This operator is designed to use Atlassian Jira SDK: https://atlassian-python-api.readthedocs.io/jira.html :param jira_conn_id: reference to a pre-defined Jira Connection :param jira_method: method name from Atlassian Jira Python SDK to be called diff --git a/airflow/providers/atlassian/provider.yaml b/airflow/providers/atlassian/jira/provider.yaml similarity index 86% rename from airflow/providers/atlassian/provider.yaml rename to airflow/providers/atlassian/jira/provider.yaml index 0cd99a3be0b95..5650668fdc0eb 100644 --- a/airflow/providers/atlassian/provider.yaml +++ b/airflow/providers/atlassian/jira/provider.yaml @@ -38,18 +38,18 @@ integrations: operators: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.operators.jira + - airflow.providers.atlassian.jira.operators.jira sensors: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.sensors.jira + - airflow.providers.atlassian.jira.sensors.jira hooks: - integration-name: Atlassian Jira python-modules: - - airflow.providers.atlassian.hooks.jira + - airflow.providers.atlassian.jira.hooks.jira connection-types: - - hook-class-name: airflow.providers.atlassian.hooks.jira.JiraHook + - hook-class-name: airflow.providers.atlassian.jira.hooks.jira.JiraHook connection-type: jira diff --git a/airflow/providers/atlassian/sensors/__init__.py b/airflow/providers/atlassian/jira/sensors/__init__.py similarity index 100% rename from airflow/providers/atlassian/sensors/__init__.py rename to airflow/providers/atlassian/jira/sensors/__init__.py diff --git a/airflow/providers/atlassian/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py similarity index 98% rename from airflow/providers/atlassian/sensors/jira.py rename to airflow/providers/atlassian/jira/sensors/jira.py index 55544c11f6930..be3c7691bd81e 100644 --- a/airflow/providers/atlassian/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence -from airflow.providers.atlassian.hooks.jira import JiraHook +from airflow.providers.atlassian.jira.hooks.jira import JiraHook from airflow.sensors.base import BaseSensorOperator if TYPE_CHECKING: @@ -117,7 +117,7 @@ def issue_field_checker(self, jira_result: dict) -> bool | None: elif isinstance(field_val, str): result = self.expected_value.lower() == field_val.lower() elif isinstance(field_val, dict) and field_val.get("name", None): - result = self.expected_value.lower() == field_val.get("name").lower() + result = self.expected_value.lower() == field_val.get("name", "").lower() else: self.log.warning( "Not implemented checker for issue field %s which " diff --git a/tests/providers/atlassian/hooks/__init__.py b/tests/providers/atlassian/jira/__init__.py similarity index 100% rename from tests/providers/atlassian/hooks/__init__.py rename to tests/providers/atlassian/jira/__init__.py diff --git a/tests/providers/atlassian/operators/__init__.py b/tests/providers/atlassian/jira/hooks/__init__.py similarity index 100% rename from tests/providers/atlassian/operators/__init__.py rename to tests/providers/atlassian/jira/hooks/__init__.py diff --git a/tests/providers/atlassian/hooks/test_jira.py b/tests/providers/atlassian/jira/hooks/test_jira.py similarity index 96% rename from tests/providers/atlassian/hooks/test_jira.py rename to tests/providers/atlassian/jira/hooks/test_jira.py index dd8e86bea7adc..3039218afc4a7 100644 --- a/tests/providers/atlassian/hooks/test_jira.py +++ b/tests/providers/atlassian/jira/hooks/test_jira.py @@ -20,7 +20,7 @@ from unittest.mock import Mock, patch from airflow.models import Connection -from airflow.providers.atlassian.hooks.jira import JiraHook +from airflow.providers.atlassian.jira.hooks.jira import JiraHook from airflow.utils import db jira_client_mock = Mock(name="jira_client") diff --git a/tests/providers/atlassian/sensors/__init__.py b/tests/providers/atlassian/jira/operators/__init__.py similarity index 100% rename from tests/providers/atlassian/sensors/__init__.py rename to tests/providers/atlassian/jira/operators/__init__.py diff --git a/tests/providers/atlassian/operators/test_jira.py b/tests/providers/atlassian/jira/operators/test_jira.py similarity index 97% rename from tests/providers/atlassian/operators/test_jira.py rename to tests/providers/atlassian/jira/operators/test_jira.py index f11c4035e5227..4ee36c138dd69 100644 --- a/tests/providers/atlassian/operators/test_jira.py +++ b/tests/providers/atlassian/jira/operators/test_jira.py @@ -21,7 +21,7 @@ from airflow.models import Connection from airflow.models.dag import DAG -from airflow.providers.atlassian.operators.jira import JiraOperator +from airflow.providers.atlassian.jira.operators.jira import JiraOperator from airflow.utils import db, timezone DEFAULT_DATE = timezone.datetime(2017, 1, 1) diff --git a/tests/providers/atlassian/jira/sensors/__init__.py b/tests/providers/atlassian/jira/sensors/__init__.py new file mode 100644 index 0000000000000..13a83393a9124 --- /dev/null +++ b/tests/providers/atlassian/jira/sensors/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/tests/providers/atlassian/sensors/test_jira.py b/tests/providers/atlassian/jira/sensors/test_jira.py similarity index 97% rename from tests/providers/atlassian/sensors/test_jira.py rename to tests/providers/atlassian/jira/sensors/test_jira.py index 011ed4f325588..f845f72f31c79 100644 --- a/tests/providers/atlassian/sensors/test_jira.py +++ b/tests/providers/atlassian/jira/sensors/test_jira.py @@ -21,7 +21,7 @@ from airflow.models import Connection from airflow.models.dag import DAG -from airflow.providers.atlassian.sensors.jira import JiraTicketSensor +from airflow.providers.atlassian.jira.sensors.jira import JiraTicketSensor from airflow.utils import db, timezone DEFAULT_DATE = timezone.datetime(2017, 1, 1) From c2ee023e7b56fe367d839287325cdeffcd0db26e Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Sat, 12 Nov 2022 16:44:00 +0530 Subject: [PATCH 03/11] Adding generated files for breeze and dependencies --- generated/provider_dependencies.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generated/provider_dependencies.json b/generated/provider_dependencies.json index 178af7b20d095..8bffac0888542 100644 --- a/generated/provider_dependencies.json +++ b/generated/provider_dependencies.json @@ -168,8 +168,8 @@ }, "atlassian.jira": { "deps": [ - "JIRA>1.0.7", - "apache-airflow>=2.3.0" + "apache-airflow>=2.3.0", + "atlassian-python-api>=1.14.2" ], "cross-providers-deps": [] }, From 35fb2fab82e2665de1943b764902c87b401e8faf Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Sat, 12 Nov 2022 21:47:28 +0530 Subject: [PATCH 04/11] Fix documentation in jira.py --- airflow/providers/atlassian/jira/sensors/jira.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py index be3c7691bd81e..e793dcfe3eb5e 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -31,7 +31,7 @@ class JiraSensor(BaseSensorOperator): Monitors a jira ticket for any change. :param jira_conn_id: reference to a pre-defined Jira Connection - :param method_name: method name from atlassian-python-api jira-sdk to execute + :param method_name: method name from atlassian-python-api JIRA sdk to execute :param method_params: parameters for the method method_name :param result_processor: function that return boolean and act as a sensor response """ From 5031ad6e12a26e5dd1468394665473b9847cce26 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Thu, 1 Dec 2022 00:53:50 +0530 Subject: [PATCH 05/11] Fixes in atlassian jira provider --- .../providers/atlassian/jira/hooks/jira.py | 33 ++++--------------- .../atlassian/jira/operators/jira.py | 12 +++++-- .../providers/atlassian/jira/sensors/jira.py | 6 ++-- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/airflow/providers/atlassian/jira/hooks/jira.py b/airflow/providers/atlassian/jira/hooks/jira.py index de5a2fbc38c7f..8286483ca6611 100644 --- a/airflow/providers/atlassian/jira/hooks/jira.py +++ b/airflow/providers/atlassian/jira/hooks/jira.py @@ -18,7 +18,6 @@ """Hook for JIRA""" from __future__ import annotations -import warnings from typing import Any from atlassian import Jira @@ -64,30 +63,12 @@ def get_conn(self) -> Jira: if "verify" in extra_options and extra_options["verify"].lower() == "false": verify = False - # validate - if "validate" in extra_options: - warnings.warn( - "Passing 'validate' in the connection is no longer supported.", - DeprecationWarning, - stacklevel=2, - ) - - if "get_server_info" in extra_options: - warnings.warn( - "Passing 'get_server_info' in the connection is no longer supported.", - DeprecationWarning, - stacklevel=2, - ) - - try: - self.client = Jira( - url=conn.host, - username=conn.login, - password=conn.password, - verify_ssl=verify, - proxies=self.proxies, - ) - except Exception as jira_error: - raise AirflowException(f"Failed to create jira client, jira error: {str(jira_error)}") + self.client = Jira( + url=conn.host, + username=conn.login, + password=conn.password, + verify_ssl=verify, + proxies=self.proxies, + ) return self.client diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py index c1852cbbf779e..2fbc6456cee81 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -17,8 +17,11 @@ # under the License. from __future__ import annotations +import json from typing import TYPE_CHECKING, Any, Callable, Sequence +from requests import HTTPError + from airflow.exceptions import AirflowException from airflow.models import BaseOperator from airflow.providers.atlassian.jira.hooks.jira import JiraHook @@ -77,10 +80,13 @@ def execute(self, context: Context) -> Any: resource = hook.client jira_result = getattr(resource, self.method_name)(**self.jira_method_args) + + output = json.loads(jira_result["id"]) if "id" in jira_result else None + self.xcom_push(context, key="id", value=output) + if self.result_processor: return self.result_processor(context, jira_result) return jira_result - - except Exception as e: - raise AirflowException(f"Jira operator error: {str(e)}") + except HTTPError as e: + raise AirflowException(f"Failed to execute jiraOperator, error: {str(e.response)}") diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py index e793dcfe3eb5e..c890c284ed5a5 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -19,6 +19,8 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence +from requests import HTTPError + from airflow.providers.atlassian.jira.hooks.jira import JiraHook from airflow.sensors.base import BaseSensorOperator @@ -125,8 +127,8 @@ def issue_field_checker(self, jira_result: dict) -> bool | None: self.field, ) - except Exception: - self.log.exception("Error while checking with expected value %s:", self.expected_value) + except HTTPError as e: + self.log.error("Jira error while checking with expected value, error: %s", e.response) if result is True: self.log.info( "Issue field %s has expected value %s, returning success", self.field, self.expected_value From 8e2ba9536b27a8e3ff0eb26a54627ce4a8e3c051 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Sun, 4 Dec 2022 20:22:52 +0530 Subject: [PATCH 06/11] Updating Jira provider CHANGELOG.rst --- airflow/providers/atlassian/jira/CHANGELOG.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/airflow/providers/atlassian/jira/CHANGELOG.rst b/airflow/providers/atlassian/jira/CHANGELOG.rst index e316872b87bfb..fc12fc0dd3be3 100644 --- a/airflow/providers/atlassian/jira/CHANGELOG.rst +++ b/airflow/providers/atlassian/jira/CHANGELOG.rst @@ -24,6 +24,23 @@ Changelog --------- +2.0.0 +..... + +Breaking changes +~~~~~~~~~~~~~~~~ + +* ``Changing atlassian JIRA SDK to official atlassian-python-api SDK (#27633)`` + +Migrated ``Jira`` provider from Atlassian ``Jira`` SDK to ``atlassian-python-api`` SDK. +``Jira`` provider doesn't support ``validate`` and ``get_server_info`` in connection extra dict. +Changed the return type of ``JiraHook.get_conn`` to return an ``atlassian.Jira`` object instead of a ``jira.Jira`` object. + +.. warning:: Due to the underlying SDK change, the ``JiraOperator`` now requires ``jira_method`` and ``jira_method_args`` + arguments as per ``atlassian-python-api``. + + Please refer `Atlassian Python API Documentation `__ + 1.1.0 ..... From 4338b14124b19ac584fb3165e1aef499aa37ffb7 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Mon, 5 Dec 2022 01:20:00 +0530 Subject: [PATCH 07/11] Fix tests --- airflow/providers/atlassian/jira/operators/jira.py | 3 +-- tests/providers/atlassian/jira/operators/test_jira.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py index 2fbc6456cee81..99f2abf3bdad4 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -17,7 +17,6 @@ # under the License. from __future__ import annotations -import json from typing import TYPE_CHECKING, Any, Callable, Sequence from requests import HTTPError @@ -81,7 +80,7 @@ def execute(self, context: Context) -> Any: jira_result = getattr(resource, self.method_name)(**self.jira_method_args) - output = json.loads(jira_result["id"]) if "id" in jira_result else None + output = jira_result.get("id", None) if jira_result is not None else None self.xcom_push(context, key="id", value=output) if self.result_processor: diff --git a/tests/providers/atlassian/jira/operators/test_jira.py b/tests/providers/atlassian/jira/operators/test_jira.py index 4ee36c138dd69..cd348ccdf69d9 100644 --- a/tests/providers/atlassian/jira/operators/test_jira.py +++ b/tests/providers/atlassian/jira/operators/test_jira.py @@ -72,7 +72,7 @@ def test_issue_search(self, jira_mock): @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True, return_value=jira_client_mock) def test_update_issue(self, jira_mock): - jira_mock.return_value.issue_add_comment.return_value = True + jira_mock.return_value.issue_add_comment.return_value = minimal_test_ticket add_comment_operator = JiraOperator( task_id="add_comment_test", From 968af29ef5a3769ee5c5ccb8c9abc6d61f752060 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Mon, 5 Dec 2022 15:39:38 +0530 Subject: [PATCH 08/11] Removing try-except block from operators and sensor file in jira --- .../atlassian/jira/operators/jira.py | 41 +++++++++---------- .../providers/atlassian/jira/sensors/jira.py | 37 ++++++++--------- 2 files changed, 36 insertions(+), 42 deletions(-) diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py index 99f2abf3bdad4..8afeee037269a 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -62,30 +62,27 @@ def __init__( self.get_jira_resource_method = get_jira_resource_method def execute(self, context: Context) -> Any: - try: - if self.get_jira_resource_method is not None: - # if get_jira_resource_method is provided, jira_method will be executed on - # resource returned by executing the get_jira_resource_method. - # This makes all the provided methods of atlassian-python-api JIRA sdk accessible and usable - # directly at the JiraOperator without additional wrappers. - # ref: https://atlassian-python-api.readthedocs.io/jira.html - if isinstance(self.get_jira_resource_method, JiraOperator): - resource = self.get_jira_resource_method.execute(**context) - else: - resource = self.get_jira_resource_method(**context) + if self.get_jira_resource_method is not None: + # if get_jira_resource_method is provided, jira_method will be executed on + # resource returned by executing the get_jira_resource_method. + # This makes all the provided methods of atlassian-python-api JIRA sdk accessible and usable + # directly at the JiraOperator without additional wrappers. + # ref: https://atlassian-python-api.readthedocs.io/jira.html + if isinstance(self.get_jira_resource_method, JiraOperator): + resource = self.get_jira_resource_method.execute(**context) else: - # Default method execution is on the top level jira client resource - hook = JiraHook(jira_conn_id=self.jira_conn_id) - resource = hook.client + resource = self.get_jira_resource_method(**context) + else: + # Default method execution is on the top level jira client resource + hook = JiraHook(jira_conn_id=self.jira_conn_id) + resource = hook.client - jira_result = getattr(resource, self.method_name)(**self.jira_method_args) + jira_result = getattr(resource, self.method_name)(**self.jira_method_args) - output = jira_result.get("id", None) if jira_result is not None else None - self.xcom_push(context, key="id", value=output) + output = jira_result.get("id", None) if jira_result is not None else None + self.xcom_push(context, key="id", value=output) - if self.result_processor: - return self.result_processor(context, jira_result) + if self.result_processor: + return self.result_processor(context, jira_result) - return jira_result - except HTTPError as e: - raise AirflowException(f"Failed to execute jiraOperator, error: {str(e.response)}") + return jira_result diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py index c890c284ed5a5..49deff30788fb 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -109,26 +109,23 @@ def poke(self, context: Context) -> Any: def issue_field_checker(self, jira_result: dict) -> bool | None: """Check issue using different conditions to prepare to evaluate sensor.""" result = None - try: - if jira_result is not None and self.field is not None and self.expected_value is not None: - - field_val = jira_result.get("fields", {}).get(self.field, None) - if field_val is not None: - if isinstance(field_val, list): - result = self.expected_value in field_val - elif isinstance(field_val, str): - result = self.expected_value.lower() == field_val.lower() - elif isinstance(field_val, dict) and field_val.get("name", None): - result = self.expected_value.lower() == field_val.get("name", "").lower() - else: - self.log.warning( - "Not implemented checker for issue field %s which " - "is neither string nor list nor Jira Resource", - self.field, - ) - - except HTTPError as e: - self.log.error("Jira error while checking with expected value, error: %s", e.response) + if jira_result is not None and self.field is not None and self.expected_value is not None: + + field_val = jira_result.get("fields", {}).get(self.field, None) + if field_val is not None: + if isinstance(field_val, list): + result = self.expected_value in field_val + elif isinstance(field_val, str): + result = self.expected_value.lower() == field_val.lower() + elif isinstance(field_val, dict) and field_val.get("name", None): + result = self.expected_value.lower() == field_val.get("name", "").lower() + else: + self.log.warning( + "Not implemented checker for issue field %s which " + "is neither string nor list nor Jira Resource", + self.field, + ) + if result is True: self.log.info( "Issue field %s has expected value %s, returning success", self.field, self.expected_value From 50743a56cd4cf25b2d1b8c1138ca84999b1dba41 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Mon, 5 Dec 2022 15:39:57 +0530 Subject: [PATCH 09/11] Removing try-except block from operators and sensor file in jira --- airflow/providers/atlassian/jira/operators/jira.py | 2 -- airflow/providers/atlassian/jira/sensors/jira.py | 1 - 2 files changed, 3 deletions(-) diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py index 8afeee037269a..16b802b660b50 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -19,9 +19,7 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence -from requests import HTTPError -from airflow.exceptions import AirflowException from airflow.models import BaseOperator from airflow.providers.atlassian.jira.hooks.jira import JiraHook diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py index 49deff30788fb..4b3a9d89b36c0 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -19,7 +19,6 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence -from requests import HTTPError from airflow.providers.atlassian.jira.hooks.jira import JiraHook from airflow.sensors.base import BaseSensorOperator From c990eb6cd6c2687d229de5235383f56ad1e5b817 Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Mon, 5 Dec 2022 17:46:56 +0530 Subject: [PATCH 10/11] Fix static checks --- airflow/providers/atlassian/jira/operators/jira.py | 1 - airflow/providers/atlassian/jira/sensors/jira.py | 1 - 2 files changed, 2 deletions(-) diff --git a/airflow/providers/atlassian/jira/operators/jira.py b/airflow/providers/atlassian/jira/operators/jira.py index 16b802b660b50..b5fcb46a9f47a 100644 --- a/airflow/providers/atlassian/jira/operators/jira.py +++ b/airflow/providers/atlassian/jira/operators/jira.py @@ -19,7 +19,6 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence - from airflow.models import BaseOperator from airflow.providers.atlassian.jira.hooks.jira import JiraHook diff --git a/airflow/providers/atlassian/jira/sensors/jira.py b/airflow/providers/atlassian/jira/sensors/jira.py index 4b3a9d89b36c0..a6ed22e0de4e4 100644 --- a/airflow/providers/atlassian/jira/sensors/jira.py +++ b/airflow/providers/atlassian/jira/sensors/jira.py @@ -19,7 +19,6 @@ from typing import TYPE_CHECKING, Any, Callable, Sequence - from airflow.providers.atlassian.jira.hooks.jira import JiraHook from airflow.sensors.base import BaseSensorOperator From 166212b3ee75aaefc473640b849b804af7e4142b Mon Sep 17 00:00:00 2001 From: Aditya Malik Date: Tue, 6 Dec 2022 18:05:22 +0530 Subject: [PATCH 11/11] Adding 2.0.0 version in jira provider.yaml --- airflow/providers/atlassian/jira/provider.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/airflow/providers/atlassian/jira/provider.yaml b/airflow/providers/atlassian/jira/provider.yaml index 5650668fdc0eb..78130d41e7544 100644 --- a/airflow/providers/atlassian/jira/provider.yaml +++ b/airflow/providers/atlassian/jira/provider.yaml @@ -22,6 +22,7 @@ description: | `Atlassian Jira `__ versions: + - 2.0.0 - 1.1.0 - 1.0.0