@ -0,0 +1,79 @@ | |||
# 接口 | |||
```bash | |||
IP: 192.168.100.50 | |||
PORT: 8000 | |||
HOST: baidu-link-submit-ms.juejin.im | |||
``` | |||
## 资源创建通知 | |||
### 请求 | |||
`POST /v1/events/created` | |||
### 参数 | |||
```bash | |||
# 格式 | |||
Content-Type: application/json; charset=utf-8 | |||
{ | |||
type, | |||
id | |||
} | |||
``` | |||
```bash | |||
# 说明 | |||
type := 'link' | 'column' | |||
# type -> 资源类型,必需 | |||
# link -> 链接 | |||
# column -> 专栏 | |||
id := <string> | |||
# id -> 资源 ID,必需 | |||
``` | |||
### 响应 | |||
```bash | |||
{ | |||
"s": 1, | |||
"m": "success", | |||
"d": [] | |||
} | |||
``` | |||
### 示例 | |||
```bash | |||
# 专栏文章创建后 | |||
POST http://192.168.100.50:8000/v1/events/created HTTP/1.1 | |||
Host: baidu-link-submit-ms.juejin.im | |||
Content-Type: application/json | |||
{ | |||
"type": "column", | |||
"id": "5ac9dc9af265da23884d5543" | |||
} | |||
``` | |||
## 资源更新通知 | |||
### 请求 | |||
`POST /v1/events/updated` | |||
其余同上。 | |||
## 资源删除通知 | |||
### 请求 | |||
`POST /v1/events/deleted` | |||
其余同上。 |
@ -1,2 +1 @@ | |||
# hi-guoqian-go-ms | |||
guoqian Go->redis |
@ -0,0 +1,58 @@ | |||
# baidu_link_submit_ms.private.conf | |||
# baidu_link_submit_ms nginx config file. | |||
# | |||
# This file auto generated by baidu_link_submit_ms/scripts/init_config.sh, | |||
# [WARRING!] DO NOT change this manualy. | |||
# | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
upstream baidu_link_submit_ms_private { | |||
server 127.0.0.1:10100; | |||
keepalive 64; | |||
} | |||
server { | |||
listen 8000; | |||
server_name baidu-link-submit-ms.juejin.im; | |||
default_type 'text/plain'; # or browser will download page | |||
include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; | |||
root /data/repo/baidu_link_submit_ms; | |||
access_log /data/repo/baidu_link_submit_ms/logs/nginx-access.public.log logstash; | |||
error_log /data/repo/baidu_link_submit_ms/logs/nginx-error.public.log; | |||
client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; | |||
proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; | |||
# X-Juejin-Src for api src trace back | |||
# X-Juejin-Uid for non-login user id | |||
# X-Juejin-Token for api param hash check | |||
add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; | |||
if ($request_method = OPTIONS ) { | |||
return 200; | |||
} | |||
# global location settings | |||
location /status { | |||
return 200; | |||
} | |||
location / { | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header Host $http_host; | |||
proxy_set_header X-Nginx-Proxy true; | |||
proxy_pass http://baidu_link_submit_ms_private; | |||
} | |||
location ~ /\. { | |||
deny all; | |||
access_log off; | |||
log_not_found off; | |||
} | |||
} |
@ -0,0 +1,58 @@ | |||
# baidu_link_submit_ms.public.conf | |||
# baidu_link_submit_ms nginx config file. | |||
# | |||
# This file auto generated by baidu_link_submit_ms/scripts/init_config.sh, | |||
# [WARRING!] DO NOT change this manualy. | |||
# | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
upstream baidu_link_submit_ms_public { | |||
server 127.0.0.1:10100; | |||
keepalive 64; | |||
} | |||
server { | |||
listen 80; | |||
server_name baidu-link-submit-ms.juejin.im; | |||
default_type 'text/plain'; # or browser will download page | |||
include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; | |||
root /data/repo/baidu_link_submit_ms; | |||
access_log /data/repo/baidu_link_submit_ms/logs/nginx-access.public.log logstash; | |||
error_log /data/repo/baidu_link_submit_ms/logs/nginx-error.public.log; | |||
client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; | |||
proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; | |||
# X-Juejin-Src for api src trace back | |||
# X-Juejin-Uid for non-login user id | |||
# X-Juejin-Token for api param hash check | |||
add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; | |||
if ($request_method = OPTIONS ) { | |||
return 200; | |||
} | |||
# global location settings | |||
location /status { | |||
return 200; | |||
} | |||
location / { | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header Host $http_host; | |||
proxy_set_header X-Nginx-Proxy true; | |||
proxy_pass http://baidu_link_submit_ms_public; | |||
} | |||
location ~ /\. { | |||
deny all; | |||
access_log off; | |||
log_not_found off; | |||
} | |||
} |
@ -0,0 +1 @@ | |||
1 |
@ -0,0 +1,12 @@ | |||
[Unit] | |||
Description = Micro Service API | |||
After = syslog.target network.target | |||
[Service] | |||
PIDFile = /data/repo/baidu_link_submit_ms/lock/baidu_link_submit_ms.pid | |||
ExecStart = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta | |||
ExecReload = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta reload | |||
ExecStop = /data/repo/baidu_link_submit_ms/bin/baidu_link_submit_ms beta stop | |||
[Install] | |||
WantedBy=multi-user.target |
@ -0,0 +1 @@ | |||
1 |
@ -0,0 +1,82 @@ | |||
#!/bin/sh | |||
# ci.sh | |||
# This script for build go projects. | |||
# @version 170327:2 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [ci] | |||
echo "-[ci]-" | |||
echo "start" | |||
# ----------------------------[manual config here]------------------------------ | |||
# base config | |||
REPO_SRC=/data/repo/baidu_link_submit_ms | |||
BUILD_TARGET=baidu_link_submit_ms | |||
# fetch source config | |||
go_packages=( | |||
"github.com/astaxie/beego" | |||
) | |||
http_proxy="" | |||
# deploy config | |||
DEPLOY_SRC=/data/repo | |||
DEPLOY_LOG_SRC=/data/logs | |||
ACTION=$1 | |||
RELEASE_ENV=$2 | |||
DEV_ENV_LOCATION=( | |||
"root@192.168.0.203" | |||
) | |||
BETA_ENV_LOCATION=( | |||
"root@192.168.0.222" | |||
) | |||
ONLINE_ENV_LOCATION=( | |||
"root@192.168.100.42" # microservice03v | |||
"root@192.168.100.44" # microservice04v | |||
"root@192.168.100.46" # microservice04v | |||
) | |||
# ------------------------------------------------------------------------------ | |||
# check if release env fit repo src | |||
NOW_PWD=`pwd` | |||
if [ "$NOW_PWD" != "${REPO_SRC}/scripts" ] && [ "$NOW_PWD" != "${REPO_SRC}" ]; then | |||
echo -e "\033[43m[WARRING!] PWD is ${NOW_PWD}, but REPO_SRC is ${REPO_SRC} \033[0m"; | |||
echo -e "please check your REPO_SRC config to make sure that you config this file correctly."; | |||
exit 1; | |||
fi | |||
# run scripts | |||
SCRIPTS_SRC="${REPO_SRC}/scripts/ci" | |||
if [ "${ACTION}" == "build" ]; then | |||
. "${SCRIPTS_SRC}/fetch_source.sh" | |||
. "${SCRIPTS_SRC}/build.sh" | |||
elif [ "${ACTION}" == "release" ]; then | |||
. "${SCRIPTS_SRC}/fetch_source.sh" | |||
. "${SCRIPTS_SRC}/build.sh" | |||
. "${SCRIPTS_SRC}/deploy.sh" | |||
elif [ "${ACTION}" == "run_bee" ]; then | |||
. "${SCRIPTS_SRC}/run_bee.sh" | |||
else | |||
echo "usage:" | |||
echo "./ci.sh [action: build/release/run_bee] [beta/online/bee_path]" | |||
echo "" | |||
echo "e.g." | |||
echo "./ci.sh release beta" | |||
echo "" | |||
fi | |||
echo "end" | |||
@ -0,0 +1,72 @@ | |||
#!/bin/sh | |||
# build.sh | |||
# This script for build go projects. | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [config] | |||
echo "-[config]-" | |||
# ----------------------------[manual config here]------------------------------ | |||
# REPO_SRC=/data/repo/collection_set_api | |||
# BUILD_TARGET=collection_set_api | |||
# ------------------------------------------------------------------------------ | |||
echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" | |||
echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" | |||
echo "" | |||
sleep 1 | |||
# [set env] | |||
echo "-[set env]-" | |||
# $GOBIN | |||
export GOBIN="${REPO_SRC}/bin" | |||
echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" | |||
# $GOPATH | |||
export GOPATH="${REPO_SRC}" | |||
echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" | |||
echo "" | |||
sleep 1 | |||
# [check old build target] | |||
echo "-[check old build target]-" | |||
if [ ! -d $GOBIN ]; then mkdir $GOBIN; fi | |||
if [ -f "${GOBIN}/${BUILD_TARGET}" ]; then | |||
echo -e "\033[43m[WARRING!] build target alerady exists, will remove it. \033[0m"; | |||
echo "old build_target detail:" | |||
ls -alh "${GOBIN}/${BUILD_TARGET}"; | |||
oldShaSum=`shasum "${GOBIN}/${BUILD_TARGET}" | awk -F' ' '{print $1}'`; | |||
echo "target sha: ${oldShaSum}"; | |||
rm -rf "${GOBIN}/${BUILD_TARGET}"; | |||
echo "old build target removed."; | |||
fi | |||
echo "done." | |||
echo "" | |||
sleep 1 | |||
# [build] | |||
echo "-[build]-" | |||
echo "build start: " | |||
echo "go build -o ${GOBIN}/${BUILD_TARGET}" | |||
cd "${GOPATH}/src" | |||
go build -o "${GOBIN}/${BUILD_TARGET}" | |||
ls -alh "${GOBIN}/${BUILD_TARGET}" | |||
newShaSum=`shasum "${GOBIN}/${BUILD_TARGET}" | awk -F' ' '{print $1}'`; | |||
echo "target sha: ${newShaSum}"; | |||
if [ "$oldShaSum" == "$newShaSum" ];then | |||
echo -e "\033[43m[WARRING!] old build target shasum is equals to new build target. \033[0m" | |||
fi | |||
echo "done." | |||
@ -0,0 +1,181 @@ | |||
#!/bin/sh | |||
# deploy.sh | |||
# This script deploy repo to target env. | |||
# @version 170322:2 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [start deploy] | |||
echo "-[start deploy]-" | |||
# ----------------------------[manual config here]------------------------------ | |||
# REPO_SRC=/data/repo/collection_set_api | |||
# BUILD_TARGET=collection_set_api | |||
# DEPLOY_SRC=/data/repo | |||
# DEPLOY_LOG_SRC=/data/logs | |||
# RELEASE_ENV=$1 | |||
# | |||
# DEV_ENV_LOCATION=( | |||
# "root@192.168.0.203" | |||
# ) | |||
# BETA_ENV_LOCATION=( | |||
# "root@192.168.0.204" | |||
# ) | |||
# ONLINE_ENV_LOCATION=( | |||
# "root@192.168.100.32" # microservice03v | |||
# "root@192.168.100.28" # microservice04v | |||
# ) | |||
# ------------------------------------------------------------------------------ | |||
# final release location | |||
RELEASE_ENV_LOCATION="" | |||
# release file temp storage location | |||
RELEASE_TEMP_DIR=/data/repo/release | |||
# program system service name for systemctl | |||
SERVICE_NAME="${BUILD_TARGET}.service" | |||
# final deploy src | |||
FINAL_DEPLOY_SRC="${DEPLOY_SRC}/${BUILD_TARGET}" | |||
# nginx config | |||
NGINX_BIN_LOCATION="/data/apps/nginx/sbin/nginx" | |||
NGINX_CONFIG_LOCATION="/data/apps/nginx/conf/vhost/" | |||
# deploy target machine error handler config | |||
DEPLOY_ERROR_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_error.s" | |||
DEPLOY_SUCCESS_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_success.s" | |||
DEPLOY_LOG="${FINAL_DEPLOY_SRC}/logs/deploy.log" | |||
# print config | |||
echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" | |||
echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" | |||
echo -e "\033[34mRELEASE_TEMP_DIR set to: ${RELEASE_TEMP_DIR}\033[0m" | |||
echo -e "\033[34mPROJECT WILL DEPLOY TO: ${FINAL_DEPLOY_SRC}\033[0m" | |||
echo -e "\033[34mSERVICE_NAME set to: ${SERVICE_NAME}\033[0m" | |||
echo "" | |||
sleep 2 | |||
# [check input] | |||
if [ "$RELEASE_ENV" == "dev" ]; then | |||
RELEASE_ENV_LOCATION=${DEV_ENV_LOCATION[*]} | |||
elif [ "$RELEASE_ENV" == "beta" ]; then | |||
RELEASE_ENV_LOCATION=${BETA_ENV_LOCATION[*]} | |||
elif [ "$RELEASE_ENV" == "online" ]; then | |||
RELEASE_ENV_LOCATION=${ONLINE_ENV_LOCATION[*]} | |||
else | |||
RELEASE_ENV_LOCATION="" | |||
fi | |||
if [ "$RELEASE_ENV_LOCATION" == "" ]; then | |||
echo "please input an avaliable deploy environment [dev/beta/online]"; | |||
echo "example: ./deploy.sh beta"; | |||
exit 1; | |||
fi | |||
echo -e "\033[34mRELEASE_ENV set to: ${RELEASE_ENV} \033[0m" | |||
echo -e "\033[34mRELEASE_ENV_LOCATION set to: \033[0m" | |||
for releaseLocation in ${RELEASE_ENV_LOCATION[*]}; | |||
do | |||
echo -e "\033[34m ${releaseLocation} \033[0m" | |||
done | |||
echo "" | |||
sleep 1 | |||
# [check old release file] | |||
echo "-[check old release target]-" | |||
if [ ! -d $RELEASE_TEMP_DIR ]; then mkdir $RELEASE_TEMP_DIR; fi | |||
if [ -f "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" ]; then | |||
echo -e "\033[43m[WARRING!] release target alerady exists, will remove it. \033[0m"; | |||
ls -alh "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; | |||
oldShaSum=`shasum "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" | awk -F' ' '{print $1}'`; | |||
echo "target sha: ${oldShaSum}"; | |||
rm -f "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; | |||
echo "old build target removed."; | |||
fi | |||
echo "" | |||
sleep 1 | |||
# [compress new release file] | |||
echo "-[compress new release file]-" | |||
cd $REPO_SRC; | |||
tar -zcf "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" "./" | |||
ls -alh "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz"; | |||
newShaSum=`shasum "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" | awk -F' ' '{print $1}'`; | |||
echo "target sha: ${newShaSum}"; | |||
if [ "$oldShaSum" == "$newShaSum" ];then | |||
echo -e "\033[43m[WARRING!] old release target shasum is equals to new release target. \033[0m" | |||
fi | |||
echo "" | |||
sleep 1 | |||
# [deploy] | |||
echo "-[deploy]-" | |||
echo "- coyp to target machine" | |||
for releaseLocation in ${RELEASE_ENV_LOCATION[*]}; | |||
do | |||
echo -e "\033[34m deploy to ${releaseLocation} \033[0m"; | |||
ssh -T $releaseLocation <<DEPLOY_INIT_SCRIPTS_1 | |||
if [ ! -d $FINAL_DEPLOY_SRC ]; then mkdir $FINAL_DEPLOY_SRC; fi | |||
if [ -f ${FINAL_DEPLOY_SRC}/${BUILD_TARGET}.tar.gz ]; then | |||
rm -f ${FINAL_DEPLOY_SRC}/${BUILD_TARGET}.tar.gz; | |||
fi | |||
DEPLOY_INIT_SCRIPTS_1 | |||
scp "${RELEASE_TEMP_DIR}/${BUILD_TARGET}.tar.gz" "${releaseLocation}:${FINAL_DEPLOY_SRC}/"; | |||
ssh -T $releaseLocation <<DEPLOY_INIT_SCRIPTS_2 | |||
cd "${FINAL_DEPLOY_SRC}/"; | |||
tar -zxvf "./${BUILD_TARGET}.tar.gz"; | |||
DEPLOY_INIT_SCRIPTS_2 | |||
done | |||
echo "done." | |||
echo "" | |||
echo "-[configure & reactive service]-" | |||
i=0 | |||
for releaseLocation in ${RELEASE_ENV_LOCATION[*]}; | |||
do | |||
# sleep for online lvs reconnect nginx | |||
if [ "$i" != "0" ]; then | |||
echo "sleep 120 seconds for online lvs reconnect nginx."; | |||
sleep 120; | |||
fi | |||
# deploy start | |||
echo -e "\033[34mconfigure ${releaseLocation} \033[0m" | |||
ssh -T $releaseLocation <<DEPLOY_SCRIPTS_1 | |||
# exec reactive scripts | |||
chmod +x "${FINAL_DEPLOY_SRC}/scripts/ci/reactive_service.sh"; | |||
bash "${FINAL_DEPLOY_SRC}/scripts/ci/reactive_service.sh" ${REPO_SRC} ${BUILD_TARGET} ${DEPLOY_SRC} ${DEPLOY_LOG_SRC} ${RELEASE_ENV}; | |||
DEPLOY_SCRIPTS_1 | |||
#check deploy result | |||
isDeploySuccess="" | |||
isDeploySuccess=`ssh -T $releaseLocation <<DEPLOY_SCRIPTS_2 | |||
cat $DEPLOY_SUCCESS_SIGNAL_FILE | |||
DEPLOY_SCRIPTS_2` | |||
if [ "${isDeploySuccess}" != "success" ]; then | |||
echo -e "\033[43m[ERROR!] deploy failed detected. Failed at : ${releaseLocation}\033[0m"; | |||
echo "please check release log at : ${releaseLocation}${DEPLOY_LOG}"; | |||
echo "script exit."; | |||
exit 1; | |||
else | |||
echo -e "\033[32m[OK] deploy success. deploy at : ${releaseLocation}\033[0m"; | |||
fi | |||
# counter | |||
i=$(expr "$i" + "1"); | |||
done | |||
echo "done."; | |||
exit 0; | |||
@ -0,0 +1,71 @@ | |||
#!/bin/sh | |||
# fetch_source.sh | |||
# This script for fetch source and packages. | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [config] | |||
echo "-[config]-" | |||
# ----------------------------[manual config here]------------------------------ | |||
# REPO_SRC=/data/repo/collection_set_api | |||
go_packages=( | |||
"github.com/astaxie/beego" | |||
"github.com/garyburd/redigo/redis" | |||
) | |||
# | |||
# http_proxy="http://localhost:8123" | |||
# ------------------------------------------------------------------------------ | |||
# init env | |||
# $GOBIN | |||
export GOBIN="${REPO_SRC}/bin" | |||
echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" | |||
# $GOPATH | |||
export GOPATH="${REPO_SRC}" | |||
echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" | |||
# print package list | |||
echo "package list:" | |||
for pkg in ${go_packages[*]}; | |||
do | |||
echo -e "\033[34m${pkg}\033[0m"; | |||
done | |||
echo "" | |||
if [ "$http_proxy" != "" ]; then | |||
echo "http_proxy set to:" | |||
echo -e "\033[34m${http_proxy}\033[0m"; | |||
echo "http_proxy location info:" | |||
proxyLocation=`http_proxy=${http_proxy} curl -s ip.gs` | |||
echo -e "\033[34m${proxyLocation}\033[0m"; | |||
fi | |||
echo "" | |||
sleep 1 | |||
# [fetch] | |||
echo "-[fetch package]-" | |||
for pkg in ${go_packages[*]}; | |||
do | |||
if [ "$http_proxy" == "" ]; then | |||
echo "go get ${pkg}"; | |||
go get $pkg; | |||
else | |||
echo "http_proxy=${http_proxy} go get ${pkg}"; | |||
http_proxy=${http_proxy} go get $pkg; | |||
fi | |||
done | |||
echo "done." |
@ -0,0 +1,183 @@ | |||
#!/bin/sh | |||
# reactive_service.sh | |||
# This script for reactive this projects. | |||
# @version 170327:3 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [config] | |||
echo "-[config]-" | |||
# ----------------------------[manual config here]------------------------------ | |||
REPO_SRC=$1 | |||
BUILD_TARGET=$2 | |||
DEPLOY_SRC=$3 | |||
DEPLOY_LOG_SRC=$4 | |||
RELEASE_ENV=$5 | |||
# ------------------------------------------------------------------------------ | |||
# program system service name for systemctl | |||
SERVICE_NAME="${BUILD_TARGET}.service" | |||
# final deploy src | |||
FINAL_DEPLOY_SRC="${DEPLOY_SRC}/${BUILD_TARGET}" | |||
# nginx config | |||
NGINX_BIN_LOCATION="/data/apps/nginx/sbin/nginx" | |||
NGINX_CONFIG_LOCATION="/data/apps/nginx/conf/vhost/" | |||
# deploy target machine error handler config | |||
DEPLOY_ERROR_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_error.s" | |||
DEPLOY_SUCCESS_SIGNAL_FILE="${FINAL_DEPLOY_SRC}/logs/deploy_success.s" | |||
DEPLOY_LOG="${FINAL_DEPLOY_SRC}/logs/deploy.log" | |||
# print config | |||
echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" | |||
echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" | |||
echo -e "\033[34mPROJECT WILL DEPLOY TO: ${FINAL_DEPLOY_SRC}\033[0m" | |||
echo -e "\033[34mSERVICE_NAME set to: ${SERVICE_NAME}\033[0m" | |||
echo "" | |||
sleep 2 | |||
# [check input] | |||
if [ "$RELEASE_ENV" == "dev" ]; then | |||
echo "env ok"; | |||
elif [ "$RELEASE_ENV" == "beta" ]; then | |||
echo "env ok"; | |||
elif [ "$RELEASE_ENV" == "online" ]; then | |||
echo "env ok"; | |||
else | |||
echo "please input an avaliable deploy environment [dev/beta/online]"; | |||
echo "example: ./deploy.sh beta"; | |||
exit 1; | |||
fi | |||
echo -e "\033[34mRELEASE_ENV set to: ${RELEASE_ENV} \033[0m" | |||
echo "" | |||
sleep 1 | |||
# configure log | |||
if [ ! -d "${DEPLOY_LOG_SRC}/${BUILD_TARGET}" ]; then mkdir "${DEPLOY_LOG_SRC}/${BUILD_TARGET}"; fi | |||
if [ ! -L "${FINAL_DEPLOY_SRC}/logs" ]; then ln -s "${DEPLOY_LOG_SRC}/${BUILD_TARGET}" "${FINAL_DEPLOY_SRC}/logs"; fi | |||
# remove old deploy signal | |||
if [ -f "${DEPLOY_ERROR_SIGNAL_FILE}" ]; then rm -f "${DEPLOY_ERROR_SIGNAL_FILE}"; fi | |||
if [ -f "${DEPLOY_SUCCESS_SIGNAL_FILE}" ]; then rm -f "${DEPLOY_SUCCESS_SIGNAL_FILE}"; fi | |||
# deploy start | |||
echo "" | tee -a $DEPLOY_LOG; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "deploy start" | tee -a $DEPLOY_LOG; | |||
# configure service | |||
if [ ! -L "/etc/systemd/system/${SERVICE_NAME}" ]; then | |||
cp "${FINAL_DEPLOY_SRC}/config/systemctl/${SERVICE_NAME}" "/etc/systemd/system/${SERVICE_NAME}"; | |||
else | |||
rm -f "/etc/systemd/system/${SERVICE_NAME}"; | |||
cp "${FINAL_DEPLOY_SRC}/config/systemctl/${SERVICE_NAME}" "/etc/systemd/system/${SERVICE_NAME}"; | |||
fi | |||
# configure nginx | |||
PUBLIC_NGINX_CONF="${FINAL_DEPLOY_SRC}/config/nginx/${BUILD_TARGET}.public.conf" | |||
PRIVATE_NGINX_CONF="${FINAL_DEPLOY_SRC}/config/nginx/${BUILD_TARGET}.private.conf" | |||
if [ -f "${PUBLIC_NGINX_CONF}" ]; then | |||
ln -s "${PUBLIC_NGINX_CONF}" $NGINX_CONFIG_LOCATION; | |||
fi | |||
if [ -f "${PRIVATE_NGINX_CONF}" ]; then | |||
ln -s "${PRIVATE_NGINX_CONF}" $NGINX_CONFIG_LOCATION; | |||
fi | |||
# test nginx config | |||
$NGINX_BIN_LOCATION -t 2> "${FINAL_DEPLOY_SRC}/logs/nginx_test.log"; | |||
isNginxOk=`grep 'test is successful' "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | wc -l `; | |||
if [ "$isNginxOk" != "1" ]; then | |||
touch $DEPLOY_ERROR_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[ERROR!] deploy error with nginx config error, nginx config error is : " | tee -a $DEPLOY_LOG; | |||
cat "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | tee -a $DEPLOY_LOG; | |||
exit 1; | |||
else | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "nginx config is ok:" | tee -a $DEPLOY_LOG; | |||
cat "${FINAL_DEPLOY_SRC}/logs/nginx_test.log" | tee -a $DEPLOY_LOG; | |||
fi | |||
# stop nginx | |||
$NGINX_BIN_LOCATION -s stop | |||
# check nginx is stoped | |||
sleep 20; | |||
nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l` | |||
if [ "$nginxNum" != "0" ]; then | |||
touch $DEPLOY_ERROR_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[ERROR!] deploy error with nginx stop failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; | |||
exit 1; | |||
else | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "nginx stopped" | tee -a $DEPLOY_LOG; | |||
fi | |||
# restart service | |||
/usr/bin/systemctl daemon-reload; | |||
/usr/bin/systemctl enable ${SERVICE_NAME}; | |||
/usr/bin/systemctl stop ${BUILD_TARGET}; # use start-stop for first time deploy | |||
/usr/bin/systemctl start ${BUILD_TARGET}; | |||
# check service | |||
sleep 2; | |||
/usr/bin/systemctl status "${BUILD_TARGET}" > "${FINAL_DEPLOY_SRC}/logs/service_status.log"; | |||
serviceStatus=`grep "Active: active" "${FINAL_DEPLOY_SRC}/logs/service_status.log" | wc -l`; | |||
if [ "$serviceStatus" == "0" ]; then | |||
touch $DEPLOY_ERROR_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[ERROR!] deploy error with service start failed, systemctl status :" | tee -a $DEPLOY_LOG; | |||
cat "${FINAL_DEPLOY_SRC}/logs/service_status.log" | tee -a $DEPLOY_LOG; | |||
# restart nginx | |||
$NGINX_BIN_LOCATION; | |||
# check nginx num | |||
nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l` | |||
sleep 5; | |||
if [ "$nginxNum" == "0" ]; then | |||
touch $DEPLOY_ERROR_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[ERROR!] deploy error with nginx start failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; | |||
exit 1; | |||
else | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "nginx started" | tee -a $DEPLOY_LOG; | |||
fi | |||
exit 1; | |||
else | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "service started" | tee -a $DEPLOY_LOG; | |||
cat "${FINAL_DEPLOY_SRC}/logs/service_status.log" | tee -a $DEPLOY_LOG; | |||
fi | |||
# start nginx | |||
$NGINX_BIN_LOCATION | |||
# check nginx num | |||
nginxNum=`ps auxw | grep --color 'nginx' | grep -v grep | wc -l`; | |||
sleep 5; | |||
if [ "$nginxNum" == "0" ]; then | |||
touch $DEPLOY_ERROR_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[ERROR!] deploy error with nginx start failed, nginx process num is : ${nginxNum}" | tee -a $DEPLOY_LOG; | |||
exit 1; | |||
else | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "nginx started" | tee -a $DEPLOY_LOG; | |||
fi | |||
# deploy success | |||
echo "success" > $DEPLOY_SUCCESS_SIGNAL_FILE; | |||
echo -e "`date "+%Y-%m-%d %H:%M:%S"` \c" | tee -a $DEPLOY_LOG; | |||
echo "[OK] deploy success." | tee -a $DEPLOY_LOG; | |||
exit 0; |
@ -0,0 +1,51 @@ | |||
#!/bin/sh | |||
# run_bee.sh | |||
# This script for run beego projects for dev. | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# [config] | |||
echo "-[config]-" | |||
# ----------------------------[manual config here]------------------------------ | |||
# REPO_SRC=/data/repo/collection_set_api | |||
# BUILD_TARGET=collection_set_api | |||
BEE_PATH=$2 | |||
# ------------------------------------------------------------------------------ | |||
echo -e "\033[34mREPO_SRC set to: ${REPO_SRC}\033[0m" | |||
echo -e "\033[34mBUILD_TARGET set to: ${BUILD_TARGET}\033[0m" | |||
echo "" | |||
sleep 1 | |||
# [set env] | |||
echo "-[set env]-" | |||
# $GOBIN | |||
export GOBIN="${REPO_SRC}/bin" | |||
echo -e "\033[34mGOBIN set to: ${GOBIN}\033[0m" | |||
# $GOPATH | |||
export GOPATH="${REPO_SRC}" | |||
echo -e "\033[34mGOPATH set to: ${GOPATH}\033[0m" | |||
echo "" | |||
# run | |||
if [ "${BEE_PATH}" == "" ]; then | |||
echo "please input bee executable file loacation to run this scripts, like :" | |||
echo "./ci.sh run_bee /data/bin/bee" | |||
exit 1; | |||
fi | |||
`${BEE_PATH} run ${REPO_SRC}/src` | |||
echo "done." | |||
@ -0,0 +1,58 @@ | |||
# REPO_NAME.private.conf | |||
# REPO_NAME nginx config file. | |||
# | |||
# This file auto generated by REPO_NAME/scripts/init_config.sh, | |||
# [WARRING!] DO NOT change this manualy. | |||
# | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
upstream REPO_NAME_private { | |||
server UPSTREAM_ADDR; | |||
keepalive 64; | |||
} | |||
server { | |||
listen 8000; | |||
server_name DOMAIN_NAME; | |||
default_type 'text/plain'; # or browser will download page | |||
include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; | |||
root /data/repo/REPO_NAME; | |||
access_log /data/repo/REPO_NAME/logs/nginx-access.public.log logstash; | |||
error_log /data/repo/REPO_NAME/logs/nginx-error.public.log; | |||
client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; | |||
proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; | |||
# X-Juejin-Src for api src trace back | |||
# X-Juejin-Uid for non-login user id | |||
# X-Juejin-Token for api param hash check | |||
add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; | |||
if ($request_method = OPTIONS ) { | |||
return 200; | |||
} | |||
# global location settings | |||
location /status { | |||
return 200; | |||
} | |||
location / { | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header Host $http_host; | |||
proxy_set_header X-Nginx-Proxy true; | |||
proxy_pass http://REPO_NAME_private; | |||
} | |||
location ~ /\. { | |||
deny all; | |||
access_log off; | |||
log_not_found off; | |||
} | |||
} |
@ -0,0 +1,58 @@ | |||
# REPO_NAME.public.conf | |||
# REPO_NAME nginx config file. | |||
# | |||
# This file auto generated by REPO_NAME/scripts/init_config.sh, | |||
# [WARRING!] DO NOT change this manualy. | |||
# | |||
# @version 170227:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
upstream REPO_NAME_public { | |||
server UPSTREAM_ADDR; | |||
keepalive 64; | |||
} | |||
server { | |||
listen 80; | |||
server_name DOMAIN_NAME; | |||
default_type 'text/plain'; # or browser will download page | |||
include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; | |||
root /data/repo/REPO_NAME; | |||
access_log /data/repo/REPO_NAME/logs/nginx-access.public.log logstash; | |||
error_log /data/repo/REPO_NAME/logs/nginx-error.public.log; | |||
client_body_temp_path /data/logs/nginx/client_body_temp/ 1 2; | |||
proxy_temp_path /data/logs/nginx/proxy_temp/ 1 2; | |||
# X-Juejin-Src for api src trace back | |||
# X-Juejin-Uid for non-login user id | |||
# X-Juejin-Token for api param hash check | |||
add_header 'Access-Control-Allow-Headers' 'X-Juejin-Src,X-Juejin-Uid,X-Juejin-Token' always; | |||
if ($request_method = OPTIONS ) { | |||
return 200; | |||
} | |||
# global location settings | |||
location /status { | |||
return 200; | |||
} | |||
location / { | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header Host $http_host; | |||
proxy_set_header X-Nginx-Proxy true; | |||
proxy_pass http://REPO_NAME_public; | |||
} | |||
location ~ /\. { | |||
deny all; | |||
access_log off; | |||
log_not_found off; | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
[Unit] | |||
Description = Micro Service API | |||
After = syslog.target network.target | |||
[Service] | |||
PIDFile = /data/repo/REPO_NAME/lock/BUILD_TARGET.pid | |||
ExecStart = /data/repo/REPO_NAME/bin/BUILD_TARGET beta | |||
ExecReload = /data/repo/REPO_NAME/bin/BUILD_TARGET beta reload | |||
ExecStop = /data/repo/REPO_NAME/bin/BUILD_TARGET beta stop | |||
[Install] | |||
WantedBy=multi-user.target |
@ -0,0 +1,12 @@ | |||
[Unit] | |||
Description = Micro Service API | |||
After = syslog.target network.target | |||
[Service] | |||
PIDFile = /data/repo/REPO_NAME/lock/BUILD_TARGET.pid | |||
ExecStart = /data/repo/REPO_NAME/bin/BUILD_TARGET online | |||
ExecReload = /data/repo/REPO_NAME/bin/BUILD_TARGET online reload | |||
ExecStop = /data/repo/REPO_NAME/bin/BUILD_TARGET online stop | |||
[Install] | |||
WantedBy=multi-user.target |
@ -0,0 +1,145 @@ | |||
#!/bin/bash | |||
# init_config.sh | |||
# init enviroment config scripts. | |||
# @version 170322:1 | |||
# @author zhangxuhong <zhangxuhong@xitu.io> | |||
# | |||
# ----------------------------[manual config here]------------------------------ | |||
# base config | |||
REPO_SRC=/data/repo/baidu_link_submit_ms | |||
REPO_NAME=baidu_link_submit_ms | |||
BUILD_TARGET="${REPO_NAME}" | |||
RELEASE_ENV=$1 # test, beta, online | |||
# nginx config file type | |||
DOMAIN_NAME="baidu-link-submit-ms.juejin.im" | |||
PUBLIC_UPSTREAM_PORT=13100 | |||
PRIVATE_UPSTREAM_PORT=13100 | |||
# ------------------------------------------------------------------------------ | |||
# default config | |||
NGINX_CONF_TMPL_PUBLIC="REPO_NAME.public.conf" | |||
NGINX_CONF_TMPL_PRIVATE="REPO_NAME.private.conf" | |||
SYSTEMCTL_CONF_TMPL_BETA="REPO_NAME.beta.service" | |||
SYSTEMCTL_CONF_TMPL_RELEASE="REPO_NAME.online.service" | |||
# auto generated config | |||
# nginx | |||
NGINX_CONFIG_TMPL_FOLDER="${REPO_SRC}/scripts/config_template/nginx" | |||
NGINX_CONFIG_DEPLOY_FOLDER="${REPO_SRC}/config/nginx" | |||
NGINX_CONF_PUBLIC="${REPO_NAME}.public.conf" | |||
NGINX_CONF_PRIVATE="${REPO_NAME}.private.conf" | |||
NGINX_CONF_PUBLIC_ADDR="${NGINX_CONFIG_DEPLOY_FOLDER}/${NGINX_CONF_PUBLIC}" | |||
NGINX_CONF_PRIVATE_ADDR="${NGINX_CONFIG_DEPLOY_FOLDER}/${NGINX_CONF_PRIVATE}" | |||
if [ "${PUBLIC_UPSTREAM_PORT}" != "" ]; then | |||
UPSTREAM_ADDR_PUBLIC="127.0.0.1:${PUBLIC_UPSTREAM_PORT}" | |||
fi | |||
if [ "${PRIVATE_UPSTREAM_PORT}" != "" ]; then | |||
UPSTREAM_ADDR_PRIVATE="127.0.0.1:${PRIVATE_UPSTREAM_PORT}" | |||
fi | |||
# systemctl | |||
SYSTEMCTL_CONFIG_TMPL_FOLDER="${REPO_SRC}/scripts/config_template/systemctl" | |||
SYSTEMCTL_CONFIG_DEPLOY_FOLDER="${REPO_SRC}/config/systemctl" | |||
SYSTEMCTL_CONF="${REPO_NAME}.service" | |||
SYSTEMCTL_CONF_ADDR="${SYSTEMCTL_CONFIG_DEPLOY_FOLDER}/${SYSTEMCTL_CONF}" | |||
# release env | |||
if [ "$RELEASE_ENV" == "dev" ]; then | |||
RELEASE_ENV_LOCATION="$RELEASE_ENV" | |||
elif [ "$RELEASE_ENV" == "beta" ]; then | |||
RELEASE_ENV_LOCATION="$RELEASE_ENV" | |||
elif [ "$RELEASE_ENV" == "online" ]; then | |||
RELEASE_ENV_LOCATION="$RELEASE_ENV" | |||
else | |||
RELEASE_ENV_LOCATION="" | |||
fi | |||
if [ "$RELEASE_ENV_LOCATION" == "" ]; then | |||
echo "please input an avaliable deploy environment [dev/beta/online]"; | |||
echo "example: ./init_config.sh.sh beta"; | |||
exit 1; | |||
fi | |||
# ------------------------------------------------------------------------------ | |||
# scripts start | |||
# check env | |||
NOW_PWD=`pwd` | |||
if [ "$NOW_PWD" != "${REPO_SRC}/scripts" ] && [ "$NOW_PWD" != "${REPO_SRC}" ]; then | |||
echo -e "\033[43m[WARRING!] PWD is ${NOW_PWD}, but REPO_SRC is ${REPO_SRC} \033[0m"; | |||
echo -e "please check your REPO_SRC config to make sure that you config this file correctly."; | |||
exit 1; | |||
fi | |||
# [init nginx config] | |||
# deploy tmpl config to deploy folder | |||
# for public config | |||
if [ "${PUBLIC_UPSTREAM_PORT}" != "" ]; then | |||
# deploy tmpl config to deploy folder | |||
if [ -f "${NGINX_CONF_PUBLIC_ADDR}" ]; then | |||
rm -f "${NGINX_CONF_PUBLIC_ADDR}"; | |||
fi | |||
cp "${NGINX_CONFIG_TMPL_FOLDER}/${NGINX_CONF_TMPL_PUBLIC}" "${NGINX_CONF_PUBLIC_ADDR}"; | |||
# replace config param | |||
sed -i "s/REPO_NAME/${REPO_NAME}/g" "${NGINX_CONF_PUBLIC_ADDR}"; | |||
# replace domain name | |||
sed -i "s/DOMAIN_NAME/${DOMAIN_NAME}/g" "${NGINX_CONF_PUBLIC_ADDR}"; | |||
# replace upstream addr | |||
sed -i "s/UPSTREAM_ADDR/${UPSTREAM_ADDR_PUBLIC}/g" "${NGINX_CONF_PUBLIC_ADDR}"; | |||
fi | |||
# for private config | |||
if [ "${PRIVATE_UPSTREAM_PORT}" != "" ]; then | |||
# deploy tmpl config to deploy folder | |||
if [ -f "${NGINX_CONF_PRIVATE_ADDR}" ]; then | |||
rm -f "${NGINX_CONF_PRIVATE_ADDR}"; | |||
fi | |||
cp "${NGINX_CONFIG_TMPL_FOLDER}/${NGINX_CONF_TMPL_PRIVATE}" "${NGINX_CONF_PRIVATE_ADDR}" | |||
# replace config param | |||
sed -i "s/REPO_NAME/${REPO_NAME}/g" "${NGINX_CONF_PRIVATE_ADDR}"; | |||
# replace domain name | |||
sed -i "s/DOMAIN_NAME/${DOMAIN_NAME}/g" "${NGINX_CONF_PRIVATE_ADDR}"; | |||
# replace upstream addr | |||
sed -i "s/UPSTREAM_ADDR/${UPSTREAM_ADDR_PRIVATE}/g" "${NGINX_CONF_PRIVATE_ADDR}"; | |||
fi | |||
# [init systemctl config] | |||
# deploy tmpl config to deploy folder | |||
# for beta service | |||
if [ "${RELEASE_ENV_LOCATION}" == "beta" ]; then | |||
if [ -f "${SYSTEMCTL_CONF_ADDR}" ]; then | |||
rm -f "${SYSTEMCTL_CONF_ADDR}"; | |||
fi | |||
cp "${SYSTEMCTL_CONFIG_TMPL_FOLDER}/${SYSTEMCTL_CONF_TMPL_BETA}" "${SYSTEMCTL_CONF_ADDR}" | |||
# replace repo name | |||
sed -i "s/REPO_NAME/${REPO_NAME}/g" "${SYSTEMCTL_CONF_ADDR}"; | |||
# replace build target | |||
sed -i "s/BUILD_TARGET/${BUILD_TARGET}/g" "${SYSTEMCTL_CONF_ADDR}"; | |||
fi | |||
# for online service | |||
if [ "${RELEASE_ENV_LOCATION}" == "online" ]; then | |||
if [ -f "${SYSTEMCTL_CONF_ADDR}" ]; then | |||
rm -f "${SYSTEMCTL_CONF_ADDR}"; | |||
fi | |||
cp "${SYSTEMCTL_CONFIG_TMPL_FOLDER}/${SYSTEMCTL_CONF_TMPL_RELEASE}" "${SYSTEMCTL_CONF_ADDR}" | |||
# replace repo name | |||
sed -i "s/REPO_NAME/${REPO_NAME}/g" "${SYSTEMCTL_CONF_ADDR}"; | |||
# replace build target | |||
sed -i "s/BUILD_TARGET/${BUILD_TARGET}/g" "${SYSTEMCTL_CONF_ADDR}"; | |||
fi | |||
exit 0; |
@ -0,0 +1,11 @@ | |||
package base | |||
import ( | |||
"github.com/astaxie/beego" | |||
) | |||
const configFilePath = "/data/repo/baidu_link_submit_ms/src/config/app.conf" | |||
func init() { | |||
beego.LoadAppConfig("ini", configFilePath) | |||
} |
@ -0,0 +1,21 @@ | |||
appname = hi_guoqian_go_ms | |||
httpport = 13100 | |||
runmode = dev | |||
autorender = false | |||
copyrequestbody = true | |||
EnableDocs = false | |||
[dev] | |||
redisAddress = 192.168.0.204:6379 | |||
redisDb = 0 | |||
redisPassword= | |||
[beta] | |||
redisAddress = 192.168.0.204:6379 | |||
redisDb = 0 | |||
redisPassword= | |||
[proc] | |||
redisAddress = 192.168.100.15:6379 | |||
redisDb = 1 | |||
redisPassword=rcASeLT1NayQp59B4UiM |
@ -0,0 +1,59 @@ | |||
package controllers | |||
import ( | |||
. "errors" | |||
"github.com/astaxie/beego" | |||
. "middlewares" | |||
. "models" | |||
) | |||
var ( | |||
baseUrl string = "https://juejin.im" | |||
typePathMap map[string]string = map[string]string{ | |||
"link": "/entry/", | |||
"column": "/post/", | |||
} | |||
) | |||
type EventController struct { | |||
beego.Controller | |||
} | |||
//start | |||
func (this *EventController) Contribution() { | |||
ret, err := IncrRedis("hi:guoqian") | |||
controller := &BeegoController{Controller: this.Controller} | |||
if err != nil { | |||
if err.Error() == M_NO_RESULT { | |||
controller.RenderOutput(EmptyErr(nil)) | |||
return | |||
} else { | |||
controller.RenderOutput(ServerErr(err.Error())) | |||
return | |||
} | |||
}else{ | |||
controller.RenderOutput(Success(ret)) | |||
return | |||
} | |||
} | |||
func (this *EventController) Second() { | |||
ret, err := GetRedis("hi:guoqian") | |||
controller := &BeegoController{Controller: this.Controller} | |||
if err != nil { | |||
if err.Error() == M_NO_RESULT { | |||
controller.RenderOutput(EmptyErr(nil)) | |||
return | |||
} else { | |||
controller.RenderOutput(ServerErr(err.Error())) | |||
return | |||
} | |||
}else{ | |||
controller.RenderOutput(Success(ret)) | |||
return | |||
} | |||
} | |||
//end |
@ -0,0 +1,25 @@ | |||
package main | |||
import ( | |||
"github.com/astaxie/beego" | |||
_ "base" | |||
_ "models" | |||
_ "routers" | |||
) | |||
func main() { | |||
initLog() | |||
beego.Run() | |||
} | |||
func initLog() { | |||
name := beego.AppConfig.String("appname") | |||
logFilePath := "/data/repo/" + name + "/logs/" + name + ".log" | |||
beego.SetLogger("file", `{"filename":"` + logFilePath + `","level":2,"daily":true,"maxdays":10}`) | |||
if beego.AppConfig.String("runmode") != "dev" { | |||
beego.BeeLogger.DelLogger("console") | |||
} | |||
beego.BeeLogger.EnableFuncCallDepth(true) | |||
beego.SetLogFuncCall(true) | |||
beego.BeeLogger.Async() | |||
} |
@ -0,0 +1,39 @@ | |||
package middleware | |||
import ( | |||
"github.com/astaxie/beego" | |||
) | |||
type BeegoController struct { | |||
Controller beego.Controller | |||
} | |||
func (c *BeegoController) GetQuery(key string) string { | |||
return c.Controller.Input().Get(key) | |||
} | |||
func (c *BeegoController) GetForm(key string) string { | |||
return c.Controller.Input().Get(key) | |||
} | |||
func (c *BeegoController) GetHeader(key string) string { | |||
return c.Controller.Ctx.Input.Header(key) | |||
} | |||
func (c *BeegoController) GetCookie(key string) string { | |||
return c.Controller.Ctx.Input.Cookie(key) | |||
} | |||
func (c *BeegoController) GetBody() []byte { | |||
return c.Controller.Ctx.Input.RequestBody | |||
} | |||
func (c *BeegoController) GetPath(key string) string { | |||
return c.Controller.GetString(":" + key) | |||
} | |||
func (c *BeegoController) GetArray(key string) []string { | |||
array := make([]string, 0) | |||
c.Controller.Ctx.Input.Bind(&array, key) | |||
return array | |||
} | |||
func (c *BeegoController) RenderOutput(ret *RenderStruct) { | |||
c.Controller.Ctx.Output.Status = ret.Status | |||
c.Controller.Data["json"] = ret | |||
c.Controller.ServeJSON() | |||
} |
@ -0,0 +1,306 @@ | |||
package middleware | |||
import ( | |||
"encoding/json" | |||
"strconv" | |||
"time" | |||
) | |||
const ( | |||
TYPE_STRING = iota | |||
TYPE_INT | |||
TYPE_FLOAT | |||
TYPE_BOOLEAN | |||
TYPE_TIME | |||
TYPE_ARRAY | |||
TYPE_JSON_OBJECT | |||
) | |||
const ( | |||
POS_QUERY = iota | |||
POS_HEADER | |||
POS_BODY_FORM | |||
POS_BODY_JSON | |||
POS_PATH | |||
POS_COOKIE | |||
) | |||
const ( | |||
TIME_LAYOUT = "2006-01-02T15:04:05Z" | |||
) | |||
type InputInterface interface { | |||
GetQuery(key string) string | |||
GetForm(key string) string | |||
GetHeader(key string) string | |||
GetCookie(key string) string | |||
GetBody() []byte | |||
GetPath(key string) string | |||
GetArray(key string) []string | |||
RenderOutput(r *RenderStruct) | |||
} | |||
type InputContainer struct { | |||
simpleMap map[string]interface{} | |||
objectMap map[string][]byte | |||
arrayMap map[string][]string | |||
} | |||
type InputRule struct { | |||
Name string | |||
Description string | |||
Position int | |||
Type int | |||
//此处有蹊跷 | |||
Limit []string | |||
Necessary bool | |||
Max int | |||
Min int | |||
Default interface{} | |||
} | |||
type CheckError struct { | |||
Missing string `json:"missing" xml:"missing"` | |||
Illegal string `json:"illegal" xml:"illegal"` | |||
} | |||
func (c *CheckError) Error() string { | |||
return "input error" | |||
} | |||
//must use this func to create a new container | |||
func NewContainer() *InputContainer { | |||
return &InputContainer{ | |||
simpleMap: make(map[string]interface{}), | |||
objectMap: make(map[string][]byte), | |||
arrayMap: make(map[string][]string), | |||
} | |||
} | |||
func (i *InputContainer) CheckInput(input InputInterface, rules []*InputRule) *CheckError { | |||
for _, rule := range rules { | |||
//check special input type | |||
switch rule.Type { | |||
case TYPE_ARRAY: | |||
arr := input.GetArray(rule.Name) | |||
if rule.Necessary && len(arr) <= 0 { | |||
return &CheckError{ | |||
Missing: rule.Name, | |||
} | |||
} | |||
if rule.Max > 0 { | |||
if len(arr) > rule.Max { | |||
return &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
if rule.Min > 0 { | |||
if len(arr) < rule.Min { | |||
return &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
i.arrayMap[rule.Name] = arr | |||
case TYPE_JSON_OBJECT: | |||
var bytes []byte | |||
switch rule.Position { | |||
default: | |||
fallthrough | |||
case POS_BODY_JSON: | |||
bytes = input.GetBody() | |||
case POS_QUERY: | |||
bytes = []byte(input.GetQuery(rule.Name)) | |||
case POS_BODY_FORM: | |||
bytes = []byte(input.GetForm(rule.Name)) | |||
case POS_HEADER: | |||
bytes = []byte(input.GetHeader(rule.Name)) | |||
case POS_COOKIE: | |||
bytes = []byte(input.GetCookie(rule.Name)) | |||
} | |||
if rule.Necessary && len(bytes) <= 0 { | |||
return &CheckError{ | |||
Missing: rule.Name, | |||
} | |||
} else if len(bytes) <= 0 { | |||
continue | |||
} | |||
err := json.Unmarshal(bytes, &map[string]interface{}{}) | |||
if err != nil { | |||
return &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
i.objectMap[rule.Name] = bytes | |||
default: | |||
//check normal input type | |||
var val string | |||
switch rule.Position { | |||
case POS_PATH: | |||
val = input.GetPath(rule.Name) | |||
default: | |||
fallthrough | |||
case POS_QUERY: | |||
val = input.GetQuery(rule.Name) | |||
case POS_BODY_FORM: | |||
val = input.GetForm(rule.Name) | |||
case POS_HEADER: | |||
val = input.GetHeader(rule.Name) | |||
case POS_COOKIE: | |||
val = input.GetCookie(rule.Name) | |||
} | |||
if rule.Necessary && len(val) <= 0 { | |||
return &CheckError{ | |||
Missing: rule.Name, | |||
} | |||
} else if len(val) <= 0 { | |||
i.simpleMap[rule.Name] = rule.Default | |||
} else { | |||
res, err := checkValue(rule, val) | |||
if err != nil { | |||
return err | |||
} | |||
i.simpleMap[rule.Name] = res | |||
} | |||
} | |||
} | |||
return nil | |||
} | |||
func checkValue(rule *InputRule, val string) (interface{}, *CheckError) { | |||
limit := len(rule.Limit) <= 0 | |||
if !limit { | |||
for _, i := range rule.Limit { | |||
if val == i { | |||
limit = true | |||
break | |||
} | |||
} | |||
if !limit { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
switch rule.Type { | |||
default: | |||
fallthrough | |||
case TYPE_STRING: | |||
if rule.Max > 0 { | |||
if len(val) > rule.Max { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
if rule.Min > 0 { | |||
if len(val) < rule.Min { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
return val, nil | |||
case TYPE_INT: | |||
intVal, err := strconv.Atoi(val) | |||
if err != nil { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
if rule.Max > 0 { | |||
if intVal > rule.Max { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
if rule.Min > 0 { | |||
if intVal < rule.Min { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
return intVal, nil | |||
case TYPE_FLOAT: | |||
floatVal, err := strconv.ParseFloat(val, 64) | |||
if err != nil { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
if rule.Max > 0 { | |||
if floatVal > float64(rule.Max) { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
if rule.Min > 0 { | |||
if floatVal < float64(rule.Min) { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
} | |||
return floatVal, nil | |||
case TYPE_BOOLEAN: | |||
booleanVal, err := strconv.ParseBool(val) | |||
if err != nil { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
return booleanVal, nil | |||
case TYPE_TIME: | |||
t, err := time.Parse(TIME_LAYOUT, val) | |||
if err != nil { | |||
return nil, &CheckError{ | |||
Illegal: rule.Name, | |||
} | |||
} | |||
return t, nil | |||
} | |||
} | |||
func (i *InputContainer) GetInt(key string) int { | |||
if res, ok := i.simpleMap[key].(int); ok { | |||
return res | |||
} | |||
return 0 | |||
} | |||
func (i *InputContainer) GetBoolean(key string) bool { | |||
if res, ok := i.simpleMap[key].(bool); ok { | |||
return res | |||
} | |||
return false | |||
} | |||
func (i *InputContainer) GetFloat(key string) float64 { | |||
if res, ok := i.simpleMap[key].(float64); ok { | |||
return res | |||
} | |||
return 0 | |||
} | |||
func (i *InputContainer) GetString(key string) string { | |||
if res, ok := i.simpleMap[key].(string); ok { | |||
return res | |||
} | |||
return "" | |||
} | |||
func (i *InputContainer) GetArray(key string) []string { | |||
return i.arrayMap[key] | |||
} | |||
func (i *InputContainer) GetObject(key string, obj interface{}) error { | |||
bytes := i.objectMap[key] | |||
return json.Unmarshal(bytes, obj) | |||
} | |||
func (i *InputContainer) GetTime(key string) time.Time { | |||
if res, ok := i.simpleMap[key].(time.Time); ok { | |||
return res | |||
} | |||
return time.Time{} | |||
} |
@ -0,0 +1,112 @@ | |||
package middleware | |||
import ( | |||
"github.com/astaxie/beego" | |||
"net/http" | |||
) | |||
const ( | |||
S_UNKNOWN_ERROR = iota | |||
S_OK | |||
S_NO_RESULT | |||
S_ILLEGAL_TOKEN | |||
S_WRONG_INPUT | |||
S_WRONG_EXEC_RESULT | |||
S_TOKEN_EXPIRE | |||
) | |||
const ( | |||
M_OK = "success" | |||
M_NO_RESULT = "no result" | |||
M_ILLEGAL_TOKEN = "illegal token" | |||
M_TOKEN_EXPIRE = "token expired" | |||
M_ILLEGAL_SESSION = "illegal session" | |||
M_WRONG_INPUT = "wrong input" | |||
M_WRONG_EXEC_RESULT = "exec error" | |||
) | |||
type RenderStruct struct { | |||
Status int `json:"-"` | |||
S int `json:"s"` | |||
M string `json:"m"` | |||
D interface{} `json:"d"` | |||
} | |||
func Success(list interface{}) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = http.StatusOK | |||
r.S = S_OK | |||
r.M = M_OK | |||
if list == nil { | |||
list = []interface{}{} | |||
} | |||
r.D = list | |||
return | |||
} | |||
func EmptyErr(list interface{}) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = http.StatusOK | |||
r.S = S_NO_RESULT | |||
r.M = M_NO_RESULT | |||
if list == nil { | |||
list = []interface{}{} | |||
} | |||
r.D = list | |||
return | |||
} | |||
func InputErr(data interface{}) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = http.StatusBadRequest | |||
if data == nil { | |||
data = []interface{}{} | |||
} | |||
r.S = S_WRONG_INPUT | |||
r.M = M_WRONG_INPUT | |||
r.D = data | |||
if beego.BConfig.RunMode != "dev" { | |||
r.D = []interface{}{} | |||
} | |||
return | |||
} | |||
func NormalErr(status int, s int, msg string, d interface{}) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = status | |||
r.S = s | |||
r.M = msg | |||
if d == nil { | |||
d = []interface{}{} | |||
} | |||
r.D = d | |||
return | |||
} | |||
func ServerErr(message string) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = http.StatusInternalServerError | |||
r.S = S_WRONG_EXEC_RESULT | |||
r.M = message | |||
if len(message) <= 0 { | |||
r.M = M_WRONG_EXEC_RESULT | |||
} | |||
r.D = []interface{}{} | |||
return | |||
} | |||
func TokenErr(errorType int) (r *RenderStruct) { | |||
r = new(RenderStruct) | |||
r.Status = http.StatusForbidden | |||
switch errorType { | |||
case S_TOKEN_EXPIRE: | |||
r.S = S_TOKEN_EXPIRE | |||
r.M = M_TOKEN_EXPIRE | |||
default: | |||
fallthrough | |||
case S_ILLEGAL_TOKEN: | |||
r.S = S_ILLEGAL_TOKEN | |||
r.M = M_ILLEGAL_TOKEN | |||
} | |||
r.D = []interface{}{} | |||
return | |||
} |
@ -0,0 +1,65 @@ | |||
package models | |||
import ( | |||
"github.com/astaxie/beego" | |||
"github.com/garyburd/redigo/redis" | |||
"time" | |||
) | |||
var RedisPool *redis.Pool | |||
func init() { | |||
address := beego.AppConfig.String("redisAddress") | |||
password := beego.AppConfig.String("redisPassword") | |||
dbNum := beego.AppConfig.String("redisDb") | |||
dialFunc := func() (c redis.Conn, err error) { | |||
// c, err = redis.Dial("tcp", address) | |||
// func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) | |||
c, err = redis.DialTimeout("tcp", address, 3*time.Second, 3*time.Second, 3*time.Second) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if beego.AppConfig.String("redisPassword") != "" { | |||
if _, err := c.Do("AUTH", password); err != nil { | |||
c.Close() | |||
return nil, err | |||
} | |||
} | |||
_, selecterr := c.Do("SELECT", dbNum) | |||
if selecterr != nil { | |||
c.Close() | |||
return nil, selecterr | |||
} | |||
return | |||
} | |||
// initialize a new pool | |||
RedisPool = &redis.Pool{ | |||
MaxIdle: 100, | |||
MaxActive: 50, | |||
IdleTimeout: 180 * time.Second, | |||
Dial: dialFunc, | |||
} | |||
} | |||
func SetRedis(key string, value []byte) error { | |||
conn := RedisPool.Get() | |||
defer conn.Close() | |||
conn.Send("SET", key, value) | |||
return conn.Flush() | |||
} | |||
func GetRedis(key string) (int64, error) { | |||
conn := RedisPool.Get() | |||
defer conn.Close() | |||
ret, err := redis.Int64(conn.Do("GET", key)) | |||
return ret, err | |||
} | |||
func IncrRedis(key string) (int64, error) { | |||
conn := RedisPool.Get() | |||
defer conn.Close() | |||
ret, err := redis.Int64(conn.Do("INCR", key)) | |||
return ret, err | |||
} |
@ -0,0 +1,19 @@ | |||
package routers | |||
import ( | |||
"net/http" | |||
"github.com/astaxie/beego" | |||
. "controllers" | |||
) | |||
func init() { | |||
eventController := EventController{} | |||
namespace := beego.NewNamespace("/v1", | |||
beego.NSRouter("/second", &eventController, "get:Second"), | |||
beego.NSRouter("/contribution", &eventController, "post:Contribution"), | |||
) | |||
beego.AddNamespace(namespace) | |||
beego.ErrorHandler("404", func(w http.ResponseWriter, r *http.Request) { | |||
w.WriteHeader(http.StatusNotFound) | |||
}) | |||
} |