Repository: red-hat-storage/errata-tool

Issue:
Add bugs using CLI
Hello!

I want to be able to add bugs from the command line. My proposal is basically mimicking what is already there:

```
errata-tool advisory add-bugs <advisory-id> --bugs-ids <bug-id> <bug-id>
```

I already have a branch with the implementation, if this is interesting, I can open an MR.

Discussion:
rh-hectormartinezdev: @ktdreyer I need review and merge, any way I can help with it?

Patch:
diff --git a/errata_tool/cli/advisory.py b/errata_tool/cli/advisory.py
index 78e9737..14eff25 100644
--- a/errata_tool/cli/advisory.py
+++ b/errata_tool/cli/advisory.py
@@ -1,4 +1,5 @@
 from errata_tool.erratum import Erratum
+from errata_tool.bug import Bug
 from time import sleep
 
 
@@ -68,14 +69,40 @@ def add_parser(subparsers):
                              help='print current state of the advisory')
     push_parser.set_defaults(func=push)
 
+    add_bugs_parser = sub.add_parser('add-bugs')
+    add_bugs_parser.add_argument('errata_id', help='advisory id, "12345"')
+    add_bugs_parser.add_argument(
+        '--bug-ids', required=True, help='bugzilla bug ids, "12345"', nargs='+'
+    )
+    add_bugs_parser.set_defaults(func=add_bugs)
+
     # TODO:
     # "new-state"           Change erratum state
-    # "add-bugs"            Add bugs to erratum
     # "remove-bugs"         Provide a list of bugs to remove from erratum
     # "add-builds"          Add build to erratum (you may specify nvr)
     # "remove-builds"       Remove build from erratum
 
 
+def add_bugs(args):
+    e = Erratum(errata_id=args.errata_id)
+    bugs_to_attach = []
+    for bug_id in args.bug_ids:
+        bug = Bug(bug_id)
+        if args.errata_id in bug.all_advisory_ids:
+            continue
+        bugs_to_attach.append(bug)
+
+    e.addBugs([b.id for b in bugs_to_attach])
+    if args.dry_run:
+        print(
+            "DRY RUN: would add the following Bugs to advisory "
+            + "'{}': {}".format(args.errata_id, bugs_to_attach))
+        return
+
+    e.commit()
+    print(e)
+
+
 def get(args):
     e = Erratum(errata_id=args.errata_id)
     print(e)


Test patch:
diff --git a/errata_tool/tests/cli/test_advisory_cli.py b/errata_tool/tests/cli/test_advisory_cli.py
index 7d96a7a..50184b3 100644
--- a/errata_tool/tests/cli/test_advisory_cli.py
+++ b/errata_tool/tests/cli/test_advisory_cli.py
@@ -1,7 +1,8 @@
 import sys
 import pytest
+import requests
 from errata_tool.cli import main
-
+from errata_tool import ErrataConnector
 
 class FakeErratum(object):
 
@@ -17,6 +18,12 @@ class FakeErratum(object):
         pass
 
 
+class FakeBug(object):
+
+    def __init__(self, id):
+        pass
+
+
 def test_short_help(monkeypatch):
     argv = ['errata-tool', 'advisory', '-h']
     monkeypatch.setattr(sys, 'argv', argv)
@@ -124,3 +131,43 @@ def test_create(monkeypatch):
             '--manager-email', 'ohno@redhat.com']
     monkeypatch.setattr(sys, 'argv', argv)
     main.main()
+
+
+def test_add_bugs_dry_run(capsys, monkeypatch, mock_get, mock_put):
+    # Mock all external calls
+    monkeypatch.delattr('requests.sessions.Session.request')
+    monkeypatch.setattr(ErrataConnector, '_auth', None)
+    monkeypatch.setattr(requests, 'get', mock_get)
+
+    # Errata ID and Bug ID are reused from some fixtures already present
+    argv = ['errata-tool', '--dry-run', 'advisory',
+            'add-bugs', '33840', '--bug-ids', '1578936']
+    monkeypatch.setattr(sys, 'argv', argv)
+
+    main.main()
+
+    # We output 'DRY_RUN' and make no modification calls
+    captured = capsys.readouterr()
+    assert 'DRY RUN' in captured.out
+    assert '1578936' in captured.out
+
+    assert not hasattr(mock_put, 'kwargs')
+
+
+def test_add_bugs(monkeypatch, mock_get, mock_post, mock_put):
+    # Mock all external calls
+    monkeypatch.delattr('requests.sessions.Session.request')
+    monkeypatch.setattr(ErrataConnector, '_auth', None)
+    monkeypatch.setattr(requests, 'get', mock_get)
+    monkeypatch.setattr(requests, 'post', mock_post)
+    monkeypatch.setattr(requests, 'put', mock_put)
+
+    # Errata ID and Bug ID are reused from some fixtures already present
+    argv = ['errata-tool', 'advisory', 'add-bugs',
+            '33840', '--bug-ids', '1578936']
+    monkeypatch.setattr(sys, 'argv', argv)
+
+    main.main()
+
+    # Our bug is added to the request
+    assert '1578936' in mock_put.kwargs['data']['advisory[idsfixed]']