Repository: edgedb/edgedb

Issue:
Error creating role using CLI tool: please specify an attribute to alter
EdgeDB version: `1.0-alpha.2+dev.505.g5b68ec24`

Steps to reproduce:
```
# edgedb --admin create-role test
Usage: edgedb create-role [OPTIONS] ROLE_NAME

Error: please specify an attribute to alter
```
Command fails with weird error message if `OPTIONS` were no provided, even though they're supposed to be optional according to help message.
It works if 1 or more options are present: `edgedb --admin create-role --allow-login test`

Creating role inside interactive session without options works as expected:
```
modbay_beta> CREATE ROLE test;                                                                                                                                                                                         
CREATE
```


Discussion:
https://github.com/edgedb/edgedb/blob/d0cc7484ba897c5149195b1b0fb980a3c3565fcd/edb/cli/mng.py#L344
`_process_role_options` throws an error if no options were passed
Yes, it looks like it was supposed to be checked only in alter-role. Do you want to make a PR?
Yes please, I'm not sure what would be the best fix, passing additional argument to `_process_role_options` like `allow_empty` ?
Yes, `allow_empty` sounds sensible.
In a related vein, I've installed the edgedb-1-alpha-2 on my Debian 10 machine and reached a somewhat troubling error:

```python
$ sudo -u edgedb edgedb --admin alter role edgedb --password
Traceback (most recent call last):
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/bin/edgedb", line 11, in <module>
    sys.exit(cli())
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 1063, in invoke
    Command.invoke(self, ctx)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/edb/cli/mng.py", line 306, in alter
    connect(ctx)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/edb/cli/mng.py", line 37, in connect
    admin=ctx.obj['admin'], password=ctx.obj['password'],
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/edgedb/blocking_con.py", line 147, in connect
    connection_class=BlockingIOConnection)
  File "/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/lib/python3.7/site-packages/edgedb/blocking_con.py", line 113, in _connect_addr
    proto.sync_connect()
  File "edgedb/protocol/blocking_proto.pyx", line 70, in edgedb.protocol.blocking_proto.BlockingIOProtocol.sync_connect
  File "edgedb/protocol/blocking_proto.pyx", line 59, in edgedb.protocol.blocking_proto.BlockingIOProtocol._iter_coroutine
  File "edgedb/protocol/protocol.pyx", line 593, in connect
edgedb.errors.InternalServerError: buffer overread
```
This feels like it could qualify as a bug, but I might be using the CLI incorrectly. If not, what additional info could I supply to open a bug?

### Update:
Modifying `/home/edgedb/current`'s contents from:
`/usr/lib/x86_64-linux-gnu/edgedb-1-alpha1/bin` to `/usr/lib/x86_64-linux-gnu/edgedb-1-alpha2/bin` corrects the error and the expected command to alter the role and password for the superuser works as expected. Maybe this could be a part of the documentation for repeat installer-ers like myself.

Resolving patch:
diff --git a/edb/cli/mng.py b/edb/cli/mng.py
--- a/edb/cli/mng.py
+++ b/edb/cli/mng.py
@@ -288,7 +288,13 @@ def _decorator(func):
 ]
 
 
-def _process_role_options(ctx, password, password_from_stdin):
+def _process_role_options(
+    ctx,
+    password,
+    password_from_stdin,
+    allow_empty=False
+):
+
     if password is None and password_from_stdin:
         password = True
 
@@ -318,6 +324,9 @@ def _process_role_options(ctx, password, password_from_stdin):
         alters.append(f'SET password := {password_value}')
 
     if not alters:
+        if allow_empty:
+            return alters
+
         raise click.UsageError(
             'please specify an attribute to alter', ctx=ctx,
         )
@@ -333,12 +342,19 @@ def _process_role_options(ctx, password, password_from_stdin):
 def create_role(ctx, role_name, **kwargs):
     utils.connect(ctx)
 
-    attrs = ";\n".join(_process_role_options(ctx, **kwargs))
+    attrs = ";\n".join(_process_role_options(ctx, allow_empty=True, **kwargs))
 
-    qry = f'''
-        CREATE SUPERUSER ROLE {qi(role_name)} {{
+    if attrs:
+        formatted_attrs = f'''
+        {{
             {attrs}
         }}
+        '''
+    else:
+        formatted_attrs = ''
+
+    qry = f'''
+        CREATE SUPERUSER ROLE {qi(role_name)} {formatted_attrs}
     '''
 
     try:


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -60,6 +60,13 @@ async def test_cli_role(self):
                               '--password', input='foo-pass\n')
         self.assertIn('input is not a TTY', result.output)
 
+        result = self.run_cli(
+            'create-superuser-role',
+            'create-role-empty-options'
+        )
+
+        self.assertEqual(result.exit_code, 0)
+
     async def test_cli_repl_script(self):
         result = self.run_cli(input='SELECT 1 + 1')
         self.assertEqual(list(result.output.split('\n'))[0], '{2}')