gitlabApiを使用して、gitlabの複数グループにメンバーを一括追加する

## 課題
新しい人が入る度に手動でgitlabのグループ追加は大変

## 解決策
GitLabAPIを使用してプログラムを作成した。
以下を元にLambdaに設定してAPIにしている。

### 処理の流れ

- 入力値をバリデーション(user:ユーザー名とlevel:権限)
- usersAPIを使用してユーザー情報を取得する
- 対象のグループリストにユーザー情報に入っているIDを追加する

バリデーションなどところどころ行なっているので参考にどうぞ。

### プログラム

```python
# coding: utf-8
import json, requests, re
import inspect

private_token = '[gitlabの管理画面から発行してください]'
url_prefix = 'https://[your_gitlab_domain]/api/v4/'

def main(params):
  success_group_list = {}
  try:
    check_empty(params)
    user_info = get_user_info(params['user'])
    success_group_list = add_group(user_info[0]['id'], params['level'])
  except AddGitLabException as e:
    info = e.get_info()
    return {'body': info['body'], 'code': info['code'], 'function': info['function']}
  return {
    'code': 200,
    'body': 'Success:' + str(success_group_list)
  }

# 必須チェック
def check_empty(params):
  if 'user' not in params or len(params['user']) == 0 or 'level' not in params or len(params['level']) == 0:
    raise AddGitLabException('Input require parameter.', 400, inspect.currentframe().f_code.co_name)

# ユーザー情報を取得する
def get_user_info(username):
  url = url_prefix + 'users?active=true&username=' + username
  headers = {'Private-Token': private_token}
  response = requests.get(url, headers=headers)

  if response.status_code != 200 and response.status_code != 201:
    raise AddGitLabException(response.content, response.status_code, inspect.currentframe().f_code.co_name)
  user_info = json.loads(response.content)
  if user_info[0:1] == False:
    # 対象ユーザーが存在しない場合エラー
    raise AddGitLabException('Nothing user.', 404, inspect.currentframe().f_code.co_name)
  return user_info

# グループに対象メンバーを追加する
def add_group(user_id, level):
  success_group = []
  for group_info in target_group_list():
    for group_name, group_id in group_info.items():
      url = url_prefix + 'groups/' + str(group_id) + '/members'
      headers = {'Private-Token': private_token}
      response = requests.post(url, headers=headers, data={'user_id': user_id, 'access_level': level})
  
      # 200/201:登録成功、409:既に登録済みのため例外には投げない
      if response.status_code != 200 and response.status_code != 201 and response.status_code != 409:
        raise AddGitLabException(response.content, response.status_code, inspect.currentframe().f_code.co_name + ' group_id:' + str(group_id))
      success_group.append(group_name + ':' + str(response.status_code))
  return success_group

# 対象のグループを取得する
def target_group_list():
  return [
    {'[group_name1]' : [group_id1]},
    {'[group_name2]' : [group_id2]}
  ]

# 専用例外クラス
class AddGitLabException(Exception):
  def __init__(self, body, code, function):
    self.body = body
    self.code = code
    self.function = function

  def get_info(self):
    return {'body':self.body,'code':self.code, 'function': self.function}

print(main({'user':'test_user', 'level':'30'}))
```

グループIDはAPIで手動で取得する方法を取っている(以下を参照)

[gitlabAPI v4 groups](https://docs.gitlab.com/ee/api/groups.html)

group_idはgroupsAPIを使用して、group_idを取得してきて頑張ってリスト化しました(一回リストを作れば、それ以降はあまり変更しなくて良いので)
頑張ってリスト化しなくても特定のgroupに絞るためのいい方法があれば教えてほしいです。

## gitlabApiがv3の場合

まだ古いgitlabを扱っている場合、v3しか有効ではない方もいるかもしれません。

以下にドキュメントがあるので参考に組み替えてみてください。

※自分の場合、usersAPIのusernameではうまくユーザー情報を取ることができなかったので、やむなくsearchを使用していました(複数ユーザーが返却された場合はエラーにする)

https://gitlab.com/gitlab-org/gitlab-foss/blob/8-16-stable/doc/api/README.md