Node.jsからIBM Cloud Object Storageへ接続する際のメモ


はじめに

Node-REDからIBM Cloud Object Storageへ接続する際にエンドポイントの設定でハマったので、原因調査のためnode-red-contrib-cosモジュールで利用しているibm-cos-sdk (npmパッケージ)を使用した際のメモを残しておきます。

準備

1. ibm-cos-sdk (npmパッケージ)のインストール

適当のディレクトリを作成して、npmパッケージをインストールします。(例えば、testというディレクトリを作成します)

$ mkdir test
$ cd test
$ npm init -y
$ npm i ibm-cos-sdk

2. サンプルコードを作成

IBM Cloudのリファレンスページを参照して、サンプルコードを作成します。

client.js
var ibm = require('ibm-cos-sdk');

var config = {
 endpoint: '<エンドポイント>',
 ibmAuthEndpoint: 'https://iam.cloud.ibm.com/identity/token',
 apiKeyId: '<APIキーID>',
 serviceInstanceId: '<サービスインスタンスID>',
};

var cos = new ibm.S3(config);

function getBuckets() {
    console.log('Retrieving list of buckets');
    return cos.listBuckets()
    .promise()
    .then((data) => {
        if (data.Buckets != null) {
            console.log(data);
        }
    })
    .catch((e) => {
        console.error(`ERROR: ${e.code} - ${e.message}\n`);
    });
}

function getBucketContents(bucketName) {
    console.log(`Retrieving bucket contents from: ${bucketName}`);
    return cos.listObjects(
        {Bucket: bucketName},
    ).promise()
    .then((data) => {
        if (data != null && data.Contents != null) {
            for (var i = 0; i < data.Contents.length; i++) {
                var itemKey = data.Contents[i].Key;
                var itemSize = data.Contents[i].Size;
                console.log(`Item: ${itemKey} (${itemSize} bytes).`)
            }
        }    
    })
    .catch((e) => {
        console.error(`ERROR: ${e.code} - ${e.message}\n`);
    });
}

function getItem(bucketName, itemName) {
    console.log(`Retrieving item from bucket: ${bucketName}, key: ${itemName}`);
    return cos.getObject({
        Bucket: bucketName, 
        Key: itemName
    }).promise()
    .then((data) => {
        if (data != null) {
            console.log('File Contents: ' + Buffer.from(data.Body).toString());
        }    
    })
    .catch((e) => {
        console.error(`ERROR: ${e.code} - ${e.message}\n`);
    });
}

getBuckets();
getBucketContents('cloud-object-storage-82-cos-standard-1o6');
getItem('cloud-object-storage-82-cos-standard-1o6', 'test.txt');

config

ここで重要になるのはconfigに設定するendpoint、apiKeyId、serviceInstanceIdの値です。

apiKeyID と serviceInstanceId は、Cloud Object Storageの「サービス資格情報」の"apikey"と"resource_instance_id"を値を設定するのが正解です。
endpoint は バケットの設定(回復力・ロケーション)によって値が異なります。

間違いやすい点①

apiKeyIDと"apikey"で名称が微妙に違うことと、serviceInstanceIdは"resource_instance_id"で名称が異なっているのが間違いやすい点です。
「サービス資格情報」には iam_apikey_description や iam_apikey_name など、apikeyを含む似たような名称があったり、
serviceInstanceIdは、「サービス資格情報」のiam_serviceid_crnと混同しました。(serviceとidを含む名称のため)

間違いやすい点②

endpointは「サービス資格情報」の"endpoints"ではありません。

エンドポイントの情報は以下にあります。

例えば、アクセス先のバケットの回復力がRegional、ロケーションがjp-tokの場合、エンドポイント(パブリック接続)は
s3.jp-tok.cloud-object-storage.appdomain.cloud
になります。

サンプルコードの実行例

configに誤りがある場合

エンドポイントが間違っていてもバケットの一覧は表示されます。
バケットの中身や指定したファイル(オブジェクト)は表示されません。
(ERROR: NoSuchBucketやERROR: NoSuchKeyになります)

$ node client.js

Retrieving list of buckets
{
  Buckets: [
    {
      Name: 'cloud-object-storage-82-cos-standard-001',
      CreationDate: 2021-05-07T08:08:36.589Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-1o6',
      CreationDate: 2021-05-07T03:31:45.802Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-257',
      CreationDate: 2021-05-07T11:37:55.016Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-ztk',
      CreationDate: 2021-05-06T07:51:49.717Z
    }
  ],
  Owner: {
    DisplayName: '77c04f4b-8e89-4636-be0c-be8eb1331f15',
    ID: '77c04f4b-8e89-4636-be0c-be8eb1331f15'
  }
}

Retrieving bucket contents from: cloud-object-storage-82-cos-standard-1o6
ERROR: NoSuchBucket - The specified bucket does not exist.

Retrieving item from bucket: cloud-object-storage-82-cos-standard-1o6, key: test.txt
ERROR: NoSuchKey - The specified key does not exist.

configが正しい場合

$ node client.js

Retrieving list of buckets
{
  Buckets: [
    {
      Name: 'cloud-object-storage-82-cos-standard-001',
      CreationDate: 2021-05-07T08:08:36.589Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-1o6',
      CreationDate: 2021-05-07T03:31:45.802Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-257',
      CreationDate: 2021-05-07T11:37:55.016Z
    },
    {
      Name: 'cloud-object-storage-82-cos-standard-ztk',
      CreationDate: 2021-05-06T07:51:49.717Z
    }
  ],
  Owner: {
    DisplayName: '77c04f4b-8e89-4636-be0c-be8eb1331f15',
    ID: '77c04f4b-8e89-4636-be0c-be8eb1331f15'
  }
}

Retrieving bucket contents from: cloud-object-storage-82-cos-standard-1o6
Item: test.txt (22 bytes).

Retrieving item from bucket: cloud-object-storage-82-cos-standard-1o6, key: test.txt
File Contents: This is a test file.

まとめ

みなさま、IBM CloudのLiteアカウントで良きNode-REDライフを!

参考