作者 yangfu

初始化oepnapi

# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
*.vscode
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.log
*debug
*wasm
*.idea
*.tmp
*.sum
opp
/vendor
/*.exe~
... ...
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
... ...
FROM 192.168.0.243:5000/mmm/mmmopp:20200226 as builder
#FROM golang:1.13 as builder
ENV GOPROXY https://goproxy.cn
ENV GO111MODULE on
ENV GOPATH /go
RUN cd /go/src/gocomm \
&& git pull
WORKDIR /go/src/openapi
COPY go.mod .
COPY . .
RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -o opp main.go
#FROM alpine:latest
FROM 192.168.0.243:5000/mmm/mmmopp:20200110
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
&& apk add --no-cache tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cache ## 清除缓存
WORKDIR /root/
COPY --from=builder /go/src/opp .
EXPOSE 8080
CMD ["./openapi"]
\ No newline at end of file
... ...
appname = open-api
httpport = 8080
runmode = "${RUN_MODE||dev}"
#没设置的话 this.Ctx.Input.RequestBody 没有值
copyrequestbody = true
#enablexsrf = true
#开启应用内文档开关
EnableDocs = true
include "dev.conf"
include "dev-online.conf"
include "test.conf"
include "prod.conf"
... ...
[dev-online]
#Ali could
AccessKeyID ="LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret ="UyspWwdni55CYQ02hUCint4qY2jNYO"
\ No newline at end of file
... ...
[dev]
#Ali could
AccessKeyID ="LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret ="UyspWwdni55CYQ02hUCint4qY2jNYO"
... ...
[prod]
#Ali could
AccessKeyID ="LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret ="UyspWwdni55CYQ02hUCint4qY2jNYO"
\ No newline at end of file
... ...
[test]
#Ali could
AccessKeyID ="LTAI4FhiZ3UktC6N1u3H5GFC"
AccessKeySecret ="UyspWwdni55CYQ02hUCint4qY2jNYO"
\ No newline at end of file
... ...
package controllers
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/astaxie/beego/plugins/cors"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/time"
"openapi/protocol"
"strconv"
"strings"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/validation"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/mybeego"
)
type BaseController struct {
Header *protocol.RequestHeader
mybeego.BaseController
}
func init() {
}
var DefaultController *BaseController = &BaseController{}
//Valid valid struct
func (this *BaseController) Valid(obj interface{}) (result bool, msg *protocol.ResponseMessage) {
/*校验*/
var err error
valid := validation.Validation{}
result, err = valid.Valid(obj)
if err != nil {
}
if !result {
for _, err := range valid.Errors {
if strings.HasSuffix(err.Key, ".Mobile") {
msg = protocol.BadRequestParam(2001)
return
}
log.Error(err.Key, err.Message)
}
msg = protocol.BadRequestParam(2)
return
}
return
}
func (this *BaseController) Resp(msg *protocol.ResponseMessage) {
this.Data["json"] = msg
this.ServeJSON()
}
func (this *BaseController) RespH5(msg *protocol.ResponseMessage) {
if msg.Errno != 0 {
msg.Errno = -1
}
this.Data["json"] = msg
this.ServeJSON()
}
//获取请求头信息
func GetRequestHeader(ctx *context.Context) *protocol.RequestHeader {
h := &protocol.RequestHeader{}
h.AccessToken = ctx.Input.Header("x-mmm-accesstoken")
h.AppProject = ctx.Input.Header("x-mmm-appproject")
h.DeviceType, _ = strconv.Atoi(ctx.Input.Header("x-mmm-devicetype"))
h.Sign = ctx.Input.Header("x-mmm-sign")
h.Uuid = ctx.Input.Header("x-mmm-uuid")
h.TimeStamp = ctx.Input.Header("x-mmm-timestamp")
h.Version = ctx.Input.Header("x-mmm-version")
return h
}
//过滤器
func FilterComm(ctx *context.Context) {
if !CheckSign(ctx) {
return
}
return
}
//检查签名
func CheckSign(ctx *context.Context) (result bool) {
var (
h *protocol.RequestHeader
sign string
signHex string
)
result = true
h = GetRequestHeader(ctx)
//1.检查签名
sign = fmt.Sprintf("v!(MmM%v%v%vMmM)i^", h.TimeStamp, h.Uuid, h.AccessToken)
sha256 := sha256.New()
sha256.Write([]byte(sign))
signHex = hex.EncodeToString(sha256.Sum(nil))
if strings.Compare(signHex, h.Sign) != 0 {
msg := protocol.BadRequestParam(113)
log.Error(fmt.Sprintf("%v req:%v resp:%v %v", ctx.Request.RequestURI, common.AssertJson(h), common.AssertJson(msg), signHex))
ctx.Output.JSON(msg, false, false)
result = false
return
}
return
}
//AllowOption 允许跨域请求
var AllowOption = func(ctx *context.Context) {
if ctx.Request.Method != "OPTIONS" {
return
}
f := cors.Allow(&cors.Options{
AllowMethods: []string{"POST", "GET", "OPTIONS", "PUT", "DELETE"}, //允许的请求类型
AllowHeaders: []string{"Origin", "Accept", "Content-Type", "Authorization",
"x-mmm-cid", "x-mmm-uid", "x-mmm-accesstoken", "x-mmm-refreshtoken", "x-requested-with"}, //允许的头部信息
ExposeHeaders: []string{"Content-Length"}, //允许暴露的头信息
AllowCredentials: false, //不允许共享AuthTuffic证书
AllowAllOrigins: true, //允许的请求来源
})
f(ctx)
ctx.Output.Body([]byte("{}"))
ctx.Output.SetStatus(204)
return
}
//LogRequestData Before Router
var LogRequestData = func(ctx *context.Context) {
log.Info("====>Recv Request:%s", ctx.Input.URI())
hmap := map[string]string{
//protocol.HeaderAccessToken: ctx.Input.Header(protocol.HeaderAccessToken),
//protocol.HeaderRefreshToken: ctx.Input.Header(protocol.HeaderRefreshToken),
}
if ctx.Input.RequestBody != nil {
log.Info("====>Recv data from client:\nHeadData: %v \nBodyData: %s", hmap, string(ctx.Input.RequestBody))
} else {
log.Info("====>Recv data from client:\nHeadData: %v ", hmap)
}
}
func (this *BaseController) Prepare() {
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "*")
if this.Ctx.Input.Method() == "OPTIONS" {
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
return
}
this.Query = map[string]string{}
input := this.Input()
for k := range input {
this.Query[k] = input.Get(k)
}
if this.Ctx.Input.RequestBody != nil {
this.ByteBody = this.Ctx.Input.RequestBody[:]
if len(this.ByteBody) < 1 {
this.ByteBody = []byte("{}")
}
this.RequestHead = this.GetRequestHead()
this.Header = GetRequestHeader(this.Ctx)
this.Header.SetRequestId(fmt.Sprintf("%v.%v.%s", this.Header.Uid, time.GetTimeByYyyymmddhhmmss(), this.Ctx.Request.URL))
log.Debug(fmt.Sprintf("====>Recv data from uid(%d) ucid(%v) client:\nHeadData: %s\nRequestId:%s BodyData: %s", this.Header.Uid, this.Header.UserId, common.AssertJson(this.Header), this.Header.GetRequestId(), string(this.ByteBody)))
}
}
func (this *BaseController) Finish() {
if this.Ctx.Input.Method() == "OPTIONS" {
return
}
strByte, _ := json.Marshal(this.Data["json"])
length := len(strByte)
if length > 5000 {
log.Debug(fmt.Sprintf("<====Send to uid(%d) ucid(%v) client: %d byte\nRequestId:%s RspBodyData: %s......", this.Header.Uid, this.Header.UserId, length, this.Header.GetRequestId(), string(strByte[:5000])))
} else {
log.Debug(fmt.Sprintf("<====Send to uid(%d) ucid(%v) client: %d byte\nRequestId:%s RspBodyData: %s", this.Header.Uid, this.Header.UserId, length, this.Header.GetRequestId(), string(strByte)))
}
}
... ...
package v1
import (
"encoding/json"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/controllers"
"openapi/internal/aliyun"
"openapi/protocol"
"openapi/services/vod"
)
type VodController struct {
controllers.BaseController
}
//创建视频上传凭证 CreateUploadVideo
// @router /createUploadVideo [post]
func (this *VodController) CreateUploadVideo() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.CreateUploadVideoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
if len(request.FileName) == 0 {
request.FileName = aliyun.DefaultVideoFileName
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.CreateUploadVideo(header, request))
}
//刷新视频上传凭证 RefreshUploadVideo
// @router /refreshUploadVideo [post]
func (this *VodController) RefreshUploadVideo() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.RefreshUploadVideoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.RefreshUploadVideo(header, request))
}
//创建图片上传凭证 CreateUploadImage
// @router /createUploadImage [post]
func (this *VodController) CreateUploadImage() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.CreateUploadImageRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.CreateUploadImage(header, request))
}
//创建图片上传凭证 CreateUploadImages
// @router /createUploadImages [post]
func (this *VodController) CreateUploadImages() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var (
request *aliyun.CreateUploadImagesRequest
response *aliyun.CreateUploadImagesResponse = &aliyun.CreateUploadImagesResponse{
List: make([]*aliyun.CreateUploadImageResponse, 0),
}
)
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
var err error
if len(request.Items) == 0 {
msg = protocol.BadRequestParam(2)
}
header := controllers.GetRequestHeader(this.Ctx)
for i := range request.Items {
r := request.Items[i]
if rsp, e := vod.CreateUploadImage(header, r); e != nil {
err = e
break
} else {
response.List = append(response.List, rsp)
}
}
msg = protocol.NewReturnResponse(response, err)
}
//获取视频播放地址 GetPlayInfo
// @router /getPlayInfo [post]
func (this *VodController) GetPlayInfo() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.GetPlayInfoRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.GetPlayInfo(header, request))
}
//获取视频播放凭证 GetVideoPlayAuth
// @router /getVideoPlayAuth [post]
func (this *VodController) GetVideoPlayAuth() {
var msg *protocol.ResponseMessage
defer func() {
this.Resp(msg)
}()
var request *aliyun.GetVideoPlayAuthRequest
if err := json.Unmarshal(this.ByteBody, &request); err != nil {
log.Error(err)
msg = protocol.BadRequestParam(1)
return
}
if b, m := this.Valid(request); !b {
msg = m
return
}
header := controllers.GetRequestHeader(this.Ctx)
msg = protocol.NewReturnResponse(vod.GetVideoPlayAuth(header, request))
}
... ...
#!/bin/bash
export PATH=/root/local/bin:$PATH
kubectl -n mmm-suplus-dev get pods | grep -q mmmopp
if [ "$?" == "1" ];then
kubectl create -f /tmp/dev/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-dev get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service install success!"
else
echo "mmmopp service install fail!"
fi
kubectl -n mmm-suplus-dev get pods | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp deployment install success!"
else
echo "mmmopp deployment install fail!"
fi
else
kubectl delete -f /tmp/dev/mmm-go-opp/opp.yaml
kubectl -n mmm-suplus-dev get svc | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-dev get svc | grep -q mmmopp
done
kubectl -n mmm-suplus-dev get pods | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-dev get pods | grep -q mmmopp
done
kubectl create -f /tmp/dev/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-dev get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service update success!"
else
echo "opp service update fail!"
fi
kubectl -n mmm-suplus-dev get pods | grep -q opp
if [ "$?" == "0" ];then
echo "opp deployment update success!"
else
echo "opp deployment update fail!"
fi
fi
\ No newline at end of file
... ...
apiVersion: v1
kind: Service
metadata:
name: mmmopp
namespace: mmm-suplus-dev
labels:
k8s-app: mmmopp
spec:
ports:
- name: "http"
port: 80
targetPort: 8080
selector:
k8s-app: mmmopp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mmmopp
namespace: mmm-suplus-dev
labels:
k8s-app: mmmopp
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: mmmopp
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference: {}
weight: 100
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- cn-hangzhou.i-bp1djh1xn7taumbue1ze
- cn-hangzhou.i-bp1djh1xn7taumbue1zd
- cn-hangzhou.i-bp1euf5u1ph9kbhtndhb
- cn-hangzhou.i-bp1hyp5oips9cdwxxgxy
containers:
- name: mmmopp
image: 192.168.0.243:5000/mmm/mmmopp:dev
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/logs
name: accesslogs
- mountPath: /var/www/opp/file
name: mmmjihuitest-pvc1
ports:
- containerPort: 8080
env:
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.host
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.port
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.ip
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.port
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.user
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.password
- name: MYSQL_DB_NAME
value: "opportunity_dev"
- name: RUN_MODE
value: "dev-online"
- name: LOG_LEVEL
value: "debug"
- name: aliyun_logs_suplusfile
value: "stdout"
- name: aliyun_logs_access
value: " /opt/logs/app.log"
volumes:
- name: accesslogs
emptyDir: {}
- name: mmmjihuitest-pvc1
persistentVolumeClaim:
claimName: mmmjihuitest-pvc
\ No newline at end of file
... ...
#!/bin/bash
export PATH=/root/local/bin:$PATH
kubectl -n mmm-suplus-prd get pods | grep -q mmmopp
if [ "$?" == "1" ];then
kubectl create -f /tmp/prd/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-prd get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service install success!"
else
echo "mmmopp service install fail!"
fi
kubectl -n mmm-suplus-prd get pods | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp deployment install success!"
else
echo "mmmopp deployment install fail!"
fi
else
kubectl delete -f /tmp/prd/mmm-go-opp/opp.yaml
kubectl -n mmm-suplus-prd get svc | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-prd get svc | grep -q mmmopp
done
kubectl -n mmm-suplus-prd get pods | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-prd get pods | grep -q mmmopp
done
kubectl create -f /tmp/prd/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-prd get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service update success!"
else
echo "opp service update fail!"
fi
kubectl -n mmm-suplus-prd get pods | grep -q opp
if [ "$?" == "0" ];then
echo "opp deployment update success!"
else
echo "opp deployment update fail!"
fi
fi
\ No newline at end of file
... ...
apiVersion: v1
kind: Service
metadata:
name: mmmopp
namespace: mmm-suplus-prd
labels:
k8s-app: mmmopp
spec:
ports:
- name: "http"
port: 80
targetPort: 8080
- name: "https"
port: 443
targetPort: 443
selector:
k8s-app: mmmopp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mmmopp
namespace: mmm-suplus-prd
labels:
k8s-app: mmmopp
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: mmmopp
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference: {}
weight: 100
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- cn-hangzhou.i-bp1djh1xn7taumbue1ze
- cn-hangzhou.i-bp1djh1xn7taumbue1zd
- cn-hangzhou.i-bp1euf5u1ph9kbhtndhb
- cn-hangzhou.i-bp1hyp5oips9cdwxxgxy
containers:
- name: mmmopp
image: 192.168.0.243:5000/mmm/mmmopp:master
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/logs
name: accesslogs
- mountPath: /var/www/opp/file
name: opportunity-pvc1
ports:
- containerPort: 8080
- containerPort: 443
env:
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.host
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.port
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.ip
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.port
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.user
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.password
- name: MYSQL_DB_NAME
value: "opportunity"
- name: RUN_MODE
value: "prod"
- name: LOG_LEVEL
value: "debug"
- name: aliyun_logs_suplusfile
value: "stdout"
- name: aliyun_logs_access
value: " /opt/logs/app.log"
volumes:
- name: accesslogs
emptyDir: {}
- name: opportunity-pvc1
persistentVolumeClaim:
claimName: opportunity-pvc5
\ No newline at end of file
... ...
#!/bin/bash
export PATH=/root/local/bin:$PATH
kubectl -n mmm-suplus-test get pods | grep -q mmmopp
if [ "$?" == "1" ];then
kubectl create -f /tmp/test/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-test get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service install success!"
else
echo "mmmopp service install fail!"
fi
kubectl -n mmm-suplus-test get pods | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp deployment install success!"
else
echo "mmmopp deployment install fail!"
fi
else
kubectl delete -f /tmp/test/mmm-go-opp/opp.yaml
kubectl -n mmm-suplus-test get svc | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-test get svc | grep -q mmmopp
done
kubectl -n mmm-suplus-test get pods | grep -q mmmopp
while [ "$?" == "0" ]
do
kubectl -n mmm-suplus-test get pods | grep -q mmmopp
done
kubectl create -f /tmp/test/mmm-go-opp/opp.yaml --record
kubectl -n mmm-suplus-test get svc | grep -q mmmopp
if [ "$?" == "0" ];then
echo "mmmopp service update success!"
else
echo "opp service update fail!"
fi
kubectl -n mmm-suplus-test get pods | grep -q opp
if [ "$?" == "0" ];then
echo "opp deployment update success!"
else
echo "opp deployment update fail!"
fi
fi
\ No newline at end of file
... ...
apiVersion: v1
kind: Service
metadata:
name: mmmopp
namespace: mmm-suplus-test
labels:
k8s-app: mmmopp
spec:
ports:
- name: "http"
port: 80
targetPort: 8080
- name: "https"
port: 443
targetPort: 443
selector:
k8s-app: mmmopp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mmmopp
namespace: mmm-suplus-test
labels:
k8s-app: mmmopp
spec:
replicas: 1
template:
metadata:
labels:
k8s-app: mmmopp
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference: {}
weight: 100
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- cn-hangzhou.i-bp1djh1xn7taumbue1ze
- cn-hangzhou.i-bp1djh1xn7taumbue1zd
- cn-hangzhou.i-bp1euf5u1ph9kbhtndhb
- cn-hangzhou.i-bp1hyp5oips9cdwxxgxy
containers:
- name: mmmopp
image: 192.168.0.243:5000/mmm/mmmopp:dev
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/logs
name: accesslogs
- mountPath: /var/www/opp/file
name: mmmjihuitest2-pvc1
ports:
- containerPort: 8080
- containerPort: 443
env:
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.host
- name: MYSQL_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.port
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.ip
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: suplus-config
key: redis.port
- name: MYSQL_USER
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.user
- name: MYSQL_PASSWORD
valueFrom:
configMapKeyRef:
name: suplus-config
key: mysql.password
- name: MYSQL_DB_NAME
value: "opportunity_test"
- name: RUN_MODE
value: "test"
- name: LOG_LEVEL
value: "debug"
- name: aliyun_logs_suplusfile
value: "stdout"
- name: aliyun_logs_access
value: " /opt/logs/app.log"
volumes:
- name: accesslogs
emptyDir: {}
- name: mmmjihuitest2-pvc1
persistentVolumeClaim:
claimName: mmmjihuitest2-pvc
\ No newline at end of file
... ...
module openapi
go 1.12
require (
github.com/aliyun/alibaba-cloud-sdk-go v1.60.348
github.com/astaxie/beego v1.10.0
gitlab.fjmaimaimai.com/mmm-go/gocomm v0.0.1
)
replace gitlab.fjmaimaimai.com/mmm-go/gocomm => ../gocomm
... ...
package aliyun
import "github.com/astaxie/beego"
var (
RegionID = "cn-shanghai"
AccessKeyID = beego.AppConfig.String("AccessKeyID")
AccessKeySecret = beego.AppConfig.String("AccessKeySecret")
)
const (
FileImage = "image"
FileVoice = "voice"
FileVideo = "video"
)
const (
DefaultVideoFileName = "test.mp4"
DefaultVoiceFileName = "test.mp3"
DefaultImageFileName = "test.jpg"
)
... ...
package aliyun
import (
"github.com/astaxie/beego"
)
/*
AK AccessKey 完全访问权限
STS (Security Token Service) 临时访问控制
*/
var (
Endpoint string = beego.AppConfig.String("end_point")
BucketName string = beego.AppConfig.String("bucket_name")
//BucketNameCdn string = beego.AppConfig.String("bucket_name_cdn")
//EndpointCdn string = beego.AppConfig.String("end_point_cdn")
)
//type OssSts struct{
//
//}
//func NewSTS(){
// client,_ :=oos.NewClientWithAccessKey(RegionID,AccessKeyID,AccessKeySecret)
// client.DoAction()
//}
... ...
package aliyun
//创建视频上传凭证
/*CreateUploadVideo */
type CreateUploadVideoRequest struct {
FileName string `json:"fileName"`
}
type CreateUploadVideoResponse struct {
RequestId string `json:"requestId"`
VideoId string `json:"videoId"`
UploadAddress string `json:"uploadAddress"`
UploadAuth string `json:"uploadAuth"`
FileURL string `json:"fileURL"`
}
//刷新视频上传凭证 RefreshUploadVideo
type RefreshUploadVideoRequest struct {
VideoId string `json:"videoId" valid:"Required;"`
}
type RefreshUploadVideoResponse struct {
RequestId string `json:"requestId"`
VideoId string `json:"videoId"`
UploadAddress string `json:"uploadAddress"`
UploadAuth string `json:"uploadAuth"`
FileURL string `json:"fileURL"`
}
/*GetPlayInfo 获取播放信息*/
type GetPlayInfoRequest struct {
VideoId string `json:"videoId" xml:"VideoId"`
}
// GetPlayInfoResponse is the response struct for api GetPlayInfo
type GetPlayInfoResponse struct {
//*responses.BaseResponse
//RequestId string `json:"RequestId" xml:"RequestId"`
VideoBase VideoBase `json:"VideoBase" xml:"VideoBase"`
PlayInfoList PlayInfoListInGetPlayInfo `json:"PlayInfoList" xml:"PlayInfoList"`
}
/*获取视频播放凭证*/
type GetVideoPlayAuthRequest struct {
VideoId string `json:"videoId" xml:"VideoId"`
}
// VideoBase is a nested struct in vod response
type VideoBase struct {
OutputType string `json:"OutputType" xml:"OutputType"`
CoverURL string `json:"CoverURL" xml:"CoverURL"`
Duration string `json:"Duration" xml:"Duration"`
Status string `json:"Status" xml:"Status"`
Title string `json:"Title" xml:"Title"`
VideoId string `json:"VideoId" xml:"VideoId"`
MediaType string `json:"MediaType" xml:"MediaType"`
CreationTime string `json:"CreationTime" xml:"CreationTime"`
TranscodeMode string `json:"TranscodeMode" xml:"TranscodeMode"`
//ThumbnailList ThumbnailListInGetPlayInfo `json:"ThumbnailList" xml:"ThumbnailList"`
}
type PlayInfoListInGetPlayInfo struct {
PlayInfo []PlayInfo `json:"PlayInfo" xml:"PlayInfo"`
}
// PlayInfo is a nested struct in vod response
type PlayInfo struct {
JobId string `json:"JobId" xml:"JobId"`
Format string `json:"Format" xml:"Format"`
PreprocessStatus string `json:"PreprocessStatus" xml:"PreprocessStatus"`
EncryptType string `json:"EncryptType" xml:"EncryptType"`
Fps string `json:"Fps" xml:"Fps"`
ModificationTime string `json:"ModificationTime" xml:"ModificationTime"`
NarrowBandType string `json:"NarrowBandType" xml:"NarrowBandType"`
Bitrate string `json:"Bitrate" xml:"Bitrate"`
Encrypt int64 `json:"Encrypt" xml:"Encrypt"`
Rand string `json:"Rand" xml:"Rand"`
CreationTime string `json:"CreationTime" xml:"CreationTime"`
StreamType string `json:"StreamType" xml:"StreamType"`
Height int64 `json:"Height" xml:"Height"`
WatermarkId string `json:"WatermarkId" xml:"WatermarkId"`
Duration string `json:"Duration" xml:"Duration"`
Complexity string `json:"Complexity" xml:"Complexity"`
Width int64 `json:"Width" xml:"Width"`
Size int64 `json:"Size" xml:"Size"`
Status string `json:"Status" xml:"Status"`
Definition string `json:"Definition" xml:"Definition"`
Plaintext string `json:"Plaintext" xml:"Plaintext"`
PlayURL string `json:"PlayURL" xml:"PlayURL"`
Specification string `json:"Specification" xml:"Specification"`
}
//GetVideoPlayAuthResponse is the response struct for api GetVideoPlayAuth
type GetVideoPlayAuthResponse struct {
RequestId string `json:"requestId" xml:"RequestId"`
PlayAuth string `json:"playAuth" xml:"PlayAuth"`
VideoMeta VideoMeta `json:"videoMeta" xml:"VideoMeta"`
}
// VideoMeta is a nested struct in vod response
type VideoMeta struct {
CoverURL string `json:"coverURL" xml:"CoverURL"`
Duration float64 `json:"duration" xml:"Duration"`
Status string `json:"-" xml:"Status"`
Title string `json:"title" xml:"Title"`
VideoId string `json:"videoId" xml:"VideoId"`
}
... ...
package aliyun
type CreateUploadImageRequest struct {
FileName string `json:"fileName"`
}
type CreateUploadImageResponse struct {
RequestId string `json:"requestId"`
ImageId string `json:"imageId" `
ImageURL string `json:"imageURL"`
UploadAddress string `json:"uploadAddress"`
UploadAuth string `json:"uploadAuth"`
FileURL string `json:"fileURL"`
}
type CreateUploadImagesRequest struct {
Items []*CreateUploadImageRequest `json:"items"`
}
type CreateUploadImagesResponse struct {
List []*CreateUploadImageResponse `json:"list"`
}
... ...
package aliyun
import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"
)
type UploadAddress struct {
Endpoint string
Bucket string
FileName string
}
//@cname 绑定域名
func (up UploadAddress) GetFileUrl(cname string) string {
if len(cname) > 0 {
return fmt.Sprintf("%v%v", cname, up.FileName)
}
if strings.Contains(up.Endpoint, "https") {
return fmt.Sprintf("%v%v.%v/%v", up.Endpoint[:8], up.Bucket, up.Endpoint[8:], up.FileName)
} else if strings.Contains(up.Endpoint, "http") {
return fmt.Sprintf("%v%v.%v/%v", up.Endpoint[:7], up.Bucket, up.Endpoint[7:], up.FileName)
}
return ""
}
//解析UploadAddress
func ParseUploadAddress(uploadAddress string) (up UploadAddress, err error) {
var jsData []byte
jsData, err = base64.StdEncoding.DecodeString(uploadAddress)
if err != nil {
return
}
if err = json.Unmarshal(jsData, &up); err != nil {
return
}
return
}
... ...
package aliyun
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vod"
"github.com/astaxie/beego"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
comm_time "gitlab.fjmaimaimai.com/mmm-go/gocomm/time"
"openapi/internal/utils"
"path"
"path/filepath"
"time"
)
//客户端
func DefaultVodClient() (client *vod.Client, err error) {
return InitVodClient(AccessKeyID, AccessKeySecret)
}
//初始化客户端
func InitVodClient(accessKeyId string, accessKeySecret string) (client *vod.Client, err error) {
// 点播服务接入区域
regionId := RegionID
// 创建授权对象
credential := &credentials.AccessKeyCredential{
accessKeyId,
accessKeySecret,
}
// 自定义config
config := sdk.NewConfig()
config.AutoRetry = true // 失败是否自动重试
config.MaxRetryTime = 3 // 最大重试次数
config.Timeout = 3000000000 // 连接超时,单位:纳秒;默认为3秒
// 创建vodClient实例
return vod.NewClientWithOptions(regionId, config, credential)
}
//获取视频上传地址和凭证,并创建视频信息
func CreateUploadVideo(client *vod.Client, r *CreateUploadVideoRequest) (response *CreateUploadVideoResponse, err error) {
request := vod.CreateCreateUploadVideoRequest()
filePath := getFileName(FileVideo, r.FileName)
if filepath.Ext(r.FileName) == "mp3" {
filePath = getFileName(FileVoice, r.FileName)
}
request.Title = filePath
request.FileName = filePath
request.AcceptFormat = "JSON"
rsp, err := client.CreateUploadVideo(request)
if err != nil {
return
}
response = &CreateUploadVideoResponse{
RequestId: rsp.RequestId,
VideoId: rsp.VideoId,
UploadAddress: rsp.UploadAddress,
UploadAuth: rsp.UploadAuth,
}
if up, e := ParseUploadAddress(rsp.UploadAddress); e != nil {
log.Error(e)
} else {
response.FileURL = up.GetFileUrl("")
}
return
}
func RefreshUploadVideo(client *vod.Client, r *RefreshUploadVideoRequest) (response *RefreshUploadVideoResponse, err error) {
request := vod.CreateRefreshUploadVideoRequest()
request.VideoId = r.VideoId
request.AcceptFormat = "JSON"
var rsp *vod.RefreshUploadVideoResponse
rsp, err = client.RefreshUploadVideo(request)
if err != nil {
return
}
if err = utils.JsonDeepCopy(&response, &rsp); err != nil {
return
}
if up, e := ParseUploadAddress(rsp.UploadAddress); e != nil {
log.Error(e)
} else {
response.FileURL = up.GetFileUrl("")
}
return
}
//获取图片上传地址和凭证,并创建视频信息
func CreateUploadImage(client *vod.Client, r *CreateUploadImageRequest) (response *CreateUploadImageResponse, err error) {
request := vod.CreateCreateUploadImageRequest()
filePath := getFileName(FileImage, r.FileName)
request.ImageType = "default"
request.Title = filePath
request.ImageExt = filepath.Ext(r.FileName)[1:]
request.AcceptFormat = "JSON"
//request.StorageLocation = filepath.Base(request.Title)
rsp, err := client.CreateUploadImage(request)
if err != nil {
return
}
err = utils.JsonDeepCopy(&response, &rsp)
return
}
//获取播放信息
func GetPlayInfo(client *vod.Client, r *GetPlayInfoRequest) (response *vod.GetPlayInfoResponse, err error) {
request := vod.CreateGetPlayInfoRequest()
request.VideoId = r.VideoId
request.AcceptFormat = "JSON"
return client.GetPlayInfo(request)
}
//获取播放信息
func GetGetVideoPlayAuth(client *vod.Client, r *GetVideoPlayAuthRequest) (response GetVideoPlayAuthResponse, err error) {
request := vod.CreateGetVideoPlayAuthRequest()
request.VideoId = r.VideoId
request.AcceptFormat = "JSON"
var rsp *vod.GetVideoPlayAuthResponse
if rsp, err = client.GetVideoPlayAuth(request); err != nil {
log.Error(err)
return
}
err = utils.JsonDeepCopy(&response, rsp)
return
}
//fileType: video voice image
func getFileName(fileType string, filename string) string {
date := comm_time.GetTimeByYyyymmdd()
subfix := path.Ext(filename)
prefix := fmt.Sprintf("%v_%v", time.Now().Unix(), common.RandomString(32))
filename = fmt.Sprintf("%v%v", prefix, subfix)
sourcePath := fmt.Sprintf("%v/%v/%v/%v/%v", beego.BConfig.AppName, beego.BConfig.RunMode, fileType, date, filename)
return sourcePath
}
... ...
package utils
import "os"
// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}
// 判断所给路径是否为文件夹
func IsDir(path string) bool {
s, err := os.Stat(path)
if err != nil {
return false
}
return s.IsDir()
}
// 判断所给路径是否为文件
func IsFile(path string) bool {
return !IsDir(path)
}
... ...
package utils
import "github.com/astaxie/beego"
func init() {
logLevelMap := make(map[string]int)
logLevelMap["debug"] = beego.LevelDebug
logLevelMap["info"] = beego.LevelInformational
logLevelMap["warn"] = beego.LevelWarning
logLevelMap["error"] = beego.LevelError
logLevelMap["fatal"] = beego.LevelEmergency
}
func ResolveLogLevel(level string) int {
switch level {
case "debug":
return beego.LevelDebug
case "info":
return beego.LevelInformational
case "warn":
return beego.LevelWarning
case "error":
return beego.LevelError
case "fatal":
return beego.LevelEmergency
}
return beego.LevelInformational
}
... ...
package utils
import (
"fmt"
"math"
"strconv"
)
func decimal(value float64) float64 {
return math.Trunc(value*1e1+0.5) * 1e-1
}
func Decimal(value float64) float64 {
value = decimal(value)
value, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", value), 64)
return value
}
func DecimalToNumber(value float64) float64 {
value = decimal(value)
value, _ = strconv.ParseFloat(fmt.Sprintf("%.f", value), 64)
return value
}
... ...
package utils
import (
"bytes"
"errors"
"fmt"
"github.com/astaxie/beego/orm"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"reflect"
"strings"
)
// 更新指定表的几个列
func UpdateTableByMap(tabeleStruct interface{}, changeMap map[string]interface{}) error {
if reflect.TypeOf(tabeleStruct).Kind() != reflect.Ptr {
err := errors.New("UpdateTableByMap: tableStruct must ptr")
log.Error(err)
return err
}
if len(changeMap) < 1 {
log.Info("changeMap is nil")
return nil
}
o := orm.NewOrm()
changeColumn := make([]string, 0, len(changeMap))
for i, v := range changeMap {
changeColumn = append(changeColumn, i)
if err := SetStructValueByType(tabeleStruct, i, v); err != nil {
log.Error(err, i, v)
return err
}
}
num, err := o.Update(tabeleStruct, changeColumn...)
if err != nil {
log.Error(err)
return err
}
log.Info(fmt.Sprintf("UpdateTableByMap: table:%s effect records:%d column:%v values:%v", GetTableName(tabeleStruct), num, changeColumn, changeMap))
return nil
}
func UpdateTableByMapWithOrmer(o orm.Ormer, tabeleStruct interface{}, changeMap map[string]interface{}) error {
if reflect.TypeOf(tabeleStruct).Kind() != reflect.Ptr {
err := errors.New("UpdateTableByMap: tableStruct must ptr")
log.Error(err)
return err
}
if len(changeMap) < 1 {
log.Info("changeMap is nil")
return nil
}
changeColumn := make([]string, 0, len(changeMap))
for i, v := range changeMap {
changeColumn = append(changeColumn, i)
if err := SetStructValueByType(tabeleStruct, i, v); err != nil {
log.Error(err, i, v)
return err
}
}
num, err := o.Update(tabeleStruct, changeColumn...)
if err != nil {
log.Error(err)
return err
}
log.Info(fmt.Sprintf("UpdateTableByMap: table:%s effect records:%d column:%v", GetTableName(tabeleStruct), num, changeColumn))
return nil
}
// 通过反射调用结构对应的TableName函数,达到返回表名的目的
func GetTableName(tableStruct interface{}) string {
m := reflect.ValueOf(tableStruct).MethodByName("TableName")
if m.IsValid() && m.Kind() == reflect.Func {
re := m.Call(nil)
for _, v := range re {
if v.IsValid() {
return v.String()
}
}
}
return "unknown"
}
// 通用事物提交sql结构体
type SqlData struct {
Sql string
Param []interface{}
}
func ExecuteSqlByRoll(isCheck bool, sqlSlice ...*SqlData) bool {
o := orm.NewOrm()
var someError bool = false
o.Begin()
for i := range sqlSlice {
if sqlSlice[i].Sql == "" {
continue
}
log.Info("execute sql:", sqlSlice[i])
if ret, err := o.Raw(sqlSlice[i].Sql, sqlSlice[i].Param...).Exec(); err != nil {
log.Error(err)
someError = true
} else {
num, _ := ret.RowsAffected()
log.Debug("num:", num)
if isCheck && num < 1 {
someError = true
}
}
}
if someError {
log.Error("出错,回滚事物")
o.Rollback()
return false
} else {
log.Info("成功,提交事物")
o.Commit()
return true
}
return true
}
//PrintLogSql 打印sql语句
func PrintLogSql(sql string, param ...interface{}) {
format := `SQL EXCEUTE:[%s]-%s`
parmformat := `[%v]`
var p strings.Builder
for i := range param {
p.WriteString(fmt.Sprintf(parmformat, param[i]))
}
log.Debug(fmt.Sprintf(format, sql, p.String()))
}
//ExecuteQueryOne 执行原生sql查询单条记录;结果用结构体接收
func ExecuteQueryOne(result interface{}, sqlstr string, param ...interface{}) error {
var err error
o := orm.NewOrm()
err = ExecuteQueryOneWithOrmer(o, result, sqlstr, param)
return err
}
//ExecuteQueryOneWithOrmer 执行原生sql查询单条
func ExecuteQueryOneWithOrmer(o orm.Ormer, result interface{}, sqlstr string, param ...interface{}) error {
PrintLogSql(sqlstr, param...)
var err error
err = o.Raw(sqlstr, param).QueryRow(result)
if err != nil {
return err
}
return nil
}
//ExecuteQuerySql 执行原生sql查询多条记录
func ExecuteQueryAll(result interface{}, sqlstr string, param ...interface{}) error {
//PrintLogSql(sqlstr, param...)
var err error
o := orm.NewOrm()
err = ExecuteQueryAllWithOrmer(o, result, sqlstr, param)
return err
}
//ExecuteQueryOneWithOrmer 执行原生sql查询多条记录
func ExecuteQueryAllWithOrmer(o orm.Ormer, result interface{}, sqlstr string, param ...interface{}) error {
PrintLogSql(sqlstr, param...)
var (
err error
)
_, err = o.Raw(sqlstr, param).QueryRows(result)
if err != nil {
return err
}
return nil
}
func ExecuteSQLWithOrmer(o orm.Ormer, sqlstr string, param ...interface{}) error {
PrintLogSql(sqlstr, param...)
var (
err error
)
r, err := o.Raw(sqlstr, param...).Exec()
if err != nil {
return err
}
num, _ := r.RowsAffected()
log.Debug(fmt.Sprintf("RowsAffected:%d", num))
return nil
}
type SqlExcutor struct {
table string
wherestr []string
orderstr []string
islimit bool
offset int
pagenum int
}
func NewSqlExutor() *SqlExcutor {
return &SqlExcutor{}
}
func (s *SqlExcutor) Table(str string) *SqlExcutor {
s.table = str
return s
}
func (s *SqlExcutor) Where(condition ...string) *SqlExcutor {
if len(condition) <= 0 {
return s
}
s.wherestr = append(s.wherestr, condition...)
return s
}
func (s *SqlExcutor) Order(condition ...string) *SqlExcutor {
if len(condition) <= 0 {
return s
}
s.orderstr = append(s.orderstr, condition...)
return s
}
func (s *SqlExcutor) Limit(page, pagenum int) *SqlExcutor {
offset := 0
if page > 0 {
offset = (page - 1) * pagenum
}
s.islimit = true
s.offset = offset
s.pagenum = pagenum
return s
}
func (s *SqlExcutor) WhereString() string {
sql := bytes.NewBufferString("")
if len(s.wherestr) > 0 {
sql.WriteString(" where ")
for i := range s.wherestr {
if i != 0 {
sql.WriteString(" AND ")
}
sql.WriteString(s.wherestr[i])
}
}
return sql.String()
}
... ...
package utils
import (
"bytes"
"encoding/gob"
"encoding/json"
"errors"
"fmt"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"reflect"
"strconv"
"strings"
"time"
)
// 此函数将指定的结构体成员值更新到结构体中
func SetStructValueByType(s interface{}, columnType string, columnValue interface{}) error {
columnValueV := reflect.ValueOf(columnValue)
var setValue reflect.Value
var flag = false
v := reflect.ValueOf(s)
for i, n := 0, v.Elem().NumField(); i < n; i++ {
if v.Elem().Type().Field(i).Name == columnType {
setValue = v.Elem().Field(i)
flag = true
break
}
}
if !flag {
return errors.New("struct is not type:")
} else if !setValue.CanSet() {
return errors.New("setValue.CanSet is false")
} else if setValue.Kind() != columnValueV.Kind() {
return errors.New("struct field and value of type is error")
}
switch columnValueV.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
setValue.SetInt(int64(columnValueV.Int()))
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
setValue.SetUint(uint64(columnValueV.Uint()))
case reflect.Float32, reflect.Float64:
setValue.SetFloat(float64(columnValueV.Float()))
case reflect.String:
setValue.SetString(columnValueV.String())
case reflect.Struct:
setValue.Set(columnValueV)
default:
return errors.New("columnValue err for:" + columnType)
}
return nil
}
func JoinInts(ids []int, spilt string) string {
var idStrings []string = make([]string, len(ids))
for i := 0; i < len(ids); i++ {
idStrings[i] = fmt.Sprintf("%v", ids[i])
}
return strings.Join(idStrings, spilt)
}
func JoinInt8s(ids []int8, spilt string) string {
var idStrings []string = make([]string, len(ids))
for i := 0; i < len(ids); i++ {
idStrings[i] = fmt.Sprintf("%v", ids[i])
}
return strings.Join(idStrings, spilt)
}
func JoinInt64s(ids []int64, spilt string) string {
var idStrings []string = make([]string, len(ids))
for i := 0; i < len(ids); i++ {
idStrings[i] = fmt.Sprintf("%v", ids[i])
}
return strings.Join(idStrings, spilt)
}
//判断是否为空
func IsNil(i interface{}) bool {
vi := reflect.ValueOf(i)
if vi.Kind() == reflect.Ptr {
return vi.IsNil()
}
return false
}
func JsonUnmarshal(jsonData string, v interface{}) {
if len(jsonData) == 0 {
return
}
if e := json.Unmarshal([]byte(jsonData), v); e != nil {
log.Error("json.unmarshal error data:", jsonData, e)
}
}
//深度拷贝
func DeepCopy(dst, src interface{}) error {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(src); err != nil {
return err
}
return gob.NewDecoder(&buf).Decode(dst)
}
//深度拷贝
func JsonDeepCopy(dst, src interface{}) error {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(src); err != nil {
return err
}
return json.NewDecoder(&buf).Decode(dst)
}
//检查版本信息
func ValidVersion(current, compare string) bool {
curVersions := strings.Split(current, ".")
comVersions := strings.Split(compare, ".")
for i := range curVersions {
//v1,v2:=strings.TrimSpace(curVersions[i]),""
v1, _ := strconv.ParseInt(strings.TrimSpace(curVersions[i]), 10, 64)
var v2 int64
if i < len(comVersions) {
v2, _ = strconv.ParseInt(strings.TrimSpace(comVersions[i]), 10, 64)
}
if v1 == 0 && v2 == 0 {
continue
}
if v1 >= v2 {
return true
}
if v1 < v2 {
return false
}
}
return false
}
// 统计某函数执行时间
// 使用方式
// defer utils.Profiling("test")()
func Profiling(msg string) func() {
start := time.Now()
return func() {
log.Info(fmt.Sprintf("%s[%s]:%s", msg, "use", time.Since(start)))
}
}
//合并字典
func MergeMap(to map[string]interface{}, from map[string]interface{}) {
for k, v := range from {
to[k] = v
}
}
func GetPageInfo(pageIndex, pageSize int) (offset, size int) {
if pageSize == 0 {
pageSize = 20
}
if pageIndex == 0 {
pageIndex = 1
}
offset = (pageIndex - 1) * pageSize
size = pageSize
return
}
... ...
package utils
import (
"encoding/json"
"fmt"
"testing"
)
func Test_DeepCopy(t *testing.T) {
type User1 struct {
Name string
Age int
Address string
}
type User2 struct {
Name string
Age int
Job string
}
var src = User1{Name: "foo", Age: 10, Address: "bar"}
var dst *User2
if err := DeepCopy(&dst, src); err != nil {
t.Fatal(err)
}
if src.Name != dst.Name {
t.Fatal("deep copy fail.")
}
//t.Log(src,"\n",dst)
}
func TestValidVersion(t *testing.T) {
inputs := []struct {
In string
Compare string
Out bool
}{
{In: "0.9.0", Compare: "0.8.0", Out: true},
{In: "0.8.11", Compare: "0.8.0", Out: true},
{In: "0.7.0", Compare: "0.8.0", Out: false},
{In: "0.8.0", Compare: "0.8.0", Out: true},
{In: "0.9", Compare: "0.8.0", Out: true},
{In: "0.10", Compare: "0.8.0", Out: true},
{In: "1.8.0", Compare: "0.8.0", Out: true},
{In: "0.99.0", Compare: "0.8.0", Out: true},
{In: "01.0.0", Compare: "0.8.0", Out: true},
}
for i := range inputs {
input := inputs[i]
if ValidVersion(input.In, input.Compare) != input.Out {
t.Fatal(fmt.Sprintf("valid version fail. input :%v compare:%v want:%v", input.In, input.Compare, input.Out))
}
}
}
func TestMergeMap(t *testing.T) {
to := map[string]interface{}{"1": 1, "2": 2}
from := map[string]interface{}{"3": 3, "4": 4}
t.Log("merge 前:", to)
MergeMap(to, from)
t.Log("merge 后:", to)
}
func TestIntUnmarsh(t *testing.T) {
jsonString := `{"id":8242051651122944}`
type param struct {
Id int `json:"id"`
}
var p param
json.Unmarshal([]byte(jsonString), &p)
t.Log(p)
jsonByte, _ := json.Marshal(p)
t.Log(string(jsonByte))
}
... ...
package main
import (
"github.com/astaxie/beego"
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
_ "openapi/routers"
"time"
)
func init() {
time.Local = time.FixedZone("CST", 3600*8)
}
func main() {
defer func() {
log.Info("app on stop!")
}()
log.Info("app on start!")
log.Info("Beego Run Mode:", beego.BConfig.RunMode)
beego.Run()
}
... ...
package protocol
const RelateSplit = "/"
... ...
package protocol
import (
"encoding/json"
)
//CustomErrParse 解析自定义错误结构体
type CustomErrParse interface {
ParseToMessage() *ResponseMessage
}
//ErrorMap 统一消息错误编码
type ErrorMap map[int]string
//Search 搜索错误描述
func (m ErrorMap) Search(code int) ErrorCode {
if v, ok := m[code]; ok {
return ErrorCode{
Errno: code,
Errmsg: v,
}
}
return ErrorCode{Errno: code, Errmsg: "错误码未定义"}
}
//ErrorCode 统一错误结构
type ErrorCode struct {
Errno int `json:"code"`
Errmsg string `json:"msg"`
}
//ResponseMessage 统一返回消息结构体
type ResponseMessage struct {
ErrorCode
Data interface{} `json:"data"`
}
func NewMesage(code int) *ResponseMessage {
return &ResponseMessage{
ErrorCode: SearchErr(code),
Data: nil,
}
}
//ErrWithMessage 自定义错误结构
type ErrWithMessage struct {
Err error `json:"-"`
ErrorCode
}
var (
_ CustomErrParse = new(ErrWithMessage)
_ error = new(ErrWithMessage)
)
//NewErrWithMessage 构建错误返回
//code:用于匹配统一消息错误编码 eRR:填充嵌套错误
func NewErrWithMessage(code int, eRR ...error) *ErrWithMessage {
r := &ErrWithMessage{
ErrorCode: SearchErr(code),
}
if len(eRR) > 0 {
r.Err = eRR[0]
}
return r
}
//Error 实现接口error 中的方法
//将ErrorCode转为json数据,建议用于日志记录
func (e ErrWithMessage) Error() string {
bt, _ := json.Marshal(e.ErrorCode)
return string(bt)
}
//Unwrap 接口实现
func (e ErrWithMessage) Unwrap() error {
return e.Err
}
//ParseToMessage 实现CustomErrParse的接口
func (e ErrWithMessage) ParseToMessage() *ResponseMessage {
return &ResponseMessage{
ErrorCode: e.ErrorCode,
Data: nil,
}
}
func SearchErr(code int) ErrorCode {
return errmessge.Search(code)
}
func NewReturnResponse(data interface{}, eRR error) *ResponseMessage {
var msg *ResponseMessage
if eRR == nil {
msg = NewMesage(0)
msg.Data = data
return msg
}
// fmt.Println("日志:" + eRR.Error())
if x, ok := eRR.(CustomErrParse); ok {
msg = x.ParseToMessage()
msg.Data = data
return msg
}
return NewMesage(1)
}
func BadRequestParam(code int) *ResponseMessage {
return NewMesage(code)
}
func NewSuccessWithMessage(msg string) *ErrWithMessage {
return &ErrWithMessage{
Err: nil,
ErrorCode: ErrorCode{0, msg},
}
}
func NewCustomMessage(code int, msg string) *ErrWithMessage {
return &ErrWithMessage{
Err: nil,
ErrorCode: ErrorCode{code, msg},
}
}
... ...
package protocol
import (
"fmt"
"sync/atomic"
)
type RequestHeader struct {
TimeStamp string
Version string
Uuid string
Sign string
DeviceType int
AppProject string
AccessToken string
Uid int64 //用户基本信息Id
CompanyId int64
UserId int64 //UserId 唯一标识,唯一关联所有用户信息(=user_company.id)
requestId string //请求编号 md5
reqIndex int64 //请求链序号
}
func (reqHead *RequestHeader) SetRequestId(addString ...string) {
if len(addString) == 0 {
return
}
reqHead.requestId = addString[0]
}
func (reqHead *RequestHeader) GetRequestId() string {
atomic.AddInt64(&reqHead.reqIndex, 1)
return fmt.Sprintf("%s.%d", reqHead.requestId, reqHead.reqIndex)
}
... ...
package protocol
var errmessge ErrorMap = map[int]string{
0: "成功",
1: "系统异常",
2: "参数错误",
}
... ...
package protocol
import "mime/multipart"
const (
FileImage = "image"
FileVoice = "voice"
FileVideo = "video"
)
/*Image */
type FileRequest struct {
//Xxx string`json:"xxx" valid:"Required"`
Files []*multipart.FileHeader
FileType string
}
type FileResponse struct {
Paths []string `json:"paths"`
}
... ...
package routers
import (
"github.com/astaxie/beego"
"openapi/controllers"
"openapi/controllers/v1"
)
var nsV1 *beego.Namespace
func init() {
nsV1 := beego.NewNamespace("v1",
beego.NSNamespace("vod", beego.NSBefore(controllers.FilterComm), beego.NSBefore(controllers.AllowOption), beego.NSInclude(&v1.VodController{})),
)
beego.AddNamespace(nsV1)
}
... ...
package vod
import (
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
"openapi/internal/aliyun"
"openapi/protocol"
)
//创建视频上传凭证
func CreateUploadVideo(header *protocol.RequestHeader, request *aliyun.CreateUploadVideoRequest) (rsp *aliyun.CreateUploadVideoResponse, err error) {
var ()
client, e := aliyun.DefaultVodClient()
if e != nil {
log.Error(e)
err = e
return
}
rsp, err = aliyun.CreateUploadVideo(client, request)
if err != nil {
log.Error(err)
}
return
}
//创建视频上传凭证
func RefreshUploadVideo(header *protocol.RequestHeader, request *aliyun.RefreshUploadVideoRequest) (rsp *aliyun.RefreshUploadVideoResponse, err error) {
var ()
client, e := aliyun.DefaultVodClient()
if e != nil {
log.Error(e)
err = e
return
}
rsp, err = aliyun.RefreshUploadVideo(client, request)
if err != nil {
log.Error(err)
}
return
}
//创建图片上传凭证
func CreateUploadImage(header *protocol.RequestHeader, request *aliyun.CreateUploadImageRequest) (rsp *aliyun.CreateUploadImageResponse, err error) {
var ()
client, e := aliyun.DefaultVodClient()
if e != nil {
log.Error(e)
err = e
return
}
if len(request.FileName) == 0 {
request.FileName = aliyun.DefaultImageFileName
}
rsp, err = aliyun.CreateUploadImage(client, request)
if err != nil {
log.Error(err)
}
return
}
//获取视频播放地址
func GetPlayInfo(header *protocol.RequestHeader, request *aliyun.GetPlayInfoRequest) (rsp interface{}, err error) {
var ()
client, e := aliyun.DefaultVodClient()
if e != nil {
log.Error(e)
err = e
return
}
rsp, err = aliyun.GetPlayInfo(client, request)
if err != nil {
log.Error(err)
}
return
}
//获取视频播放凭证
func GetVideoPlayAuth(header *protocol.RequestHeader, request *aliyun.GetVideoPlayAuthRequest) (rsp interface{}, err error) {
var ()
client, e := aliyun.DefaultVodClient()
if e != nil {
log.Error(e)
err = e
return
}
rsp, err = aliyun.GetGetVideoPlayAuth(client, request)
if err != nil {
log.Error(err)
}
return
}
... ...