HCL Compass Rest APIs In Action の翻訳版です。
HCL Compass Rest API の活用
2021年9月20日
著者: Pradeesh S P / Technical Specialist, HCL Software
この記事では、HCL Compass 2.0.2バージョンで提供されるRESTFULサービスについて説明します。HCL Compassでは、ウェブやデスクトップ・インターフェースの他に、Perl APIやJava Native Interfaceを使用することができます。これらの2つのオプションは、複雑で柔軟性に欠けているため、Compassを中心としたアプリケーションや統合の構築が難しく、時間がかかります。
HCL Compass REST APIは、開発者がHTTPベースのREST APIを使用してHCL Compassと対話することを可能にします。REST APIは、レコードの表示や修正、クエリの作成と編集、テキスト検索など、HCL Compassの多くの機能を実行するために使用できます。REST APIの機能は、コンポーネントとしてHCL Compassのインストールに含まれています。これは、Apache Tomcatインスタンス上に展開され、CQwebサービスから独立して実行されます。一度インストールすれば、あとはサービスを起動するだけで使い始めることができます。このブログでは、REST APIを利用してHCL Compassのデータと対話するPythonスクリプトを開発します。このスクリプトを作成しながら、一般的に使用されているRESTAPIのいくつかを紹介します。
この記事は、プログラミングや、特定のタスクを実現するためのコードを提供するものではありません。単に、Compassデータと対話するためにREST APIを実用的な文脈で使用する方法を紹介するものです。もちろん、Pythonスクリプトを書くには、関数を使うなど、もっと簡単で効率的な方法があります。データ操作のコードの一部はスニペットに含まれておらず、ほとんどがREST APIと対話するためのリクエストモジュールの使い方を扱っています。
スクリプトを実行すると、システムで利用可能なリポジトリのリストを表示します。 パラメータとしてユーザー名、パスワード、データベースを入力することで、認証するリポジトリをリストから選ぶことができます。 選択したリポジトリに関連するデータベースを一覧表示します。 ユーザーにデータベースの提供を求め、そのユーザーに割り当てられたレコードを表示するためのクエリを構築する。 クエリを実行して、結果セットを表示します。 クエリを削除します。 REST サーバーからログアウトします。
Repos API - Schema Repositories のリストを取得します。 Authenticate API - CCM REST サーバーへの認証を行います。 Databases API - スキーマリポジトリに関連付けられたデータベースを一覧表示する。 Folders API - クエリを作成する親フォルダーをリストアップする。 QueryDefs API - クエリ定義を作成する。 ResultSets API - クエリ定義を実行して、結果セットを構築します。 ResultSet API - 以前に実行された Query Definition の単一ページを取得します。 QueryDef API - クエリ定義を削除するためのものです。 Authenticate API - CCM Rest Server からログオフする。
では、これらのAPIを詳細に確認しながら、スクリプトを作成していきましょう。
最初のタスクは、ユーザーがスキーマリポジトリを選択できるように、スキーマリポジトリのリストを取得することです。これには、REPOS API、特にエンドポイントである/ccmweb/rest/repos を使用します。この目的のためには、GET HTTPリクエストを使用する必要があります。このデモでは、Python Requests モジュールを使用してREST APIスクリプトを作成します。そのためには、スクリプトにモジュールをインポートする必要があります。そして、request.get()関数を使用して、このAPIリクエストを送信します。request.get関数は、リポジトリのエンドポイントをURLとして受け取り、ヘッダを引数として渡します。この特定のAPIでは、期待されるヘッダーは次のとおりです。
'Content-Type': "application/json"
ヘッダー情報は headers という変数に保存され、URL は repo_endpoint という変数に保存されます。これは、Rest APIのリクエストを行うために、このスクリプト全体でrequestモジュールにパラメータを渡すための、標準的なテンプレートになります。
cont_type = “application/json”
headers={‘Content-Type’: cont_type}
repo_endpoint = “https://servername:8190/ccmweb/rest/repos”
response = requests.get(
repo_endpoint,
headers=headers
)
上記のコードは、システムで利用可能なリポジトリのリストを取得します。
システムでリポジトリが利用できるようになり、ユーザーがログインするリポジトリを選択できるようになったので、認証を行う必要があります。REST サーバーへの認証には、/ccmweb/rest/authenticate をエンドポイントとする Authenticate API を使用します。使用するHTTPリクエストはPOSTです。まず、ユーザーにユーザー名、パスワード、リポジトリ名、ログインしたいデータベースを入力してもらいます。以前のREPOS APIとは異なり、Authenticate APIでは、上記の情報をJSON形式でボディに送信する必要があります。ヘッダーとURLの他に、今回はボディデータもrequests.postメソッドで提供しなければなりません。また、リクエストが何らかの例外やエラーメッセージを発生させたかどうかを知る必要があり、そのために raise_for_status() メソッドを使用します。すべてがうまくいけば、このリクエストは認証トークンをJSON形式で出力します。これは、Compassのデータを取得または変更するための今後のAPIリクエストに使用する必要があります。このデータを操作してトークンを取得するためには、このJSON出力を処理してPythonの辞書データ構造に変換する必要があります。そのために、.json()メソッドを使用します。Json.dumps関数は、Pythonで処理できるようにjsonデータを文字列に変換します。前回のAPIコールと同じヘッダーを今回も渡していることに注目してください。
期待されるヘッダーは、「Content-Type」。"application/json"
eponame = input(“\nEnter Repository Name : “)
auth_url = “https://servername:8190/ccmweb/rest/authenticate”
username = input(“\nEnter your username : “)
password = input(“\nEnter your password : “)
db1name = input(“\nEnter db name : “)
body_data={“username”:username,
“password”:password,
“repo”:reponame,
“db”:db1name
}
auth_response = requests.post(auth_url,headers=headers,data=json.dumps(body_data))
auth_response.raise_for_status()
auth_data=auth_response.json()
スキーマ・リポジトリに関連するデータベースの一覧を表示するには、エンドポイントがccmweb/rest/repos/repository name/databasesのDatabases APIを使用します。HTTPリクエストは GET です。今回は、先ほどのAPIコールのヘッダーとは別に、Authentication Token(先ほどのAPIコールの後に出力として受け取ったもの)を以下のフォーマットで送る必要があります。
期待されるヘッダーは ‘Content-Type’: “application/json”,
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
requests.get関数では、URLとヘッダを渡しています。また、resay_for_status()を行い、.json関数でレスポンスを読み込んでいます。このAPIでは、必須のボディデータはありません。データベースを辞書として取得し、それを処理してユーザーがCompassデータへのアクセスを選択できるように表示する必要があります。
auth = “Bearer”+” “+auth_data[‘token’]
headers1={‘Content-Type’: cont_type,
‘Authorization’: auth
}
db_url = f”https://servername:8190/ccmweb/rest/repos/{RespositoryName}/databases”
dbname_response = requests.get(db_url,
headers=headers1
)
dbname_response.raise_for_status()
dbnames = dbname_response.json()
ワークスペース内のあるフォルダにクエリを作成する必要があります。そのためには、ルートワークスペースにどのようなフォルダがあるかを調べる必要があります。この例では、クエリは一時的なものなので、「Public Queries」フォルダに保存します。そのため、ワークスペース内の「Public Queries」フォルダの DBID を調べる必要があります。この目的のために Folders API を使用し、エンドポイントを /ccmweb/rest/repos/ リポジトリ名 /databases/ データベース名 /workspace/folders とします。 使用する HTTP リクエストは GET です。
期待されるヘッダーは、'Content-Type': "application/json",
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
requests.get関数にパラメータを渡し、いつものようにraise_for_status関数を使い、.json関数を使って出力されたレスポンスをキャッチする必要があります。このJSONデータをjson.dumps関数に渡します。この出力から、次のAPIで必要となるdbIdデータに興味があります。
parent_url = f”https://servername:8190/ccmweb/rest/repos/{RepositoryName}/databases/{DatabaseName}/workspace/folders”
parent_dbid_response = requests.get(parent_url ,headers=headers1)
parent_dbid_response.raise_for_status()
parent_dbid_higher = parent_dbid_response.json()
parent_dbid = parent_dbid_higher[1][‘dbId’]
ユーザーからアクセスが必要なデータベースと親DBIDの入力を得たら、スクリプトの目的は、そのデータベース内のどの欠陥が所有されているかをユーザーに表示することです。このため、最初のステップでは、ログインユーザが所有するすべての欠陥を表示するためのクエリ定義を作成する必要があります。この目的のために、QueryDefs API を使用します。エンドポイントは /ccmweb/rest/repos/リポジトリ名/データベース名/workspace/queryDefs で、使用する HTTP リクエストは POST です。このAPIでは、従来のAPIと同様のヘッダが必要ですが、構築されるクエリの構造を形成するボディデータが必須となります。
期待されるヘッダは ‘Content-Type’: “application/json”,
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
本体のデータは以下のようになり、変数query_dataに格納されます。
query_data={ “name”: “MyDefects”,
“dbIdParent”: parent_dbid,
“primaryEntityDefName”: “Defect”,
“queryFieldDefs”: [
{
“fieldPathName”: “Headline”,
“isShown”: “true”
}
],
“filterNode”: {
“boolOp”: “BOOL_OP_AND”,
“fieldFilters”: [
{
“fieldPath”: “Owner”,
“compOp”: “COMP_OP_EQ”,
“values”: [username],
“stringExpression”: “= username”
}
]
}
}
ボディデータをもう少し詳しく見てみましょう。いつものように、ボディデータはJSON形式です。
name – Name of the query.
dbIdParent – The dbid of the parent directory where the query is to be created.
primaryEntityDefName – Record type name.
queryFieldDefs – fieldPathName is the field name.
isShown : true – To display the specific field in the result set.
filterNode – boolOp – AND – Operator for adding multiple filters to the query.
fieldFilters – These are the fields to provide as filters.
fieldPath : Owner – Field name of the filter
compOp – COMP_OP_EQ – Denotes Equal to
values : [username] – ユーザー名は、ユーザーの実際のユーザー名に置き換えられます。この条件では、フィールドOwnerが提供されたユーザー名と等しくなっています。したがって、クエリはオーナーが提供されたユーザー名であるすべてのDefectをリストアップする必要があります。
API用のパラメータの準備ができたので、これらを requests.post 関数に渡し、いつものように raise_for_status 関数を使用して、.json 関数を使用して出力レスポンスをキャッチします。json.dumps関数でJSONデータを渡します。この出力から、次のAPIで必要となるdbIdのデータに興味があります。
query_db = input(“\nEnter Database name to build query : “)
query_data={ “name”: “MyDefects”,
“dbIdParent”: parent_dbid,
“primaryEntityDefName”: “Defect”,
“queryFieldDefs”: [
{
“fieldPathName”: “Headline”,
“isShown”: “true”
}
],
“filterNode”: {
“boolOp”: “BOOL_OP_AND”,
“fieldFilters”: [
{
“fieldPath”: “Owner”,
“compOp”: “COMP_OP_EQ”,
“values”: [username],
“stringExpression”: “= username”
}
]
}
}
query_url = f”https://servername:8190/ccmweb/rest/repos/{RepositoryName}/databases/{DatabaseName}/workspace/queryDefs”
query_response = requests.post(query_url,headers=headers1,data=json.dumps(query_data))
query_response.raise_for_status()
query_out = query_response.json()
query_dbid = query_out[‘dbId’]
前のステップで Query Dbid を受け取ったので、これを使ってクエリの実行と結果セットの構築を行う必要があります。これらの操作はいずれも ResultSets API で行います。使用する HTTP リクエストは POST です。この目的のために、次のエンドポイントを使用します。/ccmweb/rest/repos/repositoryname/databases/databasename/workspace/queryDefsquerydbid/resultsets。使用するヘッダーは、前のステップと同じです。
期待されるヘッダーは ‘Content-Type’: “application/json”,
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
このAPIでは、ボディデータの受け入れが必須となっています。もし特定のパラメータがない場合は、以下のように空の json を渡すことができます。
query_exec_data={
}
これ以外にも、URL、データ、ヘッダーが requests.get 関数に渡されます。いつものように、ここでも raise_for_status、json.dumps、.json の各関数を使います。出力結果から、次のAPIリクエストに渡すための「result_set_id」が得られることを期待しています。
query_exec_url = f”https://servername:8190/ccmweb/rest/repos/{RepositoryName}/databases/{DatabaseName}/workspace/queryDefs/{Querydbid}/resultsets”
query_exec_data={
}
query_exec_response=requests.post(query_exec_url,headers=headers1,data=json.dumps(query_exec_data))
query_exec_response.raise_for_status()
query_exec_results = query_exec_response.json()
resultset_id = query_exec_results[‘result_set_id’]
いよいよ結果セットをユーザーに表示します。これには、ResultSet API を使用し、エンドポイントとして /ccmweb/rest/repos/repositoryname/databases/databasename/workspace/queryDefs/querydbid/resultsets/resultsetid を指定します。前のステップの出力としてresultsetidを取得しました。HTTPリクエストはPOSTです。パラメータとしてURLとヘッダを指定するだけです。
期待されるヘッダは ‘Content-Type’: “application/json”,
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
Python Prettytableパッケージを使って、結果を表形式で表示します。結果セットの出力は、辞書形式で提供されます。そこから行の値を取得して、必要な値をPythonのリストとして抽出します。クエリ構成データでは、表示フィールドにHeadlineというフィールドのみを要求しましたが、出力にはデフォルトでdisplayNameが含まれており、これはレコードのID以外の何物でもありません。
result_set_url = f”https://servername:8190/ccmweb/rest/repos/{RepositoryName}/databases/{DatabaseName}/workspace/queryDefs/{Querydbid}/resultsets/{Resultsetid}”
result_set_response = requests.get(result_set_url,headers=headers1)
result_set_response.raise_for_status()
resultset_results = result_set_response.json()
second_final = resultset_results[‘rows’]
headline_value = []
id_value = []
for i in second_final:
headline_value.append(i[‘values’])
id_value.append(i[‘displayName’])
x.add_column(“ID”,id_value)
x.add_column(“Headline”,headline_value)
print(x)
次の作業は、作成したクエリを削除して、スクリプトを実行するたびに新しいクエリが作成されるように、Compass のデータベースに表示されないようにすることです。これには QueryDef API を使用し、エンドポイントを /ccmweb/rest/repos/reposittoryname/databases/databasename/workspace/queryDefs/querydbid とします。このためのHTTPリクエストはDELETEです。パラメータとしてurlとheadersを受け取ります。
期待されるヘッダーは ‘Content-Type’: “application/json”,
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
これまでのAPIリクエストで使われていた通常の機能とは別に、今回の違いは、何の出力も受け取らないということです。この場合、クエリが正常に削除されたかどうかをどうやって知ることができるでしょうか?それには、HTTPステータスコードを利用します。通常、HTTPレスポンスコードが200の範囲にあれば、リクエストが成功したことを意味します。そこで、HTTPレスポンスからステータスコードを取得するために、response.status_code関数が必要になります。これを条件文に渡すことで、クエリの削除が成功したかどうかを検証することができます。
remove_query_url = f”https://servername:8190/ccmweb/rest/repos/(RepositoryName}/databases/{DatabaseName}/workspace/queryDefs/{Querydbid}”
remove_query_response = requests.delete(remove_query_url,headers=headers1)
remove_query_response.raise_for_status()
remove_query_final_response = str(remove_query_response.status_code)
if remove_query_final_response.startswith(’20’):
print(“\nRemoving Query Successful”)
else:
print(“\nRemoving query failed! Please manually remove”)
クエリの出力をユーザーに表示することができたので、意図したタスクはすべて完了しました。あとは、セッションを蓄積してサーバに負荷をかけないようにするために、サーバからログオフするだけです。この目的のために、Authenticate APIを使用し、エンドポイントを/ccmweb/rest/authenticate/logoff とします。HTTPリクエストはPOSTです。先ほどのAPIリクエストと同様に、パラメータとしてURLとヘッダーのみを受け取ります。前のステップで行ったように、ログアウトが成功したかどうかを知るための出力はありませんので、ステータスコードも調べます。
期待されるヘッダーは 'Content-Type': "application/json",
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsInJlcG8iOiIxMC4wLjAiLCJleHAiOjE1NzM2NjE5NDUsImlhdCI6MTU3MzU3NTU0NSwiZGIiOiJTQU1QTCJ9.Lgdk9gPm6mFFGEnr6mRt7Vrq-nTnlP86ARKc16bP4syeTIvKQ55JX5r6aFXVC20xC2NwsjqbvAhd2f1r2PiIUA
logout_url=”https://servername:8190/ccmweb/rest/authenticate/logoff”
logout_response = requests.post(logout_url,headers=headers1)
logout_response.raise_for_status()
logout_final_response = str(logout_response.status_code)
if logout_final_response.startswith(’20’):
print(“\nLogout Successful”)
else:
print(“\nLogout Failed!”)
スクリプトの完全な出力は以下の通りです。システム内のリポジトリの一覧が表示されます。RESTサーバへの認証のために、ユーザ名、パスワード、データベースを入力する必要があります。
次に、ユーザが所有するレコードをリストアップするためのクエリを作成するために親ディレクトリを見つけます。レコードを作成して表示した後、クエリを削除してRESTサーバーからログアウトし、途中でエラーが発生した場合は報告します。
The repositories available on this server are
———————————–
CadenceTest RestAPIDemo
Authenticating to Compass Rest API server!
Enter Repository Name : RestAPIDemo
Enter your username : admin
Enter your password :
Enter db name : RESTD
Listing the Databases for the repository RestAPIDemo
The database name(s) are as follows
RESTD
restn
Building a Query to display records assigned to you
Enter Database name to build query : RESTD
Executing the Query
Displaying the Result Set
+—————+———————————–+
| ID | Headline |
+—————+———————————–+
| RESTD00000041 | [‘Testing RestAPI Demo Record 1’] |
| RESTD00000042 | [‘Testing RestAPI Demo Record 2’] |
+—————+———————————–+
Removing the Query
Removing Query Successful
Logging off
Logout Successful
これで、COMPASS HTTP REST APIの使用を実演するための簡単なスクリプトを作成するという、我々がやろうとしたことは達成されました。これが、HCL Compassのデータを使ったより複雑なアプリケーションやインテグレーションの開発に役立つことを期待しています。