본 실습에서는 cli로 수행했던 db action을 http request 로 만들어 보겠다.
이를 위해서 action을 수행하는 http endpoint api생성이 필요하다.
아래와 같은 구조로 구현 할 것이다.
(기본 환경 설정은 되어 있다 가정하고 진행 하겠다. 필요한 사람은 이전 lab을 참고하여 환경을 셋업하자.)

참고:https://github.com/jzaccone/ogs-serverless-apis

Step Summary
    · Cloudant DB  binding
    · CRUD action 생성
    · API endpoint 생성

 

[1st: DB binding]
1. Cloudant auto binding
Bluemix 의 OpenWhisk(IBM Cloud Functions)를 사용하면 OpenWhisk 에서 자동으로 package bindings 을 생성 한다.
cli에서 bx login 후 아래 command를 수행 한다.

$bx wsk package refresh
아래와 같이 자동으로 binding된다.
Bluemix_testCloudant_Credentials-1
(메뉴얼 하게 바인딩도 물론 가능하다. 여기서는 다루지 않겠다. 바인딩 부분만 메뉴얼하게 하면 나머지 과정은 동일하다.)

2. 바인딩된 credential 확인
$bx wsk package list
위 명령으로 package 명을 확인 하고 노란 부분에 본인의 package명을 넣어서 아래 명령을 수행 한다.
$bx wsk package get /yjh@xx.xxx.com_korea/Bluemix_Cloudant-Serverless_Credentials-1 parameters
아래와 비슷한 credential 정보를 확인 할 수 있을 것이다.

[
{
    “key”: “username”,
    “value”: “cdb18832-2bbbxxxxxxdf2-xxxx-Bluemix”
},
{
    “key”: “host”,
    “value”: “cdb18832-xxxx-4df2-b7b1-Bluemix.cloudant.com”
},
{
    “key”: “password”,
    “value”: “c90886674xxxxac827daxxxx972737″
}
]

 

[2nd: CRUD action 생성]

1. CRUD 구현 overal step
이전 lab에서 read와 create action을 만들었었지만 실습을 위해 단순한 코드의 새로운 action으로 만들어 보겠다.
(serverless programming 기준에 좋은 방식은 아닐 수 있다. 단순히 이해를 위해 direct access로 구현한 것이다.)
crud를 구현하는 방법은 아래와 같은 스텝을 따르게 된다.

1) Create/Read/Update/Delete action 생성
2) web action true 설정
3) api endpoint 연결

2. Create read action 생성

1) read action을 생성하자.
read-cat.js 파일을 만들고 아래와 같이 소스를 넣자.
(파일을 만들때 main function은 필수로 있어야 한다. main 함수를 바로 정의해도 되고,
export를 main으로 시켜 줘도 된다. )
단순히 docid로 db에서 값을 읽어오는 코드 이다.

var request = require('request');
var Cloudant = require('cloudant');

function main(params)
{
    var cloudant = new Cloudant({
        account: params.CLOUDANT_USERNAME,
        password:params.CLOUDANT_PASSWORD
    });

    var database = cloudant.db.use(params.CLOUDANT_DATABASE);
    var docId=params.docid||'InsertDoc';

     return new Promise(function(resolve, reject) {
      database.get(docId, function(error, response) {
        if (!error){
          console.log('success', response);
          resolve(response);
        } else {
          console.error('error', error);
          console.error('dbnane',params.CLOUDANT_DATABASE);
          reject(error);
        }
      });
    });
}

exports.main = main;

2) read-cat 이란 이름의 액션으로 등록.
–web true 속성을 줘서 http endpoint를 생성 할 수 있게 한다.
action을 만들때 –param 속성을 줘서 만들면 파라미터가 action에 자동으로 바인딩 되어 있다. 다음 action 수행시 parameter를 넘기지 않아도 자동으로 들어간다.
(CLOUDANT_USERNAME 과 같은 파라미터를 이전 lab에서 export를 해 두었기 때문에 변수 형태로 작성 할 수 있다. 잘 모르겠다면 “IBM Cloud Functions CLI 사용해보기” lab을 참고 하자. )

$bx wsk action create read-cat read-cat.js \
–param CLOUDANT_USERNAME “$CLOUDANT_USERNAME” \
–param CLOUDANT_PASSWORD “$CLOUDANT_PASSWORD” \
–param CLOUDANT_DATABASE “$CLOUDANT_DATABASE” –web true

