Watson StudioのJupyter NotebookからICOSのファイルを使う

以前の記事
[Watson StudioのJupyter NotebookからICOSへファイル出力をする](https://qiita.com/vegetable831/items/e300da8e7cd21c271ef0)
では、以下の1から4のようなファイル操作について記載しました。

![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/5a910e13-fb85-8fe7-b3f8-e1ea045699d0.jpeg)

Watson Studioでプロジェクトを作成すれば、自動的にICOSに一つバケット(上図の「バケットA」)が作成され、前回の記事はそのバケットのファイル操作を記載しました。
今回の記事は、Watson Studioのプロジェクトとは関係のないバケットへアクセスする方法を記載します。
(以下の絵の「バケットB」からのデータ取り込み)

![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/ef164587-fbb7-ac73-cc38-5203b5a7f834.jpeg)

## 0. 準備
IBM Cloudコンソールから、バケットを1つ作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/b78c9d79-9de2-8d97-0254-92b0c3faf459.png)

名前は、「qiita-bucket-b」としました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/4a25445c-4da4-2941-e464-5281eeb09ef9.png)

csvファイルを1つアップロードしました。
このファイルをWatson StudioのJupyter notebookに取り込むことができれば、この記事は完成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/e62f7c74-df8b-8299-135b-e4d6da73cc0f.png)

## 1. APIキー作成
「qiita-bucket-b」へのアクセス権限を持ったAPIキーを作成し、Jupyter notebookからはそのキーを用いることで、「qiita-bucket-b」にアクセスできる、というのが基本的な動きです。

### 1.1 サービスID作成
このあたりちょっと分かりづらいのですが、アクセス権限は直接APIキーに付与されるのではなく、サービスIDに紐付くものです。そのため、以下のような手順となります。
1. サービスIDを作成
2. サービスIDに権限を付与
3. サービスIDに対応するAPIキーを作成

IBM Cloudコンソールで、管理→アクセス(IAM)を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/1af33bec-d977-6ac1-ab06-1f57b7b74378.png)

サービスIDを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/1d083293-5b78-4153-9be6-ace07f30dc91.png)

名前や説明は任意です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/c39d64f4-7cb5-1a45-a579-8be6a97e7274.png)

ここまででサービスIDが作成されました。

### 1.2 権限の付与
作成したサービスIDに対して、「qiita-bucket-b」へのアクセス権限を付与します。
IBM CloudコンソールのICOSの管理画面から、「qiita-bucket-b」を探し、下のようにアクセス・ポリシーをクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/887d40a4-fc4a-7dfb-e476-19532703c122.png)

サービスIDとして、1.1で作成したサービスIDを選択し、「アクセス・ポリシーの作成」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/f563afc1-1d93-6d51-ea5f-d3866ddbf5af.png)

### 1.3 APIキー作成
再度、管理→アクセス(IAM)のサービスIDを開きます。
1.1で作成したサービスIDを探し、「アクセス・ポリシー」を見てみると、1.2で付与した権限が正しく設定されていることを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/fe697bc4-515a-861a-530c-27232dbd877f.png)
(なお、1.2の手順ではなく、ここから「アクセス権限の割り当て」を行うことも可能ですが、1.2の手順のほうが簡単です)

以下のようにAPIキーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/06d54050-ce54-6da8-2e7e-73ed23231eaa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/17e441b7-1f7e-2d7b-828d-564eb1d67e98.png)

一応ダウンロードしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/a123253f-98ff-ed4b-a20b-775c837a27ef.png)

ダウンロードされたJSONを開くと、APIキーを確認できます。
このAPIキーがあれば、バケット「qiita-bucket-b」へアクセスできます！

```
"apiKey": "xxxyyyzzz"
```
## 2. Jupyter Notebookからアクセス
どこにどう上記のAPIキーを指定すればいいか、悩ましいところですが、最も簡単な方法は、以下のように、Assetに登録されている適当なファイルを「Insert to code」して下さい。
これを雛形として、書き換えるのが楽なためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/fba24b99-fb48-4cbc-3ab0-6fffaa7caa47.png)

そして、insertされたコードの以下の4箇所を書き換えてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/4c9c6a33-921f-f34e-c067-1b509ab921bf.png)

### 2.1 ibm_api_key_id
1.3で作成したAPIキーに変更してください。

```
ibm_api_key_id='xxxyyyzzz'
```
### 2.2 endpoint_url
エンドポイントは、バケットごとに異なるため、IBM CloudコンソールのICOSの管理画面から確認するのが無難です。以下のように「構成」のところから確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/cf68f406-d6ef-d6e5-b13b-737b81d71fb4.png)

これをコピーして貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/7bb51e3f-3908-83fd-da93-d95b2911816e.png)

```
endpoint_url='https://s3.jp-tok.cloud-object-storage.appdomain.cloud')
```

### 2.3 Bucket
以下の通りです。

```
Bucket='qiita-bucket-b'
```

### 2.4 Key
バケットにある、アクセスしたいファイルを指定します。

```
Key='new_potato_list.csv'
```

これで実行すると、ファイルの内容を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/ee98d89d-eb9e-6525-91e0-1c0ab023e667.png)


本文は以上です。

## 補足1
このようなことを実現する方法は、他にもたくさんあると思います。
例えば、本来はWatson StudioのAssetでバケットへのconnectionを作るのがいいのかも知れません。
しかし、設定項目が多く何を入れればいいのか分かりづらいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/48a51dcc-e525-f3a0-b8d5-fb33cf93cdab.png)

そして、Jupyter notebookで上記のconnectionを「insert to code」しても、なぜかURLしか入ってくれません。(バグでしょうか。。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404032/bbbb0ea1-8459-60b9-02af-786cfcc07414.png)

## 補足2
2.2 endpoint_url では、わざわざバケットのエンドポイントを確認しました。
エンドポイントはさまざまありますが、これを間違えたときのエラーが分かりづらく、最初から正確に指定したいためです。

存在しないエンドポイントを指定すると以下のエラーが出力されますが、これは分かりやすい例です。

```
EndpointConnectionError: Could not connect to the endpoint URL: "https://s3.jp-tok.cloud-object-storage.appdomain.clou/qiita-bucket-b/new_potato_list.csv"
```

しかし、存在するが間違ったエンドポイントを指定すると以下のようなエラーが出力されます。
バケット名やファイル名が違うときも同じエラーが出力されるため、何が間違ってるのかが分かりません。

```
NoSuchKey: An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist.
```