SoftLayerのポータルユーザーのリストを出力するスクリプト

# SoftLayer Portalのユーザー管理

SoftLayerでは、Portalからクラウド上のシステムを管理します。
[SoftLayer Customer Portal](https://control.softlayer.com/)

PortalにアクセスするためにはユーザーIDが必要です。
SoftLayerのアカウントを作成するときに最初に作られるユーザーIDはマスターユーザーと呼ばれ、そのアカウントのシステムに対する全ての権限を持ちます。

マスターユーザーが全てのシステムを管理することは現実的ではないため、通常、マスターユーザーは子ユーザーを作成し、一部のシステムに対する管理権限を委譲します。子ユーザーは、更に子ユーザーを作成して権限を委譲し、システム上での開発や運用管理を開発者や運用担当者に委譲します。

図に表すと、以下のようになります。
![sl_users.png](https://qiita-image-store.s3.amazonaws.com/0/65167/a575e152-d4fa-4b78-7f89-5300f7d20ce1.png)

マスターユーザーは、子ユーザーに対して権限を割り当て、アクセスできるデバイスを指定します。子ユーザーは、管理を委譲するために孫ユーザーに対して権限を割り当て、アクセスできるデバイスを指定します。


# スクリプト

このようにユーザーは階層構造をとります。ユーザーの一覧はPortalで確認できますが、PortalやCLIではユーザーの親子関係を一覧で参照することができません。
これではユーザー管理上不便なので、SoftLayer APIを使用してユーザーの一覧と親子関係を取得するスクリプトを作成してみました。

```python:sluser.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

SL_USERNAME = <SL User Name>
SL_API_KEY = <SL API Key>
```

```python:sl_getUser.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'takechika'

import sys
from prettytable import PrettyTable
import SoftLayer
import sluser

SL_USERNAME = sluser.SL_USERNAME
SL_API_KEY = sluser.SL_API_KEY

_userMask = '''
    id,
    accountId,
    parentId,
    firstName,
    lastName,
    email
    '''
_userTableHeader = [
    'ParentID',
    'ParentName',
    'UserID',
    'UserName',
    'EMail'
    ]

def getChildren(parent, users):
    """Get children of the parent from the user list / このユーザーが親となる子ユーザーをリストから取得する.

    parent: 親ユーザーのオブジェクト (User_Customer)
    users: 検索対象の子ユーザーのリスト (an array of User_Customer)
    """

    a = {}
    b = []

    for u in users:
        if u.get('parentId') == parent.get('id'):
            a = {
                "ParentID": u.get('parentId'),
                "ParentName": parent.get('lastName') + " " + parent.get('firstName'),
                "ChildID": u.get('id'),
                "ChildName": u.get('lastName') + " " + u.get('firstName'),
                "Email": u.get('email')
            }
            b.append(a)
    return(b)

client = SoftLayer.Client(username=SL_USERNAME, api_key=SL_API_KEY)
users = client['Account'].getUsers(mask=_userMask)

# Find the master user id
for u in users:
    if u.get('parentId') == '':
        masterUser = u
        print("Master user is \"%s %s\" (id: %s)" % (masterUser.get('lastName'), masterUser.get('firstName'), masterUser.get('id')))

# Table definition
table = PrettyTable(_userTableHeader)
table.padding_width = 1

# Get user list
count = 0
for parent in users:
    userList = getChildren(parent, users)
    for x in userList[0:]:
        table.add_row(
            [
                x['ParentID'],
                x['ParentName'],
                x['ChildID'],
                x['ChildName'],
                x['Email']
            ]
        )
        count = count + 1

print(table)
print(count, "users")

exit()
```

出力は以下のようになります(ユーザー名、メールアドレスは架空のものです)。
子ユーザーと対応する親ユーザーが、一覧で表示されます。

```text
Master user is "Jedi Master" (id: 182178)
+----------+--------------------+--------+-----------------------+--------------------------+
| ParentID |     ParentName     | UserID |        UserName       |          EMail           |
+----------+--------------------+--------+-----------------------+--------------------------+
|  182178  |    Jedi Master     | 183358 |    Obi-Wan Kenobi     |    obi-wan@jp.ibm.com    |
|  182178  |    Jedi Master     | 183362 |        R2 D2          |     r2-d2@jp.ibm.com     |
|  182178  |    Jedi Master     | 183372 |        C 3PO          |     c-3po@jp.ibm.com     |
|  182178  |    Jedi Master     | 183376 |    Luke Skywalker     |     luke@jp.ibm.com      |
|  183362  |    Jedi Master     | 183378 |       Chew Bacca      |   chwebacca@jp.ibm.com   |
|  183358  |   Obi-Wan Kenobi   | 183360 |   Anakin Skywalker    |     anakin@jp.ibm.com    |
+----------+--------------------+--------+-----------------------+--------------------------+
6 users
```