[AIRFLOW-2227] Add delete method to Variable class
diff --git a/airflow/bin/cli.py b/airflow/bin/cli.py
index bca37bfa6f89b..9c264386cda97 100644
--- a/airflow/bin/cli.py
+++ b/airflow/bin/cli.py
@@ -342,8 +342,7 @@ def variables(args):
         except ValueError as e:
             print(e)
     if args.delete:
-        with db.create_session() as session:
-            session.query(Variable).filter_by(key=args.delete).delete()
+        Variable.delete(args.delete)
     if args.set:
         Variable.set(args.set[0], args.set[1])
     # Work around 'import' as a reserved keyword
diff --git a/airflow/models/__init__.py b/airflow/models/__init__.py
index f4524ebb44620..3e749c5057762 100755
--- a/airflow/models/__init__.py
+++ b/airflow/models/__init__.py
@@ -4311,10 +4311,15 @@ def set(cls, key, value, serialize_json=False, session=None):
         else:
             stored_value = str(value)
 
-        session.query(cls).filter(cls.key == key).delete()
+        Variable.delete(key)
         session.add(Variable(key=key, val=stored_value))
         session.flush()
 
+    @classmethod
+    @provide_session
+    def delete(cls, key, session=None):
+        session.query(cls).filter(cls.key == key).delete()
+
     def rotate_fernet_key(self):
         fernet = get_fernet()
         if self._val and self.is_encrypted:
diff --git a/tests/core.py b/tests/core.py
index c42fe4b906eff..6860ecd93be5c 100644
--- a/tests/core.py
+++ b/tests/core.py
@@ -745,6 +745,24 @@ def test_variable_setdefault_existing_json(self):
         self.assertEqual(value, val)
         self.assertEqual(value, Variable.get(key, deserialize_json=True))
 
+    def test_variable_delete(self):
+        key = "tested_var_delete"
+        value = "to be deleted"
+
+        # No-op if the variable doesn't exist
+        Variable.delete(key)
+        with self.assertRaises(KeyError):
+            Variable.get(key)
+
+        # Set the variable
+        Variable.set(key, value)
+        self.assertEqual(value, Variable.get(key))
+
+        # Delete the variable
+        Variable.delete(key)
+        with self.assertRaises(KeyError):
+            Variable.get(key)
+
     def test_parameterized_config_gen(self):
 
         cfg = configuration.parameterized_config(configuration.DEFAULT_CONFIG)

Make sure you have checked _all_ steps below.

### Jira

- [x] My PR addresses the following [Airflow Jira](https://issues.apache.org/jira/browse/AIRFLOW/) issues and references them in the PR title.

  - https://issues.apache.org/jira/browse/AIRFLOW-2227

### Description

- [x] Here are some details about my PR, including screenshots of any UI changes:

Add a delete method to the Variable class that no-ops if the Variable already does not exist. Additionally, refactor usages of `session.query(Variable).filter(key).delete()` to use the new `Variable.delete(key)` instead.

### Tests

- [x] My PR adds the following unit tests __OR__ does not need testing for this extremely good reason:

  - `tests.core:CoreTest.test_variable_delete`

### Commits

- [x] My commits all reference Jira issues in their subject lines, and I have squashed multiple commits if they address the same issue. In addition, my commits follow the guidelines from "[How to write a good git commit message](http://chris.beams.io/posts/git-commit/)":
  1. Subject is separated from body by a blank line
  1. Subject is limited to 50 characters (not including Jira issue reference)
  1. Subject does not end with a period
  1. Subject uses the imperative mood ("add", not "adding")
  1. Body wraps at 72 characters
  1. Body explains "what" and "why", not "how"

### Documentation

- [x] In case of new functionality, my PR adds documentation that describes how to use it.
  - When adding new operators/hooks/sensors, the autoclass documentation generation needs to be added.
  - All the public functions and the classes in the PR contain docstrings that explain what it does
  - If you implement backwards incompatible changes, please leave a note in the [Updating.md](https://github.com/apache/airflow/blob/master/UPDATING.md) so we can assign it to a appropriate release

### Code Quality

- [x] Passes `flake8`
