Open PaaS에 등록된 다양한 서비스팩을 Go언어로 작성된 애플리케이션과 바인딩하고 해당 애플리케이션에 바인딩된 환경정보(VCAP_SERVICES)에서 각 서비스별 접속정보를 획득하여 애플리케이션에 적용하여 이용 할 수 있도록 Windows 환경에서 Go 애플리케이션을 작성 할 수 있도록한다.
2.2. 개발환경 구성
Go 애플리케이션 개발을 위해 다음과 같은 환경으로 개발환경을 구성 한다.
OS : Windows 7 64bit
Go : 1.5.2
IDE : Intellij IDEA
Intellij IDEA 는 Commnuity와 Ultimate 버전이 있는데, Community 버전은 Free이고, Ultimate 버전은 은 30-day trial버전이다.
func sample_function_name() string {
args := os.Getenv("VCAP_SERVICES") //VCAP_SERVICES 엘리먼트 정보 (부모 엘리먼트)
var amqp_uri string
if args != "" {
var vcap_env map[string]interface{}
if err := json.Unmarshal([]byte(args), &vcap_env); err != nil {
log.Panic(err.Error())
}
//Service instance (not name) - for example : p-mysql - type check !!! []interface{}
if vcap_env["p-rabbitmq"] != nil { //첫번째 엘리먼트(서비스 이름) 정보
sub_env := vcap_env["p-rabbitmq"].([]interface{})
credentials := (sub_env[0].(map[string]interface{}))["credentials"].(map[string]interface{})
//두번째 엘리먼트 “credentials” 정보
amqp_uri = credentials["uri"].(string) //세번째 엘리먼트 “uri”정보
}
}
return amqp_uri
}
VCAP_SERVICES 구조 참조
2.3.4. config.ini 파일을 통한 Database, Redis, RabbitMQ 연동
1). config.ini
mysql 연결정보 설정
#Go Sample Web Server port
server.port = 8080
#Mysql DB Info
mysql.dburl=”mysql\_server\_ip”:”mysql\_server\_port”/”database\_name”
mysql.userid=”user\_id”
mysql.userpwd=”user\_password”
mysql.maxconn=”max\_connection\_number”
MongoB Info
mongodb.dburl=”mongodb\_server\_ip”: ”mongodb\_server\_port”/”collection\_name”
mongodb.userid=”user\_id”
mongodb.userpwd=”user\_password”
# Redis Info
redis.addr=”redis\_server\_ip”: ”redis\_server\_port”
# RabbitMQ Info
rabbitmq.user=”rabbitmq\_id”
rabbitmq.pass=”rabbitmq\_password”
rabbitmq.addr=”rabbitmq\_server\_ip”: ”rabbitmq\_server\_port”
2). 연동 샘플
import (
"bufio"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"net/http"
"encoding/json"
"org/openpaas/sample/Godeps/_workspace/src/gopkg.in/redis.v3"
"org/openpaas/sample/datasource"
"org/openpaas/sample/handler"
"org/openpaas/sample/message"
)
type Config map[string]string
func main() {
// Datasource - MySql, Cubrid, MongoDB 타입별 처리
var dbconfig *datasource.DBConfig
var mgodbconfig *datasource.MgoDBConfig
var handlers http.Handler
fmt.Println("##### Go Sample Application start!!!")
//============================================
// dbtype 정보는 시스템 프로퍼티에서 가져온다.
dbtype := os.Getenv("dbtype")
//============================================
//============================================
// Sample VCAP_SERVICE INFO Parsing
os_args := os.Getenv("VCAP_SERVICES")
readOSEnvironment(os_args)
//============================================
//============================================
// 기본적인 프로퍼티 설정 정보 읽어오기
config, err := ReadConfig(`config.ini`)
if err != nil {
fmt.Println(err)
}
//============================================
// Default Redis Client Create - For Login & Logout
redis_client := initRedis(config["redis.addr"])
defer redis_client.Close()
// default dbytype = "mysql"
if dbtype == "" {
dbtype = "mysql"
}
// RabbitMQ
//endpoint := "amqps://929b5a98-6521-4da5-86c1-0fcaa2450a86:55dgq7ocf1gtiamqum0hb9p8be@10.244.9.50:5671/3c14abdc-c922-428c-af70-d61eb91ef818"
endpoint := readOSEnvironment_mq()
fmt.Println("########## credentials-uri:", endpoint)
mq := message.NewRabbitMQ(endpoint)
if mq != nil {
defer message.CloseMQ(mq)
}
// DB Initialize -
// DB 타입별로 Connection 처리
if dbtype == "mysql" {
maxConnection, err := strconv.Atoi(config["mysql.maxconn"])
if err != nil {
log.Println(err)
os.Exit(-1)
}
dbconfig = datasource.NewDBConfig(config["mysql.userid"], config["mysql.userpwd"], config["mysql.dburl"], maxConnection)
defer dbconfig.CloseDb()
fmt.Println("dbmap:", dbconfig.DBMAP)
if dbconfig.DBMAP == nil {
log.Panic("Couldn't create Database Connection properly - MySQL!!!")
os.Exit(-1)
}
// Route Path 정보와 처리 서비스 연결
handlers = handler.NewHandler(dbconfig.DBMAP, redis_client, mq.Ch)
} else if dbtype == "mongodb" {
mgodbconfig = datasource.NewMgoDBConfig(config["mongodb.userid"], config["mongodb.userpwd"], config["mongodb.dburl"])
defer mgodbconfig.CloseDb()
fmt.Println("session:", mgodbconfig.SESSION)
if mgodbconfig.SESSION == nil {
log.Panic("Couldn't create Database Connection properly - MongoDB!!!")
os.Exit(-1)
}
// Route Path 정보와 처리 서비스 연결
handlers = handler.NewMgoHandler(mgodbconfig.SESSION, redis_client, mq.Ch)
} else {
fmt.Println("No database type found.")
os.Exit(-1)
}
if err := http.ListenAndServe(fmt.Sprintf(":%v", config["server.port"]), handlers); err != nil {
log.Fatalln(err)
}
}
/*
Read Config file
*/
func ReadConfig(filename string) (Config, error) {
// init with some bogus data
config := Config{
"server.ip": "127.0.0.1",
"server.port": "8080",
"mysql.dburl": "",
"mysql.userid": "",
"mysql.userpwd": "",
"mysql.maxconn": "",
}
if len(filename) == 0 {
return config, nil
}
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n')
// check if the line has = sign
// and process the line. Ignore the rest.
if equal := strings.Index(line, "="); equal >= 0 {
if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
value := ""
if len(line) > equal {
value = strings.TrimSpace(line[equal+1:])
}
// assign the config map
config[key] = value
}
}
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
}
return config, nil
}
func initRedis(addr string) *redis.Client {
client := redis.NewClient(&redis.Options{
Addr: addr,
})
return client
}
func readOSEnvironment_gf() (string, string, string, string) {
args := os.Getenv("VCAP_SERVICES")
var userName, password, authUrl, tenantName string
if args != "" {
var vcap_env map[string]interface{}
if err := json.Unmarshal([]byte(args), &vcap_env); err != nil {
log.Panic(err.Error())
}
//Service instance (not name) - for example : p-mysql - type check !!! []interface{}
if vcap_env["glusterfs"] != nil {
sub_env := vcap_env["glusterfs"].([]interface{})
credentials := (sub_env[0].(map[string]interface{}))["credentials"].(map[string]interface{})
userName = credentials["username"].(string)
password = credentials["password"].(string)
authUrl = credentials["auth_url"].(string)
tenantName = credentials["tenantname"].(string)
}
}
return userName, password, authUrl, tenantName
}
2.4. 배포
cf cli 명령어를 이용하여 Go 샘플 어플리케이션을 배포한다.
cf cli가 설치되어 있고, cf login이 이미 되어 있다는 가정하에 진행한다.
### Go 샘플 어플리케이션 배포
$ cd “Go 샘플 어플리케이션” 디렉토리
$ source .envrc # GO_PATH를 지정하기 위해
$ cd src/org/openpaas/sample
$ cf push –f manifest.yml # Go 샘플 어플리케이션 배포
Using manifest file manifest.yml
Creating app go-sample in org org / space space as admin...
OK
Using route go-sample.os.paasxpert.com
Binding go-sample.os.paasxpert.com to go-sample...
OK
Uploading go-sample...
Uploading app files from: /home/ihocho/git/OpenPaaSSample/GoSample/go-sample-app/src/org/openpaas/sample
Uploading 854.2K, 185 files
Done uploading
OK
Binding service rabbitmq-service-instance to app go-sample in org org / space space as admin...
OK
Starting app go-sample in org org / space space as admin...
Creating container
Successfully created container
Downloading app package...
Downloaded app package (321.1K)
Downloading buildpacks (https://github.com/cloudfoundry/go-buildpack.git)...
Downloaded buildpacks
Staging...
-------> Buildpack version 1.7.0
https://pivotal-buildpacks.s3.amazonaws.com/concourse-binaries/godep/godep-v17-linux-x64.tgz
-----> Checking Godeps/Godeps.json file.
-----> Installing go1.4.2... done
Downloaded [https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz]
-----> Running: godep go install -tags cloudfoundry ./...
Exit status 0
Staging complete
Uploading droplet, build artifacts cache...
Uploading droplet...
Uploading build artifacts cache...
Uploaded build artifacts cache (60M)
Uploaded droplet (2.8M)
Uploading complete
1 of 1 instances running
App started
OK
App go-sample was started using this command `sample`
Showing health and status for app go-sample in org org / space space as admin...
OK
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: go-sample.os.paasxpert.com
last uploaded: Mon Dec 14 04:39:52 UTC 2015
stack: cflinuxfs2
buildpack: https://github.com/cloudfoundry/go-buildpack.git
state since cpu memory disk details
#0 running 2015-12-14 01:41:20 PM 0.0% 2.1M of 256M 0 of 1G
Go 샘플 애플리케이션에의 데이터 관리는 MySQL, MongoDB 중에 하나를 이용하기 때문에 배포시 환경변수 정보(dbtype)에 데이터베이스 이름(mysql or mongodb)를 설정하여 배포한다..
2.5. 테스트
curl 명령어를 통해 command 창에서 직접 테스트 할 수 있다.
### 모든 조직정보 조회
curl -v http://”depolyed_sample_app_name”/orgs
### 특정 조직정보 조회
curl -v http:// ”depolyed_sample_app_name”/orgs/{org_id}
### 조직 생성
curl -X POST -v
–d '{"id":”org_id”,"label":"org_lable_info","desc":"org_description_info","url":"org_uri_info"}'
http:// ”depolyed_sample_app_name”/orgs
### 조직 수정
curl -X PUT -v
-d '{"label":" org_lable_info ","desc":"org_description_info","url":"org_url_info"}'
http:// ”depolyed_sample_app_name”/orgs/{org_id}
### 조직 삭제
curl -X DELETE -v http:// ”depolyed_sample_app_name”/orgs/{org_id}