3) endpoint 생성을 확인 하자.
(command를 연습할겸 확인하는 command도 수행 해보자.)
$bx wsk action get read-cat –url

4) parameter가 셋팅되었는지 확인 하자.
$bx wsk action get read-cat –summary

5) action이 제대로 수행되는지 확인 하자.
(action name 앞에 namespace를 붙여도 되고 안 붙여도 된다. namespace가 하나일 경우.)
아래와 같은 결과가 나오면 제대로 수행 된 것이다. (결과는 조금 다를 수 있다. error가 나지 않고 json format으로 무엇인가 return을 받는다면 제대로 수행 된 것으로 봐도 좋다.)
$bx wsk action invoke read-cat –blocking –result –param docid test3

이것으로 read-cat action이 생성 되었다.

3. create-cat action 생성
read action과 크게 다르진 않지만 write action은 POST method로 data를 받을 것이다.
이것은 일종의 http 약속이다. 절대적으로 따라야 하는것은 아니지만 따르는게 좋다.
일반적으로 web programming을 할 경우, client에서 post 로 data를 보내면 server에서 post로 받아서 이를 handling 해야 한다.
openwhisk 에서는 client에서 http method를 무엇으로 하던 –web true 속성을 주면 json 형태로 data를 받을 수 있다.

1) create-cat.js 생성
아래와 같이 소스코드를 create-cat.js 란 이름으로 작성 하자.

var request = require('request');
var Cloudant = require('cloudant');
function main(params)
{
    var cloudant = new Cloudant({
        account:params.CLOUDANT_USERNAME,
        password:params.CLOUDANT_PASSWORD
    });
    var database = cloudant.db.use(params.CLOUDANT_DATABASE);
    var docId=params.docid||'InsertDoc';
    return new Promise(function(resolve, reject) {
    database.insert({name: 'JH',age:4,color:'yellow' }, docId,
        function(err, body) {
            if (err &&err.statusCode != 409) {
                console.log("Error within insert." + err);
                reject();
            } else {
                console.log("Success within  insert.");
                resolve();
            }
        }
    );
  });
}
exports.main = main;

2) action 생성
$bx wsk action create create-cat create-cat.js\
–param CLOUDANT_USERNAME “$CLOUDANT_USERNAME”\
–param CLOUDANT_PASSWORD “$CLOUDANT_PASSWORD” \
–param CLOUDANT_DATABASE “$CLOUDANT_DATABASE” –web true

참고) action의 web 속성을 raw로 주면 단순한 데이터 처리가 복잡해진다. 파일 전달과 같이 필요시에만 raw로 주고, 일반적으로는 –web true로 주면 된다. –web true로 주면 json 형태로 데이터를 받아서 처리 할 수 있다.

action 속성

http content-type

request body 형식

access 형태

–web true

application/x-www-form-urlencode

x-www-from-urlencode

param.key  가능

 –web true

application/json

x-www-from-urlencode

param.key  가능

 –web true

application/x-www-form-urlencode

form-data
(=multipart/form-data)

binary 로 전송됨.

–web true에서 사용 부적절.

–web raw

관계없음

관계 없음

__ow_body/ __ow_query에 담김.

pure text또는 binary 타입임.

참고: https://console.bluemix.net/docs/openwhisk/openwhisk_webactions.html#openwhisk_webactions

3) endpoint 생성 확인
endpoint 생성을 확인 하자. (command를 연습할겸 확인하는 command도 수행 해보자.)
$bx wsk action get create-cat –url

4) parameter가 셋팅되었는지 확인 하자.
$bx wsk action get create-cat –summary

5) action을 수행 해보자.
$bx wsk action invoke create-cat –blocking –result –param docid test4

6) action 수행 결과를 확인 하자.
read action을 통해 제대로 create 되었는지 확인 할 수 있다.
$bx wsk action invoke read-cat –blocking –result –param docid test4

7) 동일한 action을 http request를 통해 해보겠다.
get / post 둘다 해보자. (이후에 차이점을 보기 위해 get/post 둘다 수행)

(파란 부분은 자신의 action endpoint로 적어야 한다. )
$curl -X POST -H ‘Content-Type: application/json’ -d ‘{“docid”:”test6″}’ https://openwhisk.ng.bluemix.net/api/v1/00000000000.com_korea/default/create-cat

$curl -X GET -H ‘Content-Type: application/json’ https://openwhisk.ng.bluemix.net/api/v1/00000r.ibm.com_korea/default/create-cat?docid=test7

get 이건 post이건 모두 create가 동작 하는것을 볼 수 있다.
우리가 목표로 하는 것은 post에서만 동작 하도록 하는 것이다.
이 후 step에서 api gateway를 통해 method를 제한 해볼 것이다.

이것으로 create-cat action이 생성 되었다.

4. update-cat action 생성
cloudant에서는 insert command로 update를 수행 한다.
_id값과 , _rev 값을 꼭 줘야 한다.
id 값이 매칭 되는게 있으면 자동으로 update를 수행 하는 형태 이다.

1) create-cat 소스를 조금만 수정해서 만들어 보자.
docid외에 다른 속성값(?)을 변경가능하게 만들었다.

var request = require('request');
var Cloudant = require('cloudant'); 

function main(params)
{
    var cloudant = new Cloudant({
        account:params.CLOUDANT_USERNAME,
        password:params.CLOUDANT_PASSWORD
    });
 
    var database = cloudant.db.use(params.CLOUDANT_DATABASE);
    var docId=params.docid||'InsertDoc';
    var docname=params.name||'JH';
    var age=params.age||4;
    var color=params.color||'yellow';
    var revId=params.revid||' ';
    console.log(docId)
    console.log(docname)

    return new Promise(function(resolve, reject) {
        database.find({selector:{ "_id":docId }}, function(err, result) {
            if (err) return console.log(err.message);
            console.log('Find completed: ' + JSON.stringify(result));
            database.insert({_id:docId,_rev:result.docs[0]._rev,name: docname,age:age,color:color }, 
                function(err, body){
                    if (err && err.statusCode!=409){
                        console.log("Error within insert." + err);
                        reject();
                    } else {
                        console.log(body)
                        console.log("Success within  insert.");
                        resolve();
                    }
                }
            );
        });
    });
}

exports.main = main;

 

2) action 생성
$bx wsk action create update-cat update-cat.js \
–param CLOUDANT_USERNAME “$CLOUDANT_USERNAME” \
–param CLOUDANT_PASSWORD “$CLOUDANT_PASSWORD” \
–param CLOUDANT_DATABASE “$CLOUDANT_DATABASE” –web true

3) endpoint 생성 확인
endpoint 생성을 확인 하자. (command를 연습할겸 확인하는 command도 수행 해보자.)
$bx wsk action get update-cat –url

4) action을 수행 해보자.
$bx wsk action invoke update-cat –blocking –result –param docid test4 –param name Damon33

5) action 수행 결과를 확인 하자.
read action을 통해 제대로 create 되었는지 확인 할 수 있다.
$bx wsk action invoke read-cat –blocking –result –param docid test4

6) 동일한 액션을 http request로 해보자.
update action은 patch 또는 put method를 사용한다. 여기서는 put을 사용하겠다.

(파란 부분은 자신의 action endpoint로 적어야 한다. )
$curl -X PUT -H ‘Content-Type: application/json’ -d ‘{“docid”:”test4″,”name”:”damon44″}’ https://openwhisk.ng.bluemix.net/api/00000000000.com_korea/default/update-cat

이렇게 update-cat action이 생성 되었다.

5. delete-cat action 생성
마지막으로 delete action을 구현 해보자.

1) 아래 소스로 delete-cat.js 파일을 만들자.

var request = require('request');
var Cloudant = require('cloudant');

function main(params)
{
    var cloudant = new Cloudant({
        account: params.CLOUDANT_USERNAME,
        password: params.CLOUDANT_PASSWORD
    });

    var database = cloudant.db.use(params.CLOUDANT_DATABASE);
    var docId=params.docid||'InsertDoc';
    var revId=params.revid||' ';
    console.log(docId)
    console.log(docname)

    return new Promise(function(resolve, reject) {
        database.find({selector:{ "_id":docId }}, function(err,result) {
            if (err) return console.log(err.message);
            
            database.destroy(docId,result.docs[0]._rev), 
                function(err) {
                    if (err && err.statusCode!=409){
                        console.log("Error within insert." + err);
                        reject();
                    } else {
                        console.log("Success within  insert.");
                        resolve();
                    }
                }
        });
    });
}

exports.main = main;

2) action 생성
$bx wsk action create delete-cat delete-cat.js \
–param CLOUDANT_USERNAME “$CLOUDANT_USERNAME” \
–param CLOUDANT_PASSWORD “$CLOUDANT_PASSWORD” \
–param CLOUDANT_DATABASE “$CLOUDANT_DATABASE” –web true

3) endpoint 생성 확인
endpoint 생성을 확인 하자. (command를 연습할겸 확인하는 command도 수행 해보자.)
$bx wsk action get delete-cat –url

4) action을 수행 해보자.
$bx wsk action invoke delete-cat –blocking –result –param docid test4

5) action 수행 결과를 확인 하자.
read action을 통해 제대로 create 되었는지 확인 할 수 있다.
$bx wsk action invoke read-cat –blocking –result –param docid test4

6) 동일한 액션을 http request로 해보자.
delete action은 delete method를 사용한다.

(파란 부분은 자신의 action endpoint로 적어야 한다. )
$curl -X DELETE -H ‘Content-Type: application/json’ -d ‘{“docid”:”test4″}’ https://openwhisk.ng.bluemix.net/api/00000000000000.com_korea/default/delete-cat

[3rd: CRUD api gateway endpoint생성]
api endpoint를 만들편 api gateway를 통해 action이 수행 된다.
이전 랩에서 공부 했듯이 action의 ulr 을 바로 사용하는것보다 api gateway를 통하는게 여러가지로 장점이 많다.

1. Create api endpoint
http method를 적절히 매치하여 endpoint를 만들것이다.

$bx wsk api create -n “Cats API” /v1 /cat post create-cat
생성됨과 동시에 endpoint를 확인 할 수 있다.

나머지 action도 같은 방식으로 api endpoint를 만들자.

$bx wsk api create /v1 /cat put update-cat
$bx wsk api create /v1 /cat get read-cat
$bx wsk api create /v1 /cat delete delete-cat

2. api list 확인
만들어진 endpoint를 확인하자.
$bx wsk api list

/xxx@xxx.xxx.com_korea/read-cat       get  Cats API  https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

/xxx@xx.xxx.com_korea/update-cat     put  Cats API  https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

/xxx@xx.xxx.com_korea/create-cat      post  Cats API  https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

/xxx@xx.xxx.com_korea/delete-cat       delete  Cats API  https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

CRUD 4개의 url이모두 동일하다. method만 달리해서 같은 api endpoint가 되었다.

3. Test api endpoint
이제 각 action이 제대로 동작하는지 확인해 보자.
앞선 과정중 create-cat endpoint에 get과 post 방식 모두 동작 했었던 것을 기억해보자.
api endpoint를 통하면 method가 지정되기때문에 지정된 method를 사용해 access해야만 제대로 동작 하게 될 것이다.

먼저 post action이 잘 동작해는 수행 해보자.
(파란 부분은 자신의 endpoint url 로.)
$curl -X POST -H ‘Content-Type: application/json’ -d ‘{“docid”:”test9″}’ https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

확인을 위해 read api endpoint를 호출 해보자. (이건 브라우저에서 해보자)
https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat?docid=test9

잘 동작 한 것을 확인 할 수 있다.

update action과 delete action도 수행 해해보자.
(파란 부분은 자신의 action endpoint로 적어야 한다. )
$curl -X PUT -H ‘Content-Type: application/json’ -d ‘{“docid”:”test9″,”name”:”damon99″}’ https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

$curl -X DELETE -H ‘Content-Type: application/json’ -d ‘{“docid”:”test9″}’ https://service.us.apiconnect.ibmcloud.com/gws/apigateway/api/7bbe0aa3d0ab81a7ad43ddc9c03db9e0533d077842fb3645c22ec43323d59363/v1/cat

지금까지 openwhisk action에 api endpoint를 연결하여 rest api 를 만들어 보았다.
다음 랩은 지금까지 진행한 lab을 좀 더 효율적으로 개발 할 수 있게 해주는 severless framework 에 대해 알아 볼 것이다.

참고:
https://console.bluemix.net/docs/openwhisk/openwhisk_apigateway.html#creating-serverless-rest-apis
https://github.com/jzaccone/ogs-serverless-apis
https://github.com/IBM/ibm-cloud-functions-serverless-apis

토론 참가

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.