【ServiceNow】APIからCatalog Itemの設定を取得したい

### はじめに

- バージョン
  - ServiceNow: Rome
  - Python: 3.8.8

Catalog Itemの設定にはその配下にvariablesやCatalog UI Policiesなど、  
複数あります。今回は、REST API Explorerを使ってCatalog Item(Name: api_test)と
これに紐づくvariablesの設定を取得してみます。

![catalog_item.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/793768f0-43e8-afb5-4dd9-21f8bbb50de5.jpeg)

### 1. Catalog Itemの設定を取得するコードの作成

1. アプリケーションナビゲーターから``REST API Explorer``を選択します
2. Path parametersに以下の設定を入れます
   - table Name: sc_cat_item
   - sysparm_query: name=api_test
     - 列``name``の値が``api_test``であるものを検索 

   ![sc_cat_item.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/93a4fb79-2bd8-dd7b-d5b6-7bc84c3c9705.jpeg)

3. ``Send``を選択してCatalog Itemの設定を取得出来ていたら、Code Samples内の``Python``を  
選択してコードを作成します

   ![code_sample.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/effd0427-eb1f-6ef7-1d8d-0b56d2add204.jpeg)

4. 以下のようなコードが作成されました

```python
#Need to install requests package for python
#easy_install requests
import requests

# Set the request parameters
url = 'https://devXXXXXX.service-now.com/api/now/table/sc_cat_item?sysparm_query=name%3Dapi_test&sysparm_limit=1'

# Eg. User name="admin", Password="admin" for this code sample.
user = 'admin'
pwd = 'admin'

# Set proper headers
headers = {"Content-Type":"application/json","Accept":"application/json"}

# Do the HTTP request
response = requests.get(url, auth=(user, pwd), headers=headers )

# Check for HTTP codes other than 200
if response.status_code != 200: 
    print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',response.json())
    exit()

# Decode the JSON response into a dictionary and use the data
data = response.json()
print(data)
```

### 2. variablesの設定を取得するコードの作成

Catalog Itemとvariablesの設定を比較すると、variablesのcat_itemという項目に  
Catalog Itemのsys_idが入っているようなので、APIで取得します

1. アプリケーションナビゲーターから``REST API Explorer``を選択します
2. Path parametersに以下の設定を入れます
   - table Name: item_option_new
   - sysparm_query: cat_item={{ Catalog Itemのsys_id }}
     - 列``cat_item``の値がCatalog Itemのsys_idと等しいものを検索
     - (注) 列``cat_item``はGUIだと見えない

   ![item_option_new.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554812/88c4d073-b10d-c97b-be3f-4cb096799f78.jpeg)

3. ``Send``を選択してvariablesの設定を取得出来ていたら、Code Samples内の``Python``を  
選択してコードを作成します

4. 以下のようなコードが作成されました

```python
#Need to install requests package for python
#easy_install requests
import requests

# Set the request parameters
url = 'https://devXXXXXX.service-now.com/api/now/table/item_option_new?sysparm_query=cat_item%3Dxxxxxxxxxxxxx&sysparm_limit=1'

# Eg. User name="admin", Password="admin" for this code sample.
user = 'admin'
pwd = 'admin'

# Set proper headers
headers = {"Content-Type":"application/json","Accept":"application/json"}

# Do the HTTP request
response = requests.get(url, auth=(user, pwd), headers=headers )

# Check for HTTP codes other than 200
if response.status_code != 200: 
    print('Status:', response.status_code, 'Headers:', response.headers, 'Error Response:',response.json())
    exit()

# Decode the JSON response into a dictionary and use the data
data = response.json()
print(data)
```

### 3. コードの修正

コードの修正をするとキリがないので、最低限の修正を加えました。
主な修正点は以下です。
- APIへのアクセスに使用する情報を、変数``common_info``に記載
- urlの最後の``sysparm_limit=1``を削除
  - 取得するデータ数に制限がかかってしまうため
- Catalog Itemの設定を取得する関数get_catalog_item_settingsと
variablesの設定を取得する関数get_variables_settingsを作成
  - 引数: クエリに使用する文字列
  - 戻り値: APIの結果

```python
from typing import Dict, List
import requests

common_info = {
    "base_url": "https://devXXXXXX.service-now.com/api/now/table/",
    "api_auth": ("admin", "admin"),
    "api_headers": {
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
}


def get_catalog_item_settings(catalog_item_name: str) -> Dict:
    # Set the request parameters
    url = (
        common_info["base_url"]
        + "sc_cat_item?sysparm_query=name%3D"
        + catalog_item_name
    )
    # Do the HTTP request
    response = requests.get(
        url, auth=common_info["api_auth"], headers=common_info["api_headers"]
    )

    # Check for HTTP codes other than 200
    if response.status_code != 200:
        print(
            "Status:",
            response.status_code,
            "Headers:",
            response.headers,
            "Error Response:",
            response.json(),
        )
        exit()

    # Decode the JSON response into a dictionary and use the data
    data = response.json()
    return data


def get_variables_settings(catalog_item_sys_id: str) -> List:
    # Set the request parameters
    url = (
        common_info["base_url"]
        + "item_option_new?sysparm_query=cat_item%3D"
        + catalog_item_sys_id
    )
    # Do the HTTP request
    response = requests.get(
        url, auth=common_info["api_auth"], headers=common_info["api_headers"]
    )

    # Check for HTTP codes other than 200
    if response.status_code != 200:
        print(
            "Status:",
            response.status_code,
            "Headers:",
            response.headers,
            "Error Response:",
            response.json(),
        )
        exit()

    # Decode the JSON response into a dictionary and use the data
    data = response.json()
    return data


if __name__ == "__main__":
    catalog_item = get_catalog_item_settings("api_test")["result"][0]
    variables = get_variables_settings(catalog_item["sys_id"])["result"]
    print(catalog_item)
    print(variables)
```

### 4. 結果の確認

- Catalog Item

```json
{
    ...,
    "description": "<p>api_test_description</p>",
    "name": "api_test",
    "short_description": "api_test_short_description",
    "sys_id": "xxxxCatalog Itemのsys_idxxxx",
    ...,
}
```

- variables

```json
[
    {
        "cat_item": {
            "link": "https://devXXXXXX.service-now.com/api/now/table/sc_cat_item/xxxxCatalog Itemのsys_idxxxx",
            "value": "xxxxCatalog Itemのsys_idxxxx"
        },
        ...,
        "name": "api_test_var1",
        "order": "100",
        "question_text": "api_test_var1",
        ...,
    },
    {
        ...,
        "cat_item": {
            "link": "https://devXXXXXX.service-now.com/api/now/table/sc_cat_item/xxxxCatalog Itemのsys_idxxxx",
            "value": "xxxxCatalog Itemのsys_idxxxx"
        },
        "name": "api_test_var2",
        "order": "200",
        "question_text": "api_test_var2",
        ...,
    }
]
```

### まとめ

Catalog UI Policiesなどvariables以外の値も取りたい場合は、テーブルの中のどの列に  
Catalog Itemのsys_idが格納されているかを確認し、因果関係を確認して下さい。

### 参考記事

[Service NowでTable APIを使ってみる](https://qiita.com/EconUC/items/2d2c659942b5097a162f#rest-api-explorer%E3%82%92%E4%BD%BF%E3%81%86)