This is an automated email from the ASF dual-hosted git repository.
eladkal 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 31b06d5b12 Add jira connection docs and UI form (#36458)
31b06d5b12 is described below
commit 31b06d5b12547ae688ed945d580e5b5e29bb2433
Author: shohamy7 <[email protected]>
AuthorDate: Sat Dec 30 13:08:56 2023 +0200
Add jira connection docs and UI form (#36458)
* Add jira connection docs and UI form
* Add support for str and bool in the extra
---
airflow/providers/atlassian/jira/hooks/jira.py | 34 +++++++++++--
.../connections.rst | 44 +++++++++++++++++
.../index.rst | 1 +
tests/providers/atlassian/jira/hooks/test_jira.py | 55 ++++++++++++++++++++--
4 files changed, 127 insertions(+), 7 deletions(-)
diff --git a/airflow/providers/atlassian/jira/hooks/jira.py
b/airflow/providers/atlassian/jira/hooks/jira.py
index 3862d86bbd..ed706aed95 100644
--- a/airflow/providers/atlassian/jira/hooks/jira.py
+++ b/airflow/providers/atlassian/jira/hooks/jira.py
@@ -18,11 +18,12 @@
"""Hook for JIRA."""
from __future__ import annotations
+import warnings
from typing import Any
from atlassian import Jira
-from airflow.exceptions import AirflowException
+from airflow.exceptions import AirflowException,
AirflowProviderDeprecationWarning
from airflow.hooks.base import BaseHook
@@ -56,12 +57,21 @@ class JiraHook(BaseHook):
conn = self.get_connection(self.jira_conn_id)
if conn.extra is not None:
extra_options = conn.extra_dejson
+ verify = extra_options.get("verify", verify)
# only required attributes are taken for now,
# more can be added ex: timeout, cloud, session
# verify
- if "verify" in extra_options and
extra_options["verify"].lower() == "false":
- verify = False
+ if isinstance(verify, str):
+ warnings.warn(
+ "Extra parameter `verify` using str is deprecated and
will be removed "
+ "in a future release. Please use `verify` using bool
instead.",
+ AirflowProviderDeprecationWarning,
+ stacklevel=2,
+ )
+ verify = True
+ if extra_options["verify"].lower() == "false":
+ verify = False
self.client = Jira(
url=conn.host,
@@ -72,3 +82,21 @@ class JiraHook(BaseHook):
)
return self.client
+
+ @classmethod
+ def get_connection_form_widgets(cls) -> dict[str, Any]:
+ """Returns connection widgets to add to connection form."""
+ from flask_babel import lazy_gettext
+ from wtforms import BooleanField
+
+ return {
+ "verify": BooleanField(lazy_gettext("Verify SSL"), default=True),
+ }
+
+ @classmethod
+ def get_ui_field_behaviour(cls) -> dict[str, Any]:
+ """Returns custom field behaviour."""
+ return {
+ "hidden_fields": ["schema", "extra"],
+ "relabeling": {},
+ }
diff --git a/docs/apache-airflow-providers-atlassian-jira/connections.rst
b/docs/apache-airflow-providers-atlassian-jira/connections.rst
new file mode 100644
index 0000000000..e33392f54d
--- /dev/null
+++ b/docs/apache-airflow-providers-atlassian-jira/connections.rst
@@ -0,0 +1,44 @@
+ .. 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.
+
+Jira Connection
+===============
+
+The Jira connection type enables connection to Atlassian Jira.
+
+Default Connection IDs
+----------------------
+
+Jira Hook uses parameter ``jira_conn_id`` for Connection IDs and the value of
the
+parameter as ``jira_default`` by default.
+
+Configuring the Connection
+--------------------------
+Host
+ The Jira host (should be with scheme).
+
+Port
+ Specify the port to use for connecting to Jira.
+
+Login
+ The user that will be used for authentication against the Jira API.
+
+Password
+ The password of the user that will be used for authentication against the
Jira API.
+
+Verify SSL
+ Whether to verify SSL when connecting to the Jira API (this is ``True`` by
default).
diff --git a/docs/apache-airflow-providers-atlassian-jira/index.rst
b/docs/apache-airflow-providers-atlassian-jira/index.rst
index f7ccd801c6..b22e8c9fb6 100644
--- a/docs/apache-airflow-providers-atlassian-jira/index.rst
+++ b/docs/apache-airflow-providers-atlassian-jira/index.rst
@@ -34,6 +34,7 @@
:maxdepth: 1
:caption: Guides
+ Connection types <connections>
Notifications <notifications/index>
.. toctree::
diff --git a/tests/providers/atlassian/jira/hooks/test_jira.py
b/tests/providers/atlassian/jira/hooks/test_jira.py
index 930767fb68..f3a9888cc0 100644
--- a/tests/providers/atlassian/jira/hooks/test_jira.py
+++ b/tests/providers/atlassian/jira/hooks/test_jira.py
@@ -21,32 +21,79 @@ from unittest.mock import Mock, patch
import pytest
+from airflow.exceptions import AirflowProviderDeprecationWarning
from airflow.models import Connection
from airflow.providers.atlassian.jira.hooks.jira import JiraHook
from airflow.utils import db
pytestmark = pytest.mark.db_test
-
jira_client_mock = Mock(name="jira_client")
class TestJiraHook:
+ depcrecation_message = (
+ "Extra parameter `verify` using str is deprecated and will be removed "
+ "in a future release. Please use `verify` using bool instead."
+ )
+ conn_id = "jira_default"
+ conn_id_with_str_verify = "jira_default_with_str"
+ conn_type = "jira"
+ host = "https://localhost/jira/"
+ port = 443
+ login = "user"
+ password = "password"
+ proxies = None
+
def setup_method(self):
db.merge_conn(
Connection(
- conn_id="jira_default",
+ conn_id=self.conn_id,
+ conn_type="jira",
+ host="https://localhost/jira/",
+ port=443,
+ login="user",
+ password="password",
+ extra='{"verify": false, "project": "AIRFLOW"}',
+ )
+ )
+ db.merge_conn(
+ Connection(
+ conn_id=self.conn_id_with_str_verify,
conn_type="jira",
host="https://localhost/jira/",
port=443,
+ login="user",
+ password="password",
extra='{"verify": "False", "project": "AIRFLOW"}',
)
)
@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()
+ jira_hook = JiraHook(proxies=self.proxies)
+
+ jira_mock.assert_called_once_with(
+ url=self.host,
+ username=self.login,
+ password=self.password,
+ verify_ssl=False,
+ proxies=self.proxies,
+ )
+ assert isinstance(jira_hook.client, Mock)
+ assert jira_hook.client.name == jira_mock.return_value.name
+
+ @patch("airflow.providers.atlassian.jira.hooks.jira.Jira", autospec=True,
return_value=jira_client_mock)
+ def test_jira_client_connection_with_str(self, jira_mock):
+ with pytest.warns(AirflowProviderDeprecationWarning,
match=self.depcrecation_message):
+ jira_hook = JiraHook(jira_conn_id=self.conn_id_with_str_verify,
proxies=self.proxies)
- assert jira_mock.called
+ jira_mock.assert_called_once_with(
+ url=self.host,
+ username=self.login,
+ password=self.password,
+ verify_ssl=False,
+ proxies=self.proxies,
+ )
assert isinstance(jira_hook.client, Mock)
assert jira_hook.client.name == jira_mock.return_value.name