Create & Init Project...
This commit is contained in:
102
app/admin/ep/merlin/dao/BUILD
Normal file
102
app/admin/ep/merlin/dao/BUILD
Normal file
@ -0,0 +1,102 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bilihub.go",
|
||||
"dao.go",
|
||||
"dashboard.go",
|
||||
"devicefarm.go",
|
||||
"docker.go",
|
||||
"mail.go",
|
||||
"mysql_application_record.go",
|
||||
"mysql_dashboard.go",
|
||||
"mysql_hubimage_confs.go",
|
||||
"mysql_hubimage_logs.go",
|
||||
"mysql_image.go",
|
||||
"mysql_machine.go",
|
||||
"mysql_machineV2.go",
|
||||
"mysql_machine_log.go",
|
||||
"mysql_machine_node.go",
|
||||
"mysql_machine_package.go",
|
||||
"mysql_mail_log.go",
|
||||
"mysql_mobile_machine.go",
|
||||
"mysql_mobile_machine_error_log.go",
|
||||
"mysql_mobile_machine_log.go",
|
||||
"mysql_mobile_sync_log.go",
|
||||
"mysql_snapshot_record.go",
|
||||
"mysql_task.go",
|
||||
"mysql_user.go",
|
||||
"paas.go",
|
||||
"tree.go",
|
||||
"wechat.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/merlin/dao",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/merlin/conf:go_default_library",
|
||||
"//app/admin/ep/merlin/model:go_default_library",
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/database/orm:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/sync/pipeline/fanout:go_default_library",
|
||||
"//vendor/github.com/docker/docker/api/types:go_default_library",
|
||||
"//vendor/github.com/docker/docker/api/types/filters:go_default_library",
|
||||
"//vendor/github.com/docker/docker/client:go_default_library",
|
||||
"//vendor/github.com/jinzhu/gorm:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/gopkg.in/gomail.v2:go_default_library",
|
||||
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"dao_test.go",
|
||||
"mail_test.go",
|
||||
"mysql_image_test.go",
|
||||
"mysql_machine_log_test.go",
|
||||
"mysql_machine_test.go",
|
||||
"mysql_mail_log_test.go",
|
||||
"mysql_task_test.go",
|
||||
"mysql_user_test.go",
|
||||
"paas_test.go",
|
||||
"tree_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/ep/merlin/conf:go_default_library",
|
||||
"//app/admin/ep/merlin/model:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
|
||||
"//vendor/gopkg.in/gomail.v2:go_default_library",
|
||||
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
|
||||
],
|
||||
)
|
169
app/admin/ep/merlin/dao/bilihub.go
Normal file
169
app/admin/ep/merlin/dao/bilihub.go
Normal file
@ -0,0 +1,169 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_projectURI = "/api/projects"
|
||||
_repositoryURI = "/api/repositories"
|
||||
_authHubURI = "/api/platformUsers?role=2&session="
|
||||
)
|
||||
|
||||
// AuthHub Auth Hub.
|
||||
func (d *Dao) AuthHub(c context.Context, sessionID string) (err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res interface{}
|
||||
)
|
||||
url := d.c.BiliHub.Host + _authHubURI + sessionID
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
err = ecode.MerlinNoHubAccount
|
||||
log.Error("d.AuthHub url(%s) err(%v)", url, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HubProjects Get Hub Projects.
|
||||
func (d *Dao) HubProjects(c context.Context, projectName string) (projects []*model.HubProject, err error) {
|
||||
var req *http.Request
|
||||
|
||||
url := d.c.BiliHub.Host + _projectURI + "?page=1&page_size=15&name=" + projectName
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, &projects); err != nil {
|
||||
log.Error("d.HubProjects url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ProjectRepoCount Get Project RepoCount.
|
||||
func (d *Dao) ProjectRepoCount(c context.Context, projectID int) (total int, err error) {
|
||||
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.GetHubProjectDetailResponse{}
|
||||
)
|
||||
|
||||
url := d.c.BiliHub.Host + _projectURI + "/" + strconv.Itoa(projectID)
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.ProjectRepoCount url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
return
|
||||
}
|
||||
|
||||
return res.RepoCount, err
|
||||
}
|
||||
|
||||
// ProjectRepos Get Project Repos.
|
||||
func (d *Dao) ProjectRepos(c context.Context, projectID, pageNum, pageSize int, keyWord string) (projectRepos []*model.ProjectRepository, err error) {
|
||||
var req *http.Request
|
||||
|
||||
host := d.c.BiliHub.Host + _repositoryURI + "?project_id=%s&page=%s&page_size=%s&q=%s"
|
||||
url := fmt.Sprintf(host, strconv.Itoa(projectID), strconv.Itoa(pageNum), strconv.Itoa(pageSize), keyWord)
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, &projectRepos); err != nil {
|
||||
log.Error("d.ProjectRepos url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RepoTags Get Repo Tags.
|
||||
func (d *Dao) RepoTags(c context.Context, repoName string) (repoTags []*model.RepositoryTagResponse, err error) {
|
||||
var req *http.Request
|
||||
|
||||
host := d.c.BiliHub.Host + _repositoryURI + "/%s/tags"
|
||||
url := fmt.Sprintf(host, repoName)
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, &repoTags); err != nil {
|
||||
log.Error("d.RepoTags url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteRepoTag Delete Repo Tag.
|
||||
func (d *Dao) DeleteRepoTag(c context.Context, repoName, tagName string) (err error) {
|
||||
var req *http.Request
|
||||
|
||||
host := d.c.BiliHub.Host + _repositoryURI + "/%s/tags/%s"
|
||||
url := fmt.Sprintf(host, repoName, tagName)
|
||||
|
||||
if req, err = d.newRequest(http.MethodDelete, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, nil); err != nil {
|
||||
log.Error("d.DeleteRepoTag url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteRepo Delete Repo.
|
||||
func (d *Dao) DeleteRepo(c context.Context, repoName string) (err error) {
|
||||
var req *http.Request
|
||||
|
||||
url := d.c.BiliHub.Host + _repositoryURI + "/" + repoName
|
||||
|
||||
if req, err = d.newRequest(http.MethodDelete, url, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.SetBasicAuth(d.c.BiliHub.Username, d.c.BiliHub.Password)
|
||||
|
||||
if err = d.httpClient.Do(c, req, nil); err != nil {
|
||||
log.Error("d.DeleteRepo url(%s) err(%v)", url, err)
|
||||
err = ecode.MerlinHubRequestErr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ImageTask Image Task.
|
||||
func (d *Dao) ImageTask(imageTask func()) {
|
||||
d.hubCache.Do(context.Background(), func(c context.Context) {
|
||||
imageTask()
|
||||
})
|
||||
}
|
114
app/admin/ep/merlin/dao/dao.go
Normal file
114
app/admin/ep/merlin/dao/dao.go
Normal file
@ -0,0 +1,114 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/conf"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/database/orm"
|
||||
"go-common/library/log"
|
||||
xhttp "go-common/library/net/http/blademaster"
|
||||
"go-common/library/sync/pipeline/fanout"
|
||||
|
||||
dclient "github.com/docker/docker/client"
|
||||
"github.com/jinzhu/gorm"
|
||||
"gopkg.in/gomail.v2"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
// Dao dao.
|
||||
type Dao struct {
|
||||
c *conf.Config
|
||||
httpClient *xhttp.Client
|
||||
db *gorm.DB
|
||||
email *gomail.Dialer
|
||||
mc *memcache.Pool
|
||||
cache *fanout.Fanout
|
||||
hubCache *fanout.Fanout
|
||||
expire int32
|
||||
dockerClient *dclient.Client
|
||||
}
|
||||
|
||||
// New init mysql db.
|
||||
func New(c *conf.Config) *Dao {
|
||||
var (
|
||||
dc *dclient.Client
|
||||
err error
|
||||
)
|
||||
|
||||
if dc, err = dclient.NewClientWithOpts(dclient.FromEnv); err != nil {
|
||||
log.Error("docker client init error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Dao{
|
||||
c: c,
|
||||
httpClient: xhttp.NewClient(c.HTTPClient),
|
||||
db: orm.NewMySQL(c.ORM),
|
||||
email: gomail.NewDialer(c.Mail.Host, c.Mail.Port, c.Mail.Username, c.Mail.Password),
|
||||
mc: memcache.NewPool(c.Memcache.Config),
|
||||
cache: fanout.New("cache", fanout.Worker(10), fanout.Buffer(10240)),
|
||||
hubCache: fanout.New("hubCache", fanout.Worker(10), fanout.Buffer(10240)),
|
||||
expire: int32(time.Duration(c.Memcache.Expire) / time.Second),
|
||||
dockerClient: dc,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Close close the resource.
|
||||
func (d *Dao) Close() {
|
||||
if d.db != nil {
|
||||
d.db.Close()
|
||||
}
|
||||
if d.mc != nil {
|
||||
d.mc.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// SetProxy set test proxy.
|
||||
func (d *Dao) SetProxy() {
|
||||
d.httpClient.SetTransport(gock.DefaultTransport)
|
||||
}
|
||||
|
||||
func (d *Dao) newRequest(method, url string, v interface{}) (req *http.Request, err error) {
|
||||
body := &bytes.Buffer{}
|
||||
if method != http.MethodGet {
|
||||
if err = json.NewEncoder(body).Encode(v); err != nil {
|
||||
log.Error("json encode value(%s) err(?) ", v, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if req, err = http.NewRequest(method, url, body); err != nil {
|
||||
log.Error("http new request url(?) err(?)", url, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Ping verify server is ok.
|
||||
func (d *Dao) Ping(c context.Context) (err error) {
|
||||
if err = d.db.DB().Ping(); err != nil {
|
||||
log.Info("dao.cloudDB.Ping() error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// tokenCacheSave The err does not need to return, because this method is irrelevant.
|
||||
func (d *Dao) tokenCacheSave(c context.Context, cacheItem *memcache.Item) {
|
||||
var f = func(c context.Context) {
|
||||
var (
|
||||
conn = d.mc.Get(c)
|
||||
err error
|
||||
)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(cacheItem); err != nil {
|
||||
log.Error("AddCache conn.Set(%s) error(%v)", cacheItem.Key, err)
|
||||
}
|
||||
}
|
||||
if err := d.cache.Do(c, f); err != nil {
|
||||
log.Error("Token cache save err(%v)", err)
|
||||
}
|
||||
}
|
44
app/admin/ep/merlin/dao/dao_test.go
Normal file
44
app/admin/ep/merlin/dao/dao_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/ep/merlin/conf"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
c context.Context
|
||||
)
|
||||
|
||||
func init() {
|
||||
dir, _ := filepath.Abs("../cmd/convey-test.toml")
|
||||
flag.Set("conf", dir)
|
||||
conf.Init()
|
||||
d = New(conf.Conf)
|
||||
d.httpClient.SetTransport(gock.DefaultTransport)
|
||||
c = ctx()
|
||||
}
|
||||
|
||||
func httpMock(method, url string) *gock.Request {
|
||||
r := gock.New(url)
|
||||
r.Method = strings.ToUpper(method)
|
||||
return r
|
||||
}
|
||||
|
||||
func ctx() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func WithPaasToken(f func()) func() {
|
||||
return func() {
|
||||
d.paasToken(c)
|
||||
f()
|
||||
}
|
||||
}
|
41
app/admin/ep/merlin/dao/dashboard.go
Normal file
41
app/admin/ep/merlin/dao/dashboard.go
Normal file
@ -0,0 +1,41 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/cache/memcache"
|
||||
)
|
||||
|
||||
//QueryMachineUsageSummaryFromCache Machine Usage Summary In Cache.
|
||||
func (d *Dao) QueryMachineUsageSummaryFromCache(c context.Context, pqadmrs []*model.PaasQueryAndDelMachineRequest) (pmds []*model.PaasMachineDetail, err error) {
|
||||
var (
|
||||
conn = d.mc.Get(c)
|
||||
item *memcache.Item
|
||||
)
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
for _, pqadmr := range pqadmrs {
|
||||
|
||||
pmd := &model.PaasMachineDetail{}
|
||||
|
||||
if item, err = conn.Get(pqadmr.Name); err == nil {
|
||||
if err = conn.Scan(item, &pmd); err == nil {
|
||||
pmds = append(pmds, pmd)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if pmd, err = d.QueryPaasMachine(c, pqadmr); err != nil {
|
||||
continue
|
||||
}
|
||||
pmds = append(pmds, pmd)
|
||||
|
||||
item = &memcache.Item{Key: pqadmr.Name, Object: pmd, Flags: memcache.FlagJSON, Expiration: d.expire}
|
||||
|
||||
d.tokenCacheSave(c, item)
|
||||
|
||||
}
|
||||
return
|
||||
}
|
143
app/admin/ep/merlin/dao/devicefarm.go
Normal file
143
app/admin/ep/merlin/dao/devicefarm.go
Normal file
@ -0,0 +1,143 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_deviceCode = 0
|
||||
_devicesListURL = "/apis/devices/list"
|
||||
_deviceURL = "/apis/devices/get"
|
||||
_deviceBootURL = "/apis/devices/boot"
|
||||
_deviceShutDownURL = "/apis/devices/shutdown"
|
||||
)
|
||||
|
||||
// MobileDeviceList Get Device Farm List .
|
||||
func (d *Dao) MobileDeviceList(c context.Context) (resTotal map[string][]*model.Device, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
hostList = d.c.DeviceFarm.HostList
|
||||
)
|
||||
|
||||
resTotal = make(map[string][]*model.Device)
|
||||
|
||||
for _, host := range hostList {
|
||||
|
||||
var res *model.DeviceListResponse
|
||||
|
||||
url := fmt.Sprintf("http://%s", host+_devicesListURL)
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
log.Error("d.MobileDeviceList newRequest url(%s) err(%+v)", _devicesListURL, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.MobileDeviceList httpClient url(%s) err(%+v)", _devicesListURL, err)
|
||||
continue
|
||||
}
|
||||
if res.Status.Code != _deviceCode {
|
||||
err = ecode.MerlinDeviceFarmErr
|
||||
log.Error("Status url(%s) res(%s),err(%+v)", _devicesListURL, res, err)
|
||||
continue
|
||||
}
|
||||
|
||||
resTotal[host] = res.Data.Devices
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileDeviceDetail Get Mobile Device Detail.
|
||||
func (d *Dao) MobileDeviceDetail(c context.Context, host, serial string) (device *model.Device, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.DeviceListDetailResponse
|
||||
)
|
||||
|
||||
url := fmt.Sprintf("http://%s?serial=%s", host+_deviceURL, serial)
|
||||
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
|
||||
log.Error("d.MobileDeviceDetail newRequest url(%s) err(%+v)", _deviceURL, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.MobileDeviceDetail url(%s) err(%+v)", _deviceURL, err)
|
||||
return
|
||||
}
|
||||
if res.Status.Code != _deviceCode {
|
||||
err = ecode.MerlinDeviceFarmErr
|
||||
log.Error("Status url(%s) res(%s) err(%+v)", _deviceURL, res, err)
|
||||
return
|
||||
}
|
||||
device = res.Data.Devices
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BootMobileDevice Boot Mobile Device.
|
||||
func (d *Dao) BootMobileDevice(c context.Context, host, serial string) (deviceBootData *model.DeviceBootData, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.DeviceBootResponse
|
||||
)
|
||||
|
||||
reqModel := &model.DeviceBootRequest{
|
||||
Serial: serial,
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("http://%s", host+_deviceBootURL)
|
||||
if req, err = d.newRequest(http.MethodPost, url, reqModel); err != nil {
|
||||
log.Error("d.BootMobileDevice newRequest url(%s) err(%+v)", _deviceBootURL, err)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("content-type", "application/json")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.BootMobileDevice url(%s) err(%+v)", _deviceBootURL, err)
|
||||
return
|
||||
}
|
||||
if res.Status.Code != _deviceCode {
|
||||
err = ecode.MerlinDeviceFarmErr
|
||||
log.Error("Status url(%s) res(%s) err(%+v)", _deviceBootURL, res, err)
|
||||
return
|
||||
}
|
||||
deviceBootData = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// ShutdownMobileDevice Shutdown Mobile Device.
|
||||
func (d *Dao) ShutdownMobileDevice(c context.Context, host, serial string) (err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.DeviceShutDownResponse
|
||||
)
|
||||
|
||||
reqModel := &model.DeviceBootRequest{
|
||||
Serial: serial,
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("http://%s", host+_deviceShutDownURL)
|
||||
|
||||
if req, err = d.newRequest(http.MethodPost, url, reqModel); err != nil {
|
||||
log.Error("d.ShutdownMobileDevice newRequest url(%s) err(%+v)", _deviceShutDownURL, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("content-type", "application/json")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.ShutdownMobileDevice url(%s) err(%+v)", _deviceShutDownURL, err)
|
||||
return
|
||||
}
|
||||
if res.Status.Code != _deviceCode {
|
||||
err = ecode.MerlinDeviceFarmErr
|
||||
log.Error("Status url(%s) res(%s) err(%+v)", _deviceShutDownURL, res, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
124
app/admin/ep/merlin/dao/docker.go
Normal file
124
app/admin/ep/merlin/dao/docker.go
Normal file
@ -0,0 +1,124 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go-common/library/ecode"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
)
|
||||
|
||||
// authConfig get Auth Config.
|
||||
func (d *Dao) authConfig() (authStr string, err error) {
|
||||
authConfig := types.AuthConfig{
|
||||
Username: d.c.BiliHub.Username,
|
||||
Password: d.c.BiliHub.Password,
|
||||
ServerAddress: d.c.BiliHub.HostName,
|
||||
}
|
||||
|
||||
var encodedJSON []byte
|
||||
if encodedJSON, err = json.Marshal(authConfig); err != nil {
|
||||
return
|
||||
}
|
||||
authStr = base64.URLEncoding.EncodeToString(encodedJSON)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// ImagePull Image Pull.
|
||||
func (d *Dao) ImagePull(imageName string) (err error) {
|
||||
var (
|
||||
out io.ReadCloser
|
||||
authStr string
|
||||
)
|
||||
|
||||
if authStr, err = d.authConfig(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if out, err = d.dockerClient.ImagePull(context.TODO(), imageName, types.ImagePullOptions{RegistryAuth: authStr}); err != nil {
|
||||
err = ecode.MerlinImagePullErr
|
||||
return
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
io.Copy(os.Stdout, out)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ImagePush Image Push.
|
||||
func (d *Dao) ImagePush(imageName string) (err error) {
|
||||
var (
|
||||
out io.ReadCloser
|
||||
authStr string
|
||||
)
|
||||
|
||||
if authStr, err = d.authConfig(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if out, err = d.dockerClient.ImagePush(context.TODO(), imageName, types.ImagePushOptions{RegistryAuth: authStr}); err != nil {
|
||||
err = ecode.MerlinImagePushErr
|
||||
return
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
io.Copy(os.Stdout, out)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ImageTag Image Tag.
|
||||
func (d *Dao) ImageTag(imageSrcName, imageTagName string) (err error) {
|
||||
err = d.dockerClient.ImageTag(context.TODO(), imageSrcName, imageTagName)
|
||||
return
|
||||
}
|
||||
|
||||
// ImageRemove Image Remove.
|
||||
func (d *Dao) ImageRemove(imageID string) (err error) {
|
||||
_, err = d.dockerClient.ImageRemove(context.TODO(), imageID, types.ImageRemoveOptions{Force: true, PruneChildren: true})
|
||||
return
|
||||
}
|
||||
|
||||
// ImageGetID Image Get ID.
|
||||
func (d *Dao) ImageGetID(imageName string) (imageID string, err error) {
|
||||
var images []types.ImageSummary
|
||||
|
||||
if images, err = d.dockerClient.ImageList(context.TODO(), types.ImageListOptions{}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, image := range images {
|
||||
for _, tag := range image.RepoTags {
|
||||
if tag == imageName {
|
||||
imageID = image.ID
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ImageGetAll Image Get All.
|
||||
func (d *Dao) ImageGetAll() (imageNames []string, err error) {
|
||||
var images []types.ImageSummary
|
||||
if images, err = d.dockerClient.ImageList(context.Background(), types.ImageListOptions{Filters: filters.NewArgs()}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, image := range images {
|
||||
for _, tag := range image.RepoTags {
|
||||
if strings.Contains(tag, d.c.BiliHub.HostName) {
|
||||
imageNames = append(imageNames, tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
35
app/admin/ep/merlin/dao/mail.go
Normal file
35
app/admin/ep/merlin/dao/mail.go
Normal file
@ -0,0 +1,35 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
_MailBoxNotFound = "Mailbox not found"
|
||||
)
|
||||
|
||||
// SendMail asynchronous send mail.
|
||||
func (d *Dao) SendMail(message *gomail.Message) {
|
||||
message.SetAddressHeader("From", d.email.Username, "merlin")
|
||||
d.cache.Do(context.Background(), func(c context.Context) {
|
||||
d.SendMailIfFailed(message)
|
||||
})
|
||||
}
|
||||
|
||||
// SendMailIfFailed Send Mail If Failed
|
||||
func (d *Dao) SendMailIfFailed(message *gomail.Message) {
|
||||
if err := d.email.DialAndSend(message); err != nil {
|
||||
if strings.Contains(err.Error(), _MailBoxNotFound) {
|
||||
headerMsg := message.GetHeader("Subject")
|
||||
headerMsg = append(headerMsg, "Mail Send Error:"+err.Error()+",Receiver:")
|
||||
headerMsg = append(headerMsg, message.GetHeader("To")...)
|
||||
|
||||
message.SetHeader("To", d.c.Mail.NoticeOwner...)
|
||||
message.SetHeader("Subject", headerMsg...)
|
||||
d.email.DialAndSend(message)
|
||||
}
|
||||
}
|
||||
}
|
20
app/admin/ep/merlin/dao/mail_test.go
Normal file
20
app/admin/ep/merlin/dao/mail_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
m = gomail.NewMessage()
|
||||
)
|
||||
|
||||
func Test_SendMail(t *testing.T) {
|
||||
Convey("test send mail", t, func() {
|
||||
m.SetHeader("To", "fengyifeng@bilibili.com")
|
||||
m.SetHeader("Subject", "unit test")
|
||||
d.SendMail(m)
|
||||
})
|
||||
}
|
150
app/admin/ep/merlin/dao/mysql_application_record.go
Normal file
150
app/admin/ep/merlin/dao/mysql_application_record.go
Normal file
@ -0,0 +1,150 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertApplicationRecord insert application record.
|
||||
func (d *Dao) InsertApplicationRecord(ar *model.ApplicationRecord) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(&ar).Error)
|
||||
}
|
||||
|
||||
// FindApplicationRecordsByApplicant find application record by applicant.
|
||||
func (d *Dao) FindApplicationRecordsByApplicant(applicant string, pn, ps int) (total int64, ars []*model.ApplicationRecord, err error) {
|
||||
cdb := d.db.Model(&model.ApplicationRecord{}).Where("applicant=?", applicant).Order("ID desc").Offset((pn - 1) * ps).Limit(ps)
|
||||
if err = pkgerr.WithStack(cdb.Find(&ars).Error); err != nil {
|
||||
return
|
||||
}
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("applicant=?", applicant).Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindApplicationRecordsByAuditor find application record by auditor.
|
||||
func (d *Dao) FindApplicationRecordsByAuditor(auditor string, pn, ps int) (total int64, ars []*model.ApplicationRecord, err error) {
|
||||
cdb := d.db.Model(&model.ApplicationRecord{}).Where("auditor=?", auditor).Order("ID desc").Offset((pn - 1) * ps).Limit(ps)
|
||||
if err = pkgerr.WithStack(cdb.Find(&ars).Error); err != nil {
|
||||
return
|
||||
}
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("auditor=?", auditor).Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindApplicationRecordsByMachineID find application records by machineId.
|
||||
func (d *Dao) FindApplicationRecordsByMachineID(machineID int64, pn, ps int) (total int64, ars []*model.ApplicationRecord, err error) {
|
||||
cdb := d.db.Model(&model.ApplicationRecord{}).Where("machine_id=?", machineID).Order("ID desc").Offset((pn - 1) * ps).Limit(ps)
|
||||
if err = pkgerr.WithStack(cdb.Find(&ars).Error); err != nil {
|
||||
return
|
||||
}
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("machine_id=?", machineID).Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindApplicationRecordsByID find application records by id.
|
||||
func (d *Dao) FindApplicationRecordsByID(auditID int64) (ar *model.ApplicationRecord, err error) {
|
||||
ar = &model.ApplicationRecord{}
|
||||
err = pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).First(ar).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAuditStatus update audit status.
|
||||
func (d *Dao) UpdateAuditStatus(auditID int64, status string) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).Update("STATUS", status).Error)
|
||||
}
|
||||
|
||||
// UpdateAuditStatusAndComment update audit status and comment.
|
||||
func (d *Dao) UpdateAuditStatusAndComment(auditID int64, status, comment string) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).Update("STATUS", status).Update("AUDITOR_COMMENT", comment).Error)
|
||||
}
|
||||
|
||||
// InsertApplicationRecordAndUpdateMachineDelayStatus insert application record and update machine delay status.
|
||||
func (d *Dao) InsertApplicationRecordAndUpdateMachineDelayStatus(ar *model.ApplicationRecord, machineID int64, delayStatus int) (err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Create(&ar).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
if err = tx.Model(&model.Machine{}).Where("ID=?", machineID).Update("DELAY_STATUS", delayStatus).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
err = tx.Commit().Error
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAuditStatusAndUpdateMachineDelayStatus update audit status and update machine delay status.
|
||||
func (d *Dao) UpdateAuditStatusAndUpdateMachineDelayStatus(machineID, auditID int64, delayStatus int, applyStatus string) (err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).Update("STATUS", applyStatus).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.Machine{}).Where("ID=?", machineID).Update("DELAY_STATUS", delayStatus).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
err = tx.Commit().Error
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAuditStatusAndUpdateMachineDelayStatusComment update audit status and update machine delay status comment.
|
||||
func (d *Dao) UpdateAuditStatusAndUpdateMachineDelayStatusComment(machineID, auditID int64, delayStatus int, applyStatus, comment string) (err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).Update("STATUS", applyStatus).Update("AUDITOR_COMMENT", comment).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.Machine{}).Where("ID=?", machineID).Update("DELAY_STATUS", delayStatus).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
err = tx.Commit().Error
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAuditStatusAndUpdateMachineEndTime update audit status and update machine end time.
|
||||
func (d *Dao) UpdateAuditStatusAndUpdateMachineEndTime(machineID, auditID int64, delayStatus int, applyStatus string, applyEndTime time.Time, comment string) (err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.ApplicationRecord{}).Where("ID=?", auditID).Update("STATUS", applyStatus).Update("AUDITOR_COMMENT", comment).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.Machine{}).Where("ID=?", machineID).Update("DELAY_STATUS", delayStatus).Update("END_TIME", applyEndTime).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
err = tx.Commit().Error
|
||||
return
|
||||
}
|
241
app/admin/ep/merlin/dao/mysql_dashboard.go
Normal file
241
app/admin/ep/merlin/dao/mysql_dashboard.go
Normal file
@ -0,0 +1,241 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
)
|
||||
|
||||
// MachineLifeCycle Statistics Machine Life Cycle.
|
||||
func (d *Dao) MachineLifeCycle() (machineLifeCycles []*model.MachineLifeCycle, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "select CASE " +
|
||||
"when TIMESTAMPDIFF(DAY,ctime,end_time)>0 and TIMESTAMPDIFF(DAY,ctime,end_time) <=100 THEN'0-100' " +
|
||||
"when TIMESTAMPDIFF(DAY,ctime,end_time)>100 and TIMESTAMPDIFF(DAY,ctime,end_time) <=200 THEN'100-200' " +
|
||||
"when TIMESTAMPDIFF(DAY,ctime,end_time)>200 THEN'200+' ELSE '0-100' " +
|
||||
"End as lifecycle,count(-1)from machines GROUP BY lifecycle"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mlc := &model.MachineLifeCycle{}
|
||||
if err = rows.Scan(&mlc.Duration, &mlc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
machineLifeCycles = append(machineLifeCycles, mlc)
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// MachineCountGroupByBusiness Machine Count Group By Business
|
||||
func (d *Dao) MachineCountGroupByBusiness() (machinesCount []*model.MachineCountGroupByBusiness, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "SELECT business_unit,count(-1) as count FROM machines GROUP BY business_unit ORDER BY count DESC"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MachineCountGroupByBusiness{}
|
||||
if err = rows.Scan(&mc.BusinessUnit, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
machinesCount = append(machinesCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MachineCountGroupByBusinessInRunning Machine Count Group By Business In Running
|
||||
func (d *Dao) MachineCountGroupByBusinessInRunning() (machinesCount []*model.MachineCountGroupByBusiness, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "SELECT business_unit,count(-1) as count FROM machines where status>=100 GROUP BY business_unit ORDER BY count DESC"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MachineCountGroupByBusiness{}
|
||||
if err = rows.Scan(&mc.BusinessUnit, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
machinesCount = append(machinesCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MachineWillBeExpired Statistics Machine Will Be Expired
|
||||
func (d *Dao) MachineWillBeExpired() (machines []*model.MachineCreatedAndEndTime, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "SELECT id,name,username,app,ctime,end_time from machines where `status`>=100 order by end_time limit 10"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MachineCreatedAndEndTime{}
|
||||
if err = rows.Scan(&mc.ID, &mc.MachineName, &mc.Username, &mc.App, &mc.CreateTime, &mc.EndTime); err != nil {
|
||||
return
|
||||
}
|
||||
machines = append(machines, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MachineLatestCreated Machine Latest Created
|
||||
func (d *Dao) MachineLatestCreated() (machines []*model.MachineCreatedAndEndTime, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "SELECT id,name,username,app,ctime,end_time from machines where `status`>=100 order by ctime desc limit 10"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MachineCreatedAndEndTime{}
|
||||
if err = rows.Scan(&mc.ID, &mc.MachineName, &mc.Username, &mc.App, &mc.CreateTime, &mc.EndTime); err != nil {
|
||||
return
|
||||
}
|
||||
machines = append(machines, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineUserUsageCount Mobile Machine User Usage Count
|
||||
func (d *Dao) MobileMachineUserUsageCount() (mobileMachinesUsageCount []*model.MobileMachineUserUsageCount, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := fmt.Sprintf("select username,count(username) as count from mobile_machine_logs "+
|
||||
"where operation_type='%s' and operation_result ='%s' "+
|
||||
"group by username order by count desc", model.MBBindLog, model.OperationSuccessForMachineLog)
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
mc := &model.MobileMachineUserUsageCount{}
|
||||
if err = rows.Scan(&mc.Username, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachinesUsageCount = append(mobileMachinesUsageCount, mc)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineUserLendCount Mobile Machine Lend Count
|
||||
func (d *Dao) MobileMachineUserLendCount() (mobileMachinesUsageCount []*model.MobileMachineUserUsageCount, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := fmt.Sprintf("select username,count(username) as count from mobile_machine_logs "+
|
||||
"where operation_type='%s' and operation_result ='%s' "+
|
||||
"group by username order by count desc", model.MBLendOutLog, model.OperationSuccessForMachineLog)
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MobileMachineUserUsageCount{}
|
||||
if err = rows.Scan(&mc.Username, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachinesUsageCount = append(mobileMachinesUsageCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineUsageCount Mobile Machine Usage Count
|
||||
func (d *Dao) MobileMachineUsageCount() (mobileMachinesUsageCount []*model.MobileMachineUsageCount, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := fmt.Sprintf("select b.id,b.name,count(b.name) as count from mobile_machine_logs as a "+
|
||||
"left join mobile_machines as b on a.machine_id = b.id "+
|
||||
"where a.operation_type='%s' and a.operation_result = '%s' "+
|
||||
"group by b.id,b.`name` order by count desc", model.MBBindLog, model.OperationSuccessForMachineLog)
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MobileMachineUsageCount{}
|
||||
if err = rows.Scan(&mc.MobileMachineID, &mc.MobileMachineName, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachinesUsageCount = append(mobileMachinesUsageCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineLendCount Mobile Machine Lend Count
|
||||
func (d *Dao) MobileMachineLendCount() (mobileMachinesUsageCount []*model.MobileMachineUsageCount, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := fmt.Sprintf("select b.id,b.name,count(b.name) as count from mobile_machine_logs as a "+
|
||||
"left join mobile_machines as b on a.machine_id = b.id "+
|
||||
"where a.operation_type='%s' and a.operation_result = '%s' "+
|
||||
"group by b.id,b.`name` order by count desc", model.MBLendOutLog, model.OperationSuccessForMachineLog)
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MobileMachineUsageCount{}
|
||||
if err = rows.Scan(&mc.MobileMachineID, &mc.MobileMachineName, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachinesUsageCount = append(mobileMachinesUsageCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineModeCount Mobile Machine Mode Count.
|
||||
func (d *Dao) MobileMachineModeCount() (mobileMachinesTypeCount []*model.MobileMachineTypeCount, err error) {
|
||||
var rows *sql.Rows
|
||||
|
||||
SQL := "select mode,count(mode) as count from mobile_machines where action > 0 group by mode order by count desc"
|
||||
|
||||
if rows, err = d.db.Raw(SQL).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
mc := &model.MobileMachineTypeCount{}
|
||||
if err = rows.Scan(&mc.ModeName, &mc.Count); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachinesTypeCount = append(mobileMachinesTypeCount, mc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MobileMachineUseRecord Mobile Machine Use Record
|
||||
func (d *Dao) MobileMachineUseRecord() (mobileMachineLogs []*model.MobileMachineLog, err error) {
|
||||
err = d.db.Where("operation_type= ? or operation_type = ?", model.MBBindLog, model.MBReleaseLog).Order("machine_id,id").Find(&mobileMachineLogs).Error
|
||||
return
|
||||
}
|
28
app/admin/ep/merlin/dao/mysql_hubimage_confs.go
Normal file
28
app/admin/ep/merlin/dao/mysql_hubimage_confs.go
Normal file
@ -0,0 +1,28 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertHubImageConf Insert Hub Image conf.
|
||||
func (d *Dao) InsertHubImageConf(hubImageConf *model.HubImageConf) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(hubImageConf).Error)
|
||||
}
|
||||
|
||||
// UpdateHubImageConf Update Hub Image Conf.
|
||||
func (d *Dao) UpdateHubImageConf(hubImageConf *model.HubImageConf) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.HubImageConf{}).Where("image_name=?", hubImageConf.ImageName).Updates(map[string]interface{}{
|
||||
"update_by": hubImageConf.UpdateBy, "command": hubImageConf.Command, "environments": hubImageConf.Envs, "hosts": hubImageConf.Hosts}).Error)
|
||||
}
|
||||
|
||||
// FindHubImageConfByImageName Find Hub Image Conf By Image Name.
|
||||
func (d *Dao) FindHubImageConfByImageName(imageName string) (hubImageConf *model.HubImageConf, err error) {
|
||||
hubImageConf = &model.HubImageConf{}
|
||||
if err = d.db.Where("image_name = ?", imageName).First(hubImageConf).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
59
app/admin/ep/merlin/dao/mysql_hubimage_logs.go
Normal file
59
app/admin/ep/merlin/dao/mysql_hubimage_logs.go
Normal file
@ -0,0 +1,59 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertHubImageLog Insert Hub Image Log.
|
||||
func (d *Dao) InsertHubImageLog(hubImageLog *model.HubImageLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(hubImageLog).Error)
|
||||
}
|
||||
|
||||
// UpdateHubImageLog Update Hub Image Log.
|
||||
func (d *Dao) UpdateHubImageLog(hubImageLog *model.HubImageLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.HubImageLog{}).Where("id=?", hubImageLog.ID).Updates(hubImageLog).Error)
|
||||
}
|
||||
|
||||
// UpdateHubImageLogStatus Update Hub Image Log Status.
|
||||
func (d *Dao) UpdateHubImageLogStatus(logID int64, status int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.HubImageLog{}).Where("id=?", logID).Updates(map[string]interface{}{"status": status}).Error)
|
||||
}
|
||||
|
||||
// FindHubImageLogByImageTag Find Hub Image Log By Image Tag.
|
||||
func (d *Dao) FindHubImageLogByImageTag(imageTag string) (hubImageLog *model.HubImageLog, err error) {
|
||||
hubImageLog = &model.HubImageLog{}
|
||||
if err = d.db.Where("imagetag = ?", imageTag).First(hubImageLog).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindHubImageLogByMachineID Find Hub Image Log By MachineID .
|
||||
func (d *Dao) FindHubImageLogByMachineID(machineID int64) (hubImageLogs []*model.HubImageLog, err error) {
|
||||
if err = d.db.Where("machine_id = ? ", machineID).Order("id DESC").Find(&hubImageLogs).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindHubMachine2ImageLog Find Hub Machine to Image Log .
|
||||
func (d *Dao) FindHubMachine2ImageLog(queryRequest *model.QueryMachine2ImageLogRequest) (total int64, hubImageLogs []*model.HubImageLog, err error) {
|
||||
cdb := d.db.Model(&model.HubImageLog{}).Where("machine_id=? and operate_type = ?", queryRequest.MachineID, strconv.Itoa(model.ImageMachine2Image)).Order("ID desc").Offset((queryRequest.PageNum - 1) * queryRequest.PageSize).Limit(queryRequest.PageSize)
|
||||
if err = pkgerr.WithStack(cdb.Find(&hubImageLogs).Error); err != nil {
|
||||
return
|
||||
}
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.HubImageLog{}).Where("machine_id=? and operate_type = ?", queryRequest.MachineID, strconv.Itoa(model.ImageMachine2Image)).Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateHubImageLogStatusInDoingStatus Update Hub Image Log Status in doing status.
|
||||
func (d *Dao) UpdateHubImageLogStatusInDoingStatus(machineID int64, status int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.HubImageLog{}).Where("machine_id=? and status=? and operate_type = ?", machineID, model.ImageInit, model.ImageMachine2Image).Updates(map[string]interface{}{"status": status}).Error)
|
||||
}
|
28
app/admin/ep/merlin/dao/mysql_image.go
Normal file
28
app/admin/ep/merlin/dao/mysql_image.go
Normal file
@ -0,0 +1,28 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Images Search all images in db.
|
||||
func (d *Dao) Images() (images []*model.Image, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status = ?", model.AliveImageStatus).Find(&images).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// AddImage Create new image in db.
|
||||
func (d *Dao) AddImage(image *model.Image) error {
|
||||
return pkgerr.WithStack(d.db.Create(image).Error)
|
||||
}
|
||||
|
||||
// UpdateImage Update image in db.
|
||||
func (d *Dao) UpdateImage(image *model.Image) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Image{}).Updates(image).Error)
|
||||
}
|
||||
|
||||
// DelImage Delete image in db.
|
||||
func (d *Dao) DelImage(iID int64) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Image{}).Where("id = ?", iID).Update("status", model.DeletedImageStatus).Error)
|
||||
}
|
51
app/admin/ep/merlin/dao/mysql_image_test.go
Normal file
51
app/admin/ep/merlin/dao/mysql_image_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
imageAdd = model.Image{
|
||||
Name: "docker-reg.bilibili.co/zccdebian:1.0",
|
||||
Status: 1,
|
||||
OS: "debian",
|
||||
Version: "1.0 64位",
|
||||
Description: "base",
|
||||
CreatedBy: "ut",
|
||||
}
|
||||
imageUpdate = model.Image{
|
||||
Name: "docker-reg.bilibili.co/zccdebian:1.0update",
|
||||
Status: 2,
|
||||
OS: "debian update",
|
||||
Version: "1.0 64位 update",
|
||||
Description: "base update",
|
||||
CreatedBy: "ut update",
|
||||
UpdatedBy: "ut",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Image(t *testing.T) {
|
||||
Convey("add image", t, func() {
|
||||
err := d.AddImage(&imageAdd)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
Convey("get image", t, func() {
|
||||
images, err := d.Images()
|
||||
So(err, ShouldBeNil)
|
||||
So(len(images), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
Convey("update image", t, func() {
|
||||
imageUpdate.ID = imageAdd.ID
|
||||
err := d.UpdateImage(&imageUpdate)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
Convey("delete image", t, func() {
|
||||
imageDel := model.Image{ID: imageAdd.ID}
|
||||
err := d.DelImage(imageDel.ID)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
201
app/admin/ep/merlin/dao/mysql_machine.go
Normal file
201
app/admin/ep/merlin/dao/mysql_machine.go
Normal file
@ -0,0 +1,201 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
_wildcards = "%"
|
||||
_where = "WHERE"
|
||||
_and = "AND"
|
||||
|
||||
_pathAndPodNamesMappingSQL = "SELECT CONCAT(business_unit, '.', project, '.', app) AS \"path\" , GROUP_CONCAT(pod_name) AS \"pod_names\" FROM machines WHERE status >=0 AND status < 100 AND ctime < %s GROUP BY business_unit, project, app;"
|
||||
_nodeSQL = "SELECT DISTINCT(machine_id) FROM machine_nodes"
|
||||
)
|
||||
|
||||
// FindExpiredMachineByDay find expired machines.
|
||||
func (d *Dao) FindExpiredMachineByDay(day int) (ms []*model.Machine, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status >= 0 AND DATEDIFF(end_time,NOW())>=0 AND DATEDIFF(end_time,NOW())<= ?", day).Find(&ms).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindExpiredMachine find a day-old machines.
|
||||
func (d *Dao) FindExpiredMachine() (ms []*model.Machine, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status >= 0 AND DATEDIFF(NOW(),end_time) = ?", -1).Find(&ms).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryMachine query machine.
|
||||
func (d *Dao) QueryMachine(id int64) (machine *model.Machine, err error) {
|
||||
machine = &model.Machine{}
|
||||
err = pkgerr.WithStack(d.db.Where("id = ?", id).First(machine).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryMachineByName Query Machine By Name.
|
||||
func (d *Dao) QueryMachineByName(machineName string) (machine *model.Machine, err error) {
|
||||
machine = &model.Machine{}
|
||||
err = pkgerr.WithStack(d.db.Where("name = ?", machineName).First(machine).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryOnlineMachineByName Query Online Machine By Name.
|
||||
func (d *Dao) QueryOnlineMachineByName(machineName string) (machine *model.Machine, err error) {
|
||||
machine = &model.Machine{}
|
||||
err = pkgerr.WithStack(d.db.Where("status >=100 and name = ?", machineName).First(machine).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// DelMachine delete machine.
|
||||
func (d *Dao) DelMachine(id int64, username string) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id = ?", id).Update("status", model.RemovedMachineInMerlin).Update("update_by", username).Error)
|
||||
}
|
||||
|
||||
// HasMachine verify machine name.
|
||||
func (d *Dao) HasMachine(name string) (b bool, err error) {
|
||||
var size int64
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("name LIKE ?", name+"-"+_wildcards).Where("status <> ?", model.RemovedMachineInMerlin).Count(&size).Error); err != nil {
|
||||
return
|
||||
}
|
||||
b = size > 0
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMachineStatus update machine status by giving value.
|
||||
func (d *Dao) UpdateMachineStatus(id int64, status int) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id = ?", id).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// QueryMachines query machines and update machine in names status to boot.
|
||||
func (d *Dao) QueryMachines(names []string, qmr *model.QueryMachineRequest) (total int64, machines []*model.Machine, err error) {
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("status >= 0 AND status < 100 AND pod_name IN (?)", names).Update("status", model.BootMachineInMerlin).Error); err != nil {
|
||||
return
|
||||
}
|
||||
gDB := d.db.Model(&model.Machine{}).Where("status >= 100 AND status < 300 AND pod_name IN (?) OR (status > -300 AND status <= -200 OR status >= 0 AND status < 100) AND username = ?", names, qmr.Requester)
|
||||
if qmr.Username != "" {
|
||||
gDB = gDB.Where("username LIKE ?", qmr.Username+_wildcards)
|
||||
}
|
||||
if qmr.MachineName != "" {
|
||||
gDB = gDB.Where("BINARY name LIKE ?", _wildcards+qmr.MachineName+_wildcards)
|
||||
}
|
||||
if qmr.BusinessUnit != "" || qmr.Project != "" || qmr.App != "" {
|
||||
var (
|
||||
nSQL = _nodeSQL
|
||||
logicalWord = _where
|
||||
)
|
||||
if qmr.BusinessUnit != "" {
|
||||
nSQL = fmt.Sprintf("%s %s BINARY business_unit = '%s'", nSQL, logicalWord, qmr.BusinessUnit)
|
||||
logicalWord = _and
|
||||
}
|
||||
if qmr.Project != "" {
|
||||
nSQL = fmt.Sprintf("%s %s BINARY project = '%s'", nSQL, logicalWord, qmr.Project)
|
||||
logicalWord = _and
|
||||
}
|
||||
if qmr.App != "" {
|
||||
nSQL = fmt.Sprintf("%s %s BINARY app = '%s'", nSQL, logicalWord, qmr.App)
|
||||
}
|
||||
gDB = gDB.Where("ID IN ( " + nSQL + " )")
|
||||
}
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
err = pkgerr.WithStack(gDB.Order("ctime DESC").Offset((qmr.PageNum - 1) * qmr.PageSize).Limit(qmr.PageSize).Find(&machines).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMachineEndTime update machine end time.
|
||||
func (d *Dao) UpdateMachineEndTime(id int64, delayStatus int, endTime time.Time) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id = ?", id).Update("delay_status", delayStatus).Update("end_time", endTime).Error)
|
||||
}
|
||||
|
||||
// UpdateMachineDelayStatus update machine delay status.
|
||||
func (d *Dao) UpdateMachineDelayStatus(id int64, delayStatus int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id = ?", id).Update("delay_status", delayStatus).Error)
|
||||
}
|
||||
|
||||
// QueryPathAndPodNamesMapping query path and pod names map.
|
||||
func (d *Dao) QueryPathAndPodNamesMapping() (pathAndPodNames map[string][]string, err error) {
|
||||
var (
|
||||
rows *sql.Rows
|
||||
path string
|
||||
podNames string
|
||||
)
|
||||
if rows, err = d.db.Raw(fmt.Sprintf(_pathAndPodNamesMappingSQL, d.c.Paas.MachineTimeout)).Rows(); err != nil {
|
||||
err = pkgerr.WithStack(err)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
pathAndPodNames = make(map[string][]string)
|
||||
for rows.Next() {
|
||||
if err = rows.Scan(&path, &podNames); err != nil {
|
||||
return
|
||||
}
|
||||
pathAndPodNames[path] = strings.Split(podNames, ",")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMachineStatusByPodNames update machine status by pod names.
|
||||
func (d *Dao) UpdateMachineStatusByPodNames(podNames []string, target int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("pod_name IN (?)", podNames).Update("status", target).Error)
|
||||
}
|
||||
|
||||
// UpdateMachineUser Update Machine User By Id.
|
||||
func (d *Dao) UpdateMachineUser(machineID int64, username string) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id = ?", machineID).Update("username", username).Error)
|
||||
}
|
||||
|
||||
// QueryMachinesByPodNames query machines by giving pod name slices.
|
||||
func (d *Dao) QueryMachinesByPodNames(podNames []string) (machines []*model.Machine, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("pod_name IN (?)", podNames).Find(&machines).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// InsertMachines insert machines.
|
||||
func (d *Dao) InsertMachines(u string, gmr *model.GenMachinesRequest, ins []*model.CreateInstance) (err error) {
|
||||
var m *model.Machine
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
for _, in := range ins {
|
||||
m = in.ToMachine(u, gmr)
|
||||
if err = tx.Create(m).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
for _, n := range gmr.ToMachineNode(m.ID) {
|
||||
if err = tx.Create(n).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = tx.Create(m.ToMachineLog()).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryMachineInRunning Query Machine In Running
|
||||
func (d *Dao) QueryMachineInRunning() (ms []*model.Machine, err error) {
|
||||
err = d.db.Where("status >= 100").Find(&ms).Error
|
||||
return
|
||||
}
|
||||
|
||||
// QueryMachineCount Query Machine Count
|
||||
func (d *Dao) QueryMachineCount() (total int, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.Machine{}).Count(&total).Error)
|
||||
return
|
||||
}
|
47
app/admin/ep/merlin/dao/mysql_machineV2.go
Normal file
47
app/admin/ep/merlin/dao/mysql_machineV2.go
Normal file
@ -0,0 +1,47 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertMachinesV2 insert machines for v2.
|
||||
func (d *Dao) InsertMachinesV2(u string, gmr *model.GenMachinesRequest, pgmr *model.PaasGenMachineRequest) (ms []*model.Machine, err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
for _, pm := range pgmr.Machines {
|
||||
m := pm.ToMachine(u, gmr)
|
||||
if err = tx.Create(m).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
for _, n := range gmr.ToMachineNode(m.ID) {
|
||||
if err = tx.Create(n).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = tx.Create(m.ToMachineLog()).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
ms = append(ms, m)
|
||||
}
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatusForMachines update status for machines.
|
||||
func (d *Dao) UpdateStatusForMachines(status int, ids []int64) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("id IN (?)", ids).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// UpdateMachineStatusByName update status by name.
|
||||
func (d *Dao) UpdateMachineStatusByName(status int, n string) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Machine{}).Where("name = ?", n).Update("status", status).Error)
|
||||
}
|
111
app/admin/ep/merlin/dao/mysql_machine_log.go
Normal file
111
app/admin/ep/merlin/dao/mysql_machine_log.go
Normal file
@ -0,0 +1,111 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
_machineRightJoinLogSQL = "SELECT m.id,m.name,ml.username,ml.operation_type,ml.operation_result,ml.ctime FROM machines AS m INNER JOIN machine_logs AS ml ON m.id = ml.machine_id"
|
||||
_machineRightCountSQL = "SELECT count(m.id) FROM machines AS m INNER JOIN machine_logs AS ml ON m.id = ml.machine_id"
|
||||
)
|
||||
|
||||
// InsertMachineLog insert machine log.
|
||||
func (d *Dao) InsertMachineLog(machineLog *model.MachineLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(machineLog).Error)
|
||||
}
|
||||
|
||||
// FindMachineLogsByMachineID find machine log by machineId.
|
||||
func (d *Dao) FindMachineLogsByMachineID(machineID int64, pn, ps int) (total int64, machineLogs []*model.AboundMachineLog, err error) {
|
||||
var (
|
||||
qSQL = _machineRightJoinLogSQL
|
||||
cSQL = _machineRightCountSQL
|
||||
rows *sql.Rows
|
||||
)
|
||||
if machineID > 0 {
|
||||
qSQL = _machineRightJoinLogSQL + " WHERE machine_id = " + strconv.FormatInt(machineID, 10)
|
||||
cSQL = _machineRightCountSQL + " WHERE machine_id = " + strconv.FormatInt(machineID, 10)
|
||||
}
|
||||
|
||||
cDB := d.db.Raw(cSQL)
|
||||
if err = pkgerr.WithStack(cDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
gDB := d.db.Raw(qSQL)
|
||||
if rows, err = gDB.Order("ml.ctime DESC").Offset((pn - 1) * ps).Limit(ps).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
ml := &model.AboundMachineLog{}
|
||||
if err = rows.Scan(&ml.MachineID, &ml.Name, &ml.Username, &ml.OperateType, &ml.OperateResult, &ml.OperateTime); err != nil {
|
||||
return
|
||||
}
|
||||
machineLogs = append(machineLogs, ml)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindMachineLogs Find Machine Logs.
|
||||
func (d *Dao) FindMachineLogs(queryRequest *model.QueryMachineLogRequest) (total int64, machineLogs []*model.AboundMachineLog, err error) {
|
||||
var (
|
||||
qSQL = _machineRightJoinLogSQL
|
||||
cSQL = _machineRightCountSQL
|
||||
rows *sql.Rows
|
||||
)
|
||||
|
||||
if queryRequest.MachineID > 0 || queryRequest.OperateType != "" || queryRequest.OperateUser != "" || queryRequest.MachineName != "" {
|
||||
var (
|
||||
strSQL = ""
|
||||
logicalWord = _where
|
||||
)
|
||||
|
||||
if queryRequest.MachineID > 0 {
|
||||
strSQL = fmt.Sprintf("%s %s ml.machine_id = %s", strSQL, logicalWord, strconv.FormatInt(queryRequest.MachineID, 10))
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.OperateType != "" {
|
||||
strSQL = fmt.Sprintf("%s %s ml.operation_type like '%s'", strSQL, logicalWord, _wildcards+queryRequest.OperateType+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.MachineName != "" {
|
||||
strSQL = fmt.Sprintf("%s %s m.name like '%s'", strSQL, logicalWord, _wildcards+queryRequest.MachineName+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.OperateUser != "" {
|
||||
strSQL = fmt.Sprintf("%s %s ml.username like '%s'", strSQL, logicalWord, _wildcards+queryRequest.OperateUser+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
qSQL = _machineRightJoinLogSQL + " " + strSQL
|
||||
cSQL = _machineRightCountSQL + " " + strSQL
|
||||
|
||||
}
|
||||
|
||||
cDB := d.db.Raw(cSQL)
|
||||
if err = pkgerr.WithStack(cDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
gDB := d.db.Raw(qSQL)
|
||||
if rows, err = gDB.Order("ml.ctime DESC").Offset((queryRequest.PageNum - 1) * queryRequest.PageSize).Limit(queryRequest.PageSize).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
ml := &model.AboundMachineLog{}
|
||||
if err = rows.Scan(&ml.MachineID, &ml.Name, &ml.Username, &ml.OperateType, &ml.OperateResult, &ml.OperateTime); err != nil {
|
||||
return
|
||||
}
|
||||
machineLogs = append(machineLogs, ml)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
36
app/admin/ep/merlin/dao/mysql_machine_log_test.go
Normal file
36
app/admin/ep/merlin/dao/mysql_machine_log_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
machineLog = model.MachineLog{
|
||||
Username: "fengyifeng",
|
||||
MachineID: 1,
|
||||
OperateType: "DelTest",
|
||||
OperateResult: "",
|
||||
OperateTime: time.Now(),
|
||||
}
|
||||
)
|
||||
|
||||
func TestInsertMachineLog(t *testing.T) {
|
||||
Convey("Everything goes well when names is slice with value", t, func() {
|
||||
err := d.InsertMachineLog(&machineLog)
|
||||
So(err, ShouldBeNil)
|
||||
d.db.Where("OperateType=DelTest").Delete(machineLog)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindMachineLogsByMachineID(t *testing.T) {
|
||||
Convey("Everything goes well when names is slice with value", t, func() {
|
||||
_, _, err := d.FindMachineLogsByMachineID(0, 1, 5)
|
||||
So(err, ShouldBeNil)
|
||||
d.db.Where("OperateType=DelTest").Delete(machineLog)
|
||||
})
|
||||
}
|
36
app/admin/ep/merlin/dao/mysql_machine_node.go
Normal file
36
app/admin/ep/merlin/dao/mysql_machine_node.go
Normal file
@ -0,0 +1,36 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DelMachineNodeByMachineID delete node by machine id.
|
||||
func (d *Dao) DelMachineNodeByMachineID(mID int64) error {
|
||||
return pkgerr.WithStack(d.db.Where("machine_id = ?", mID).Delete(&model.MachineNode{}).Error)
|
||||
}
|
||||
|
||||
// GenMachineNodes generate some machine nodes.
|
||||
func (d *Dao) GenMachineNodes(nodes []*model.MachineNode) (err error) {
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
for _, n := range nodes {
|
||||
if err = tx.Create(n).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryMachineNodes query machine nodes by machine id.
|
||||
func (d *Dao) QueryMachineNodes(mID int64) (nodes []*model.MachineNode, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.MachineNode{}).Where("machine_id = ?", mID).Find(&nodes).Error)
|
||||
return
|
||||
}
|
13
app/admin/ep/merlin/dao/mysql_machine_package.go
Normal file
13
app/admin/ep/merlin/dao/mysql_machine_package.go
Normal file
@ -0,0 +1,13 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FindAllMachinePackages find all machine packages.
|
||||
func (d *Dao) FindAllMachinePackages() (machinePackages []*model.MachinePackage, err error) {
|
||||
err = pkgerr.WithStack(d.db.Find(&machinePackages).Error)
|
||||
return
|
||||
}
|
565
app/admin/ep/merlin/dao/mysql_machine_test.go
Normal file
565
app/admin/ep/merlin/dao/mysql_machine_test.go
Normal file
@ -0,0 +1,565 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/log"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var tMachine *model.Machine
|
||||
|
||||
func machineFunc(f func()) func() {
|
||||
return func() {
|
||||
beforeAllMT()
|
||||
defer afterAllMT()
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
func beforeAllMT() {
|
||||
var err error
|
||||
tMachine = &model.Machine{
|
||||
Name: "test-machine-1",
|
||||
PodName: "test-machine-0-0",
|
||||
Status: 100,
|
||||
Username: "seanan",
|
||||
BusinessUnit: "test",
|
||||
Project: "ep",
|
||||
App: "merlin",
|
||||
ClusterID: 3,
|
||||
NetworkID: 5,
|
||||
Comment: "Unit test for the dao of merlin.",
|
||||
DelayStatus: 0,
|
||||
}
|
||||
if err = d.db.Create(tMachine).Error; err != nil {
|
||||
log.Error("Failed to init machine(%v) for test, err(%v)", tMachine, err)
|
||||
return
|
||||
}
|
||||
if err = d.db.Create(&model.MachineNode{MachineID: tMachine.ID, BusinessUnit: tMachine.BusinessUnit, Project: tMachine.Project, App: tMachine.App, TreeID: 1234}).Error; err != nil {
|
||||
log.Error("Failed to init machine node for test, err(%v)", tMachine, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func afterAllMT() {
|
||||
var err error
|
||||
if err = d.db.Where("name = ?", tMachine.Name).Delete(&model.Machine{}).Error; err != nil {
|
||||
log.Error("Failed to delete machine(%v) for test, err(%v)", tMachine, err)
|
||||
return
|
||||
}
|
||||
if err = d.db.Where("machine_id = ?", tMachine.ID).Delete(&model.MachineNode{}).Error; err != nil {
|
||||
log.Error("Failed to delete machine node for test, err(%v)", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindExpiredMachineByDay(t *testing.T) {
|
||||
Convey("The actualMachines must contain tMachine when deadline day is 0", t, machineFunc(func() {
|
||||
var err error
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("end_time", time.Now()).Error; err != nil {
|
||||
log.Error("Cannot update the end_time of tMachine")
|
||||
return
|
||||
}
|
||||
actualMachines, err := d.FindExpiredMachineByDay(0)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("The actualMachines must not contain tMachine when deadline day is not 0", t, machineFunc(func() {
|
||||
var err error
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("end_time", time.Now()).Error; err != nil {
|
||||
log.Error("Cannot update the end_time of tMachine")
|
||||
return
|
||||
}
|
||||
actualMachines, err := d.FindExpiredMachineByDay(1)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
So(true, ShouldBeFalse)
|
||||
return
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func TestFindExpiredMachine(t *testing.T) {
|
||||
Convey("The actualMachines must contain tMachine", t, machineFunc(func() {
|
||||
var err error
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("end_time", time.Now().AddDate(0, 0, 1)).Error; err != nil {
|
||||
log.Error("Cannot update the end_time of tMachine")
|
||||
return
|
||||
}
|
||||
actualMachines, err := d.FindExpiredMachine()
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("The actualMachines must not contain tMachine", t, machineFunc(func() {
|
||||
actualMachines, err := d.FindExpiredMachine()
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
So(true, ShouldBeFalse)
|
||||
return
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func TestQueryMachine(t *testing.T) {
|
||||
Convey("The actualMachines must be tMachine when id is the id of tMachine", t, machineFunc(func() {
|
||||
actualMachines, err := d.QueryMachine(tMachine.ID)
|
||||
So(err, ShouldBeNil)
|
||||
So(actualMachines.ID, ShouldEqual, tMachine.ID)
|
||||
}))
|
||||
|
||||
Convey("The actualMachines must not be tMachine when id is not the id of tMachine", t, machineFunc(func() {
|
||||
_, err := d.QueryMachine(0)
|
||||
So(err, ShouldNotBeNil)
|
||||
}))
|
||||
}
|
||||
|
||||
// TestDelMachine this test only need positive test because negative case is filtered by service
|
||||
func TestDelMachine(t *testing.T) {
|
||||
Convey("The tMachine must be delete", t, machineFunc(func() {
|
||||
var (
|
||||
actual = &model.Machine{}
|
||||
updateBy = "seanan"
|
||||
)
|
||||
err := d.DelMachine(tMachine.ID, updateBy)
|
||||
So(err, ShouldBeNil)
|
||||
d.db.Where("id = ?", tMachine.ID).Find(actual)
|
||||
So(actual.Status, ShouldEqual, model.RemovedMachineInMerlin)
|
||||
So(actual.UpdateBy, ShouldEqual, updateBy)
|
||||
}))
|
||||
}
|
||||
|
||||
// TestHasMachine HasMachine is fuzzy matching name which is end with -number
|
||||
func TestHasMachine(t *testing.T) {
|
||||
Convey("return true when machine existed", t, machineFunc(func() {
|
||||
b, err := d.HasMachine("test-machine")
|
||||
So(err, ShouldBeNil)
|
||||
So(b, ShouldBeTrue)
|
||||
}))
|
||||
|
||||
Convey("return false when machine does not exist", t, machineFunc(func() {
|
||||
b, err := d.HasMachine("no-test-machine")
|
||||
So(err, ShouldBeNil)
|
||||
So(b, ShouldBeFalse)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestUpdateMachineStatus(t *testing.T) {
|
||||
Convey("The machine status must be boot", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
actualMachine = &model.Machine{}
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Error; err != nil {
|
||||
return
|
||||
}
|
||||
err = d.UpdateMachineStatus(tMachine.ID, model.BootMachineInMerlin)
|
||||
So(err, ShouldBeNil)
|
||||
if err = d.db.Where("id = ?", tMachine.ID).First(actualMachine).Error; err != nil {
|
||||
log.Error("find machine err(%v)", err)
|
||||
return
|
||||
}
|
||||
So(actualMachine.Status, ShouldEqual, model.BootMachineInMerlin)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestQueryMachines(t *testing.T) {
|
||||
Convey("Find the boot machines by names", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Find the creating machines by requester", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
Requester: "seanan",
|
||||
}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Error; err != nil {
|
||||
return
|
||||
}
|
||||
_, actualMachines, err = d.QueryMachines(nil, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Cannot find the creating machines by other requester", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
Requester: "other",
|
||||
}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Error; err != nil {
|
||||
return
|
||||
}
|
||||
_, actualMachines, err = d.QueryMachines(nil, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
So(true, ShouldBeFalse)
|
||||
return
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
Convey("Find the machines filter by username", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
Username: "sean",
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Find the machines filter by machine name", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
MachineName: "test-machine",
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Find the machines filter by BusinessUnit", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
TreeNode: model.TreeNode{
|
||||
BusinessUnit: "test",
|
||||
},
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Find the machines filter by BusinessUnit and Project", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
TreeNode: model.TreeNode{
|
||||
BusinessUnit: "test",
|
||||
Project: "ep",
|
||||
},
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("Find the machines filter by BusinessUnit, Project and App", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
qmr = &model.QueryMachineRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 5,
|
||||
PageNum: 1,
|
||||
},
|
||||
TreeNode: model.TreeNode{
|
||||
BusinessUnit: "test",
|
||||
Project: "ep",
|
||||
App: "merlin",
|
||||
},
|
||||
}
|
||||
names = []string{"test-machine-0-0"}
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
_, actualMachines, err = d.QueryMachines(names, qmr)
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.Name == tMachine.Name {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestUpdateMachineEndTime(t *testing.T) {
|
||||
Convey("The EndTime and DelayStatus should be updated", t, machineFunc(func() {
|
||||
var (
|
||||
actualMachine = &model.Machine{}
|
||||
expectTime = time.Now().AddDate(0, 1, 0)
|
||||
expectDelayStatus = 1
|
||||
err error
|
||||
)
|
||||
err = d.UpdateMachineEndTime(tMachine.ID, expectDelayStatus, expectTime)
|
||||
So(err, ShouldBeNil)
|
||||
if err = d.db.Where("id = ?", tMachine.ID).First(actualMachine).Error; err != nil {
|
||||
log.Error("find machine err(%v)", err)
|
||||
return
|
||||
}
|
||||
So(actualMachine.EndTime.Format("2006-01-02 15:04:05"), ShouldEqual, expectTime.Format("2006-01-02 15:04:05"))
|
||||
So(actualMachine.DelayStatus, ShouldEqual, expectDelayStatus)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestUpdateMachineDelayStatus(t *testing.T) {
|
||||
Convey("The DelayStatus should be updated", t, machineFunc(func() {
|
||||
var (
|
||||
actualMachine = &model.Machine{}
|
||||
expectDelayStatus = 1
|
||||
err error
|
||||
)
|
||||
err = d.UpdateMachineDelayStatus(tMachine.ID, expectDelayStatus)
|
||||
So(err, ShouldBeNil)
|
||||
if err = d.db.Where("id = ?", tMachine.ID).First(actualMachine).Error; err != nil {
|
||||
log.Error("find machine err(%v)", err)
|
||||
return
|
||||
}
|
||||
So(actualMachine.DelayStatus, ShouldEqual, expectDelayStatus)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestQueryPathAndPodNamesMapping(t *testing.T) {
|
||||
Convey("Find path and podNames mapping when the machine exceeds 20 minutes", t, machineFunc(func() {
|
||||
var (
|
||||
pathAndPodNames map[string][]string
|
||||
err error
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Update("ctime", time.Now().AddDate(0, 0, -1)).Error; err != nil {
|
||||
return
|
||||
}
|
||||
pathAndPodNames, err = d.QueryPathAndPodNamesMapping()
|
||||
So(err, ShouldBeNil)
|
||||
expectPath := tMachine.ToTreeNode().TreePath()
|
||||
for _, pn := range pathAndPodNames[expectPath] {
|
||||
if pn == tMachine.PodName {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
|
||||
Convey("cannot find path and podNames mapping when the machine does not exceed 20 minutes", t, machineFunc(func() {
|
||||
var (
|
||||
pathAndPodNames map[string][]string
|
||||
err error
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Error; err != nil {
|
||||
return
|
||||
}
|
||||
pathAndPodNames, err = d.QueryPathAndPodNamesMapping()
|
||||
So(err, ShouldBeNil)
|
||||
expectPath := tMachine.ToTreeNode().TreePath()
|
||||
for _, pn := range pathAndPodNames[expectPath] {
|
||||
if pn == tMachine.PodName {
|
||||
So(true, ShouldBeFalse)
|
||||
return
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func TestUpdateMachineStatusByPodNames(t *testing.T) {
|
||||
Convey("cannot find path and podNames mapping when the machine does not exceed 20 minutes", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
actualMachine *model.Machine
|
||||
expectStatus = model.BootMachineInMerlin
|
||||
)
|
||||
if err = d.db.Model(&model.Machine{}).Where("id = ?", tMachine.ID).Update("status", model.CreatingMachineInMerlin).Error; err != nil {
|
||||
return
|
||||
}
|
||||
err = d.UpdateMachineStatusByPodNames([]string{tMachine.PodName}, expectStatus)
|
||||
So(err, ShouldBeNil)
|
||||
if err = d.db.Where("id = ?", tMachine.ID).First(actualMachine).Error; err != nil {
|
||||
log.Error("find machine err(%v)", err)
|
||||
return
|
||||
}
|
||||
So(actualMachine.Status, ShouldEqual, expectStatus)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestQueryMachinesByPodNames(t *testing.T) {
|
||||
Convey("cannot find path and podNames mapping when the machine does not exceed 20 minutes", t, machineFunc(func() {
|
||||
var (
|
||||
err error
|
||||
actualMachines []*model.Machine
|
||||
)
|
||||
actualMachines, err = d.QueryMachinesByPodNames([]string{tMachine.PodName})
|
||||
So(err, ShouldBeNil)
|
||||
for _, m := range actualMachines {
|
||||
if m.ID == tMachine.ID {
|
||||
return
|
||||
}
|
||||
}
|
||||
So(true, ShouldBeFalse)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestInsertMachines(t *testing.T) {
|
||||
Convey("Insert 2 machines", t, machineFunc(func() {
|
||||
var (
|
||||
testMachine2 = "test-machine-2"
|
||||
testMachine3 = "test-machine-3"
|
||||
ins = []*model.CreateInstance{
|
||||
{
|
||||
Instance: model.Instance{
|
||||
InstanceName: testMachine2,
|
||||
},
|
||||
InstanceCreateStatus: model.CreatingMachineInPass,
|
||||
}, {
|
||||
Instance: model.Instance{
|
||||
InstanceName: testMachine3,
|
||||
},
|
||||
InstanceCreateStatus: model.CreateFailedMachineInPaas,
|
||||
},
|
||||
}
|
||||
u = "seanan"
|
||||
gmr = &model.GenMachinesRequest{
|
||||
Env: model.Env{
|
||||
ClusterID: 1,
|
||||
NetworkID: 1,
|
||||
},
|
||||
PaasMachine: model.PaasMachine{
|
||||
Name: "test-machine",
|
||||
Image: "test-Image",
|
||||
CPURequest: 1000,
|
||||
MemoryRequest: 1024,
|
||||
DiskRequest: 20,
|
||||
VolumnMount: "/data",
|
||||
},
|
||||
Nodes: []*model.Node{
|
||||
{
|
||||
BusinessUnit: "test",
|
||||
Project: "ep",
|
||||
App: "merlin",
|
||||
TreeID: 1234,
|
||||
},
|
||||
},
|
||||
Comment: "test",
|
||||
Amount: 1,
|
||||
}
|
||||
err error
|
||||
actualMachine []*model.Machine
|
||||
flag = 0
|
||||
)
|
||||
err = d.InsertMachines(u, gmr, ins)
|
||||
defer func() {
|
||||
if err = d.db.Where("name IN (?)", []string{testMachine2, testMachine3}).Delete(&model.Machine{}).Error; err != nil {
|
||||
log.Error("Failed to delete machine(%v) for test, err(%v)", tMachine, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
So(err, ShouldBeNil)
|
||||
if err = d.db.Where("name IN (?)", []string{testMachine2, testMachine3}).Find(&actualMachine).Error; err != nil {
|
||||
log.Error("Find machiens err(%v)", err)
|
||||
return
|
||||
}
|
||||
for _, m := range actualMachine {
|
||||
if m.Name == testMachine2 && m.Status == model.CreatingMachineInMerlin {
|
||||
flag++
|
||||
}
|
||||
if m.Name == testMachine3 && m.Status == model.ImmediatelyFailedMachineInMerlin {
|
||||
flag += 2
|
||||
}
|
||||
}
|
||||
So(flag, ShouldEqual, 3)
|
||||
}))
|
||||
}
|
24
app/admin/ep/merlin/dao/mysql_mail_log.go
Normal file
24
app/admin/ep/merlin/dao/mysql_mail_log.go
Normal file
@ -0,0 +1,24 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertMailLog insert mail log.
|
||||
func (d *Dao) InsertMailLog(ml *model.MailLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(&ml).Error)
|
||||
}
|
||||
|
||||
// DelMailLog delete mail log.
|
||||
func (d *Dao) DelMailLog(receiverName string) (err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("receiver_name=?", receiverName).Delete(model.MailLog{}).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindMailLog find mail log.
|
||||
func (d *Dao) FindMailLog(receiverName string) (mailLogs []*model.MailLog, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("receiver_name=?", receiverName).Find(&mailLogs).Error)
|
||||
return
|
||||
}
|
41
app/admin/ep/merlin/dao/mysql_mail_log_test.go
Normal file
41
app/admin/ep/merlin/dao/mysql_mail_log_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
username = "fengyifenguitest@bilibili.com"
|
||||
)
|
||||
|
||||
func Test_Mail_Log(t *testing.T) {
|
||||
Convey("test add mail log", t, func() {
|
||||
ml := &model.MailLog{
|
||||
ReceiverName: username,
|
||||
MailType: 1,
|
||||
SendContext: "test add mail log",
|
||||
}
|
||||
err := d.InsertMailLog(ml)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test find mail log", t, func() {
|
||||
mailLogs, err := d.FindMailLog(username)
|
||||
So(len(mailLogs), ShouldBeGreaterThan, 0)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test delete mail log", t, func() {
|
||||
err := d.DelMailLog(username)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test find mail log", t, func() {
|
||||
mailLogs, err := d.FindMailLog(username)
|
||||
So(len(mailLogs), ShouldEqual, 0)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
318
app/admin/ep/merlin/dao/mysql_mobile_machine.go
Normal file
318
app/admin/ep/merlin/dao/mysql_mobile_machine.go
Normal file
@ -0,0 +1,318 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FindMobileMachineBySerial Find Device FarmBy Serial.
|
||||
func (d *Dao) FindMobileMachineBySerial(serial string) (mobileMachine *model.MobileMachine, err error) {
|
||||
mobileMachine = &model.MobileMachine{}
|
||||
if err = d.db.Where("serial = ?", serial).Find(mobileMachine).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMobileMachineByUUID Delete Mobile Machine By UUID.
|
||||
func (d *Dao) DeleteMobileMachineByUUID(UUID string) (delCnt int, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.MobileMachine{}).Where("uuid <> ? and action <>?", UUID, model.MBHostDel).Count(&delCnt).Update("action", model.MBOffline).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMobileMachineNotInHost Delete Mobile Machine Not In Host.
|
||||
func (d *Dao) DeleteMobileMachineNotInHost(hostList []string) (delCnt int, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.MobileMachine{}).Where("host not in (?)", hostList).Count(&delCnt).Update("action", model.MBHostDel).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindMobileMachineByID Find Mobile Machine By Id.
|
||||
func (d *Dao) FindMobileMachineByID(deviceID int64) (mobileMachine *model.MobileMachine, err error) {
|
||||
mobileMachine = &model.MobileMachine{}
|
||||
err = pkgerr.WithStack(d.db.Where("id = ?", deviceID).Find(mobileMachine).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// InsertMobileMachine Insert Device Farm.
|
||||
func (d *Dao) InsertMobileMachine(mobileMachine *model.MobileMachine) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(&mobileMachine).Error)
|
||||
}
|
||||
|
||||
// UpdateMobileMachineWsurlAndState Update Mobile Machine Wsurl And State.
|
||||
func (d *Dao) UpdateMobileMachineWsurlAndState(mobileMachine *model.MobileMachine) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.MobileMachine{}).Where("serial=?", mobileMachine.Serial).Updates(map[string]interface{}{"wsurl": mobileMachine.WsURL, "state": mobileMachine.State, "upload_url": mobileMachine.UploadURL}).Error)
|
||||
}
|
||||
|
||||
// UpdateMobileMachine Update Mobile Machine.
|
||||
func (d *Dao) UpdateMobileMachine(mobileMachine *model.MobileMachine) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.MobileMachine{}).Where("serial=?", mobileMachine.Serial).Updates(mobileMachine).Error)
|
||||
}
|
||||
|
||||
// UpdateMobileMachineByRelease Update Mobile Machine By Release.
|
||||
func (d *Dao) UpdateMobileMachineByRelease(mobileMachine *model.MobileMachine) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.MobileMachine{}).Where("serial=?", mobileMachine.Serial).Updates(map[string]interface{}{"username": mobileMachine.Username, "end_time": mobileMachine.EndTime}).Error)
|
||||
}
|
||||
|
||||
//FindMobileMachines Find Mobile Machines.
|
||||
func (d *Dao) FindMobileMachines(queryRequest *model.QueryMobileDeviceRequest) (total int64, mobileMachines []*model.MobileMachine, err error) {
|
||||
gDB := d.db.Model(&model.MobileMachine{}).Where("action> ? ", model.MBHostDel)
|
||||
|
||||
if queryRequest.MobileID > 0 {
|
||||
gDB = gDB.Where("id=?", queryRequest.MobileID)
|
||||
}
|
||||
if queryRequest.Serial != "" {
|
||||
gDB = gDB.Where("serial=?", queryRequest.Serial)
|
||||
}
|
||||
if queryRequest.Name != "" {
|
||||
gDB = gDB.Where("name=?", queryRequest.Name)
|
||||
}
|
||||
if queryRequest.Username != "" {
|
||||
gDB = gDB.Where("username=?", queryRequest.Username)
|
||||
}
|
||||
if queryRequest.OwnerName != "" {
|
||||
gDB = gDB.Where("owner_name=?", queryRequest.OwnerName)
|
||||
}
|
||||
if queryRequest.CPU != "" {
|
||||
gDB = gDB.Where("cpu=?", queryRequest.CPU)
|
||||
}
|
||||
if queryRequest.Version != "" {
|
||||
gDB = gDB.Where("version=?", queryRequest.Version)
|
||||
}
|
||||
if queryRequest.Mode != "" {
|
||||
gDB = gDB.Where("mode=?", queryRequest.Mode)
|
||||
}
|
||||
if queryRequest.Type > -1 {
|
||||
gDB = gDB.Where("type=?", queryRequest.Type)
|
||||
}
|
||||
if queryRequest.State != "" {
|
||||
gDB = gDB.Where("state=?", queryRequest.State)
|
||||
}
|
||||
if queryRequest.Online {
|
||||
gDB = gDB.Where("action=?", model.MBOnline)
|
||||
}
|
||||
if queryRequest.Usage == model.MBFree {
|
||||
gDB = gDB.Where("username='' and action=?", model.MBOnline)
|
||||
}
|
||||
if queryRequest.Usage == model.MBInUse {
|
||||
gDB = gDB.Where("username<>'' and action=?", model.MBOnline)
|
||||
}
|
||||
if queryRequest.Usage == model.MBNoConnect {
|
||||
gDB = gDB.Where("action=?", model.MBOffline)
|
||||
}
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//先出action>0的,未连接的排在后面
|
||||
err = pkgerr.WithStack(gDB.Order("action desc,id desc").Offset((queryRequest.PageNum - 1) * queryRequest.PageSize).Limit(queryRequest.PageSize).Find(&mobileMachines).Error)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindMobileMachineCategory Find Mobile Machine Category.
|
||||
func (d *Dao) FindMobileMachineCategory(isShowOffline bool) (mobileCategory *model.MobileCategory, err error) {
|
||||
var (
|
||||
rows *sql.Rows
|
||||
cpus []string
|
||||
versions []string
|
||||
modes []string
|
||||
states []string
|
||||
types []int
|
||||
usages []int
|
||||
|
||||
sqlGroupTpl string
|
||||
|
||||
inUseCnt int
|
||||
freeCnt int
|
||||
noConCnt int
|
||||
)
|
||||
|
||||
if isShowOffline {
|
||||
sqlGroupTpl = "select %s from mobile_machines where action> " + strconv.Itoa(model.MBHostDel) + " group by %s"
|
||||
} else {
|
||||
sqlGroupTpl = "select %s from mobile_machines where action>-1 group by %s"
|
||||
}
|
||||
|
||||
tx := d.db.Begin()
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//cpu
|
||||
if rows, err = tx.Raw(fmt.Sprintf(sqlGroupTpl, "cpu", "cpu")).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var cpu string
|
||||
if err = rows.Scan(&cpu); err != nil {
|
||||
return
|
||||
}
|
||||
cpus = append(cpus, cpu)
|
||||
}
|
||||
|
||||
//version
|
||||
if rows, err = tx.Raw(fmt.Sprintf(sqlGroupTpl, "version", "version")).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var version string
|
||||
if err = rows.Scan(&version); err != nil {
|
||||
return
|
||||
}
|
||||
versions = append(versions, version)
|
||||
}
|
||||
|
||||
//mode
|
||||
if rows, err = tx.Raw(fmt.Sprintf(sqlGroupTpl, "mode", "mode")).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var mode string
|
||||
if err = rows.Scan(&mode); err != nil {
|
||||
return
|
||||
}
|
||||
modes = append(modes, mode)
|
||||
}
|
||||
|
||||
//state
|
||||
if rows, err = tx.Raw(fmt.Sprintf(sqlGroupTpl, "state", "state")).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var state string
|
||||
if err = rows.Scan(&state); err != nil {
|
||||
return
|
||||
}
|
||||
states = append(states, state)
|
||||
}
|
||||
|
||||
//type
|
||||
if rows, err = tx.Raw(fmt.Sprintf(sqlGroupTpl, "type", "type")).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var stype int
|
||||
if err = rows.Scan(&stype); err != nil {
|
||||
return
|
||||
}
|
||||
types = append(types, stype)
|
||||
}
|
||||
|
||||
//usage
|
||||
if err = tx.Model(&model.MobileMachine{}).Where("username<>'' and action>0").Count(&inUseCnt).Error; err != nil {
|
||||
return
|
||||
}
|
||||
if err = tx.Model(&model.MobileMachine{}).Where("username='' and action>0").Count(&freeCnt).Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.MobileMachine{}).Where("action<0").Count(&noConCnt).Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if inUseCnt > 0 {
|
||||
usages = append(usages, model.MBInUse)
|
||||
}
|
||||
|
||||
if freeCnt > 0 {
|
||||
usages = append(usages, model.MBFree)
|
||||
}
|
||||
|
||||
if noConCnt > 0 {
|
||||
usages = append(usages, model.MBNoConnect)
|
||||
}
|
||||
|
||||
mobileCategory = &model.MobileCategory{}
|
||||
mobileCategory.CPUs = cpus
|
||||
mobileCategory.Versions = versions
|
||||
mobileCategory.Modes = modes
|
||||
mobileCategory.States = states
|
||||
mobileCategory.Types = types
|
||||
mobileCategory.Usages = usages
|
||||
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllMobileImages Find All Mobile Images.
|
||||
func (d *Dao) FindAllMobileImages() (mobileImages []*model.MobileImage, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.MobileImage{}).Find(&mobileImages).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindMobileImageByMode Find Mobile Image By Mode.
|
||||
func (d *Dao) FindMobileImageByMode(mode string) (mobileImage *model.MobileImage, err error) {
|
||||
mobileImage = &model.MobileImage{}
|
||||
if err = d.db.Where("mode=?", mode).First(mobileImage).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LendOutMobileMachine Lend Out Mobile.
|
||||
func (d *Dao) LendOutMobileMachine(deviceID int64, serial, username string) (err error) {
|
||||
tx := d.db.Begin()
|
||||
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mobileMachineLog := &model.MobileMachineLog{
|
||||
OperateType: model.MBLendOutLog,
|
||||
Username: username,
|
||||
MachineID: deviceID,
|
||||
OperateResult: model.OperationSuccessForMachineLog,
|
||||
}
|
||||
if err = tx.Create(mobileMachineLog).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.MobileMachine{}).Where("serial=?", serial).Update("is_lendout", model.MBLendOut).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReturnMobileMachine return Mobile.
|
||||
func (d *Dao) ReturnMobileMachine(deviceID int64, serial, username string) (err error) {
|
||||
tx := d.db.Begin()
|
||||
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mobileMachineLog := &model.MobileMachineLog{
|
||||
OperateType: model.MBReturnLog,
|
||||
Username: username,
|
||||
MachineID: deviceID,
|
||||
OperateResult: model.OperationSuccessForMachineLog,
|
||||
}
|
||||
if err = tx.Create(mobileMachineLog).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Model(&model.MobileMachine{}).Where("serial=?", serial).Update("is_lendout", model.MBOnSite).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
24
app/admin/ep/merlin/dao/mysql_mobile_machine_error_log.go
Normal file
24
app/admin/ep/merlin/dao/mysql_mobile_machine_error_log.go
Normal file
@ -0,0 +1,24 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertMobileMachineErrorLog Insert Mobile Machine Error Log.
|
||||
func (d *Dao) InsertMobileMachineErrorLog(mobileMachineErrorLog *model.MobileMachineErrorLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(mobileMachineErrorLog).Error)
|
||||
}
|
||||
|
||||
// FindMobileMachineErrorLog Find Mobile Machine Error Log.
|
||||
func (d *Dao) FindMobileMachineErrorLog(queryRequest *model.QueryMobileMachineErrorLogRequest) (total int64, mobileMachineErrorLogs []*model.MobileMachineErrorLog, err error) {
|
||||
cdb := d.db.Model(&model.MobileMachineErrorLog{}).Where("machine_id=?", queryRequest.MachineID).Order("ID desc").Offset((queryRequest.PageNum - 1) * queryRequest.PageSize).Limit(queryRequest.PageSize)
|
||||
if err = pkgerr.WithStack(cdb.Find(&mobileMachineErrorLogs).Error); err != nil {
|
||||
return
|
||||
}
|
||||
if err = pkgerr.WithStack(d.db.Model(&model.MobileMachineErrorLog{}).Where("machine_id=?", queryRequest.MachineID).Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
80
app/admin/ep/merlin/dao/mysql_mobile_machine_log.go
Normal file
80
app/admin/ep/merlin/dao/mysql_mobile_machine_log.go
Normal file
@ -0,0 +1,80 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
_mobileRightJoinLogSQL = "SELECT m.id,m.serial,ml.username,ml.operation_type,ml.operation_result,ml.ctime FROM mobile_machines AS m INNER JOIN mobile_machine_logs AS ml ON m.id = ml.machine_id"
|
||||
_mobileRightCountSQL = "SELECT count(m.id) FROM mobile_machines AS m INNER JOIN mobile_machine_logs AS ml ON m.id = ml.machine_id"
|
||||
)
|
||||
|
||||
// InsertMobileMachineLog Insert Mobile Machine Log.
|
||||
func (d *Dao) InsertMobileMachineLog(mobileMachineLog *model.MobileMachineLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(mobileMachineLog).Error)
|
||||
}
|
||||
|
||||
// FindMobileMachineLogs Find Mobile Machine Logs.
|
||||
func (d *Dao) FindMobileMachineLogs(queryRequest *model.QueryMobileMachineLogRequest) (total int64, mobileMachineLogs []*model.AboundMobileMachineLog, err error) {
|
||||
var (
|
||||
qSQL = _mobileRightJoinLogSQL
|
||||
cSQL = _mobileRightCountSQL
|
||||
rows *sql.Rows
|
||||
)
|
||||
|
||||
if queryRequest.MachineID > 0 || queryRequest.OperateType != "" || queryRequest.OperateUser != "" || queryRequest.Serial != "" {
|
||||
var (
|
||||
strSQL = ""
|
||||
logicalWord = _where
|
||||
)
|
||||
|
||||
if queryRequest.MachineID > 0 {
|
||||
strSQL = fmt.Sprintf("%s %s ml.machine_id = %s", strSQL, logicalWord, strconv.FormatInt(queryRequest.MachineID, 10))
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.OperateType != "" {
|
||||
strSQL = fmt.Sprintf("%s %s ml.operation_type like '%s'", strSQL, logicalWord, _wildcards+queryRequest.OperateType+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.Serial != "" {
|
||||
strSQL = fmt.Sprintf("%s %s m.serial like '%s'", strSQL, logicalWord, _wildcards+queryRequest.Serial+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if queryRequest.OperateUser != "" {
|
||||
strSQL = fmt.Sprintf("%s %s ml.username like '%s'", strSQL, logicalWord, _wildcards+queryRequest.OperateUser+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
qSQL = _mobileRightJoinLogSQL + " " + strSQL
|
||||
cSQL = _mobileRightCountSQL + " " + strSQL
|
||||
|
||||
}
|
||||
|
||||
cDB := d.db.Raw(cSQL)
|
||||
if err = pkgerr.WithStack(cDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
gDB := d.db.Raw(qSQL)
|
||||
if rows, err = gDB.Order("ml.ctime DESC").Offset((queryRequest.PageNum - 1) * queryRequest.PageSize).Limit(queryRequest.PageSize).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
ml := &model.AboundMobileMachineLog{}
|
||||
if err = rows.Scan(&ml.MachineID, &ml.Serial, &ml.Username, &ml.OperateType, &ml.OperateResult, &ml.OperateTime); err != nil {
|
||||
return
|
||||
}
|
||||
mobileMachineLogs = append(mobileMachineLogs, ml)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
23
app/admin/ep/merlin/dao/mysql_mobile_sync_log.go
Normal file
23
app/admin/ep/merlin/dao/mysql_mobile_sync_log.go
Normal file
@ -0,0 +1,23 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertMobileSyncLog Insert Mobile Sync Log.
|
||||
func (d *Dao) InsertMobileSyncLog(mobileSyncLog *model.MobileSyncLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(mobileSyncLog).Error)
|
||||
}
|
||||
|
||||
// UpdateMobileSyncLog Update Mobile SyncLog.
|
||||
func (d *Dao) UpdateMobileSyncLog(mobileSyncLog *model.MobileSyncLog) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.MobileSyncLog{}).Where("uuid=?", mobileSyncLog.UUID).Update(mobileSyncLog).Error)
|
||||
}
|
||||
|
||||
// FindMobileSyncLogStartStatus FindMobile SyncLog Start Status.
|
||||
func (d *Dao) FindMobileSyncLogStartStatus() (startCount int, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.MobileSyncLog{}).Where("status=0 and mtime>=DATE_SUB(NOW(),INTERVAL 10 MINUTE)").Count(&startCount).Error)
|
||||
return
|
||||
}
|
40
app/admin/ep/merlin/dao/mysql_snapshot_record.go
Normal file
40
app/admin/ep/merlin/dao/mysql_snapshot_record.go
Normal file
@ -0,0 +1,40 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertSnapshotRecord Insert Snapshot Record.
|
||||
func (d *Dao) InsertSnapshotRecord(snapshotRecord *model.SnapshotRecord) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(snapshotRecord).Error)
|
||||
}
|
||||
|
||||
// FindSnapshotRecord Find Snapshot Record.
|
||||
func (d *Dao) FindSnapshotRecord(machineID int64) (snapshotRecord *model.SnapshotRecord, err error) {
|
||||
snapshotRecord = &model.SnapshotRecord{}
|
||||
if err = d.db.Where("machine_id = ?", machineID).First(snapshotRecord).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateSnapshotRecordStatus Update Snapshot Record Status.
|
||||
func (d *Dao) UpdateSnapshotRecordStatus(machineID int64, status string) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.SnapshotRecord{}).Where("machine_id = ?", machineID).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// UpdateSnapshotRecord Update Snapshot Record.
|
||||
func (d *Dao) UpdateSnapshotRecord(snapshotRecord *model.SnapshotRecord) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.SnapshotRecord{}).Where("machine_id = ?", snapshotRecord.MachineID).Update(snapshotRecord).Error)
|
||||
}
|
||||
|
||||
// FindSnapshotStatusInDoingOver2Hours Find Snapshot Status In Doing Over 2 Hours.
|
||||
func (d *Dao) FindSnapshotStatusInDoingOver2Hours() (snapshotRecords []*model.SnapshotRecord, err error) {
|
||||
if err = d.db.Where("status = ? and unix_timestamp(now())> unix_timestamp(date_add(mtime, interval 2 hour))", model.SnapshotDoing).Find(&snapshotRecords).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
41
app/admin/ep/merlin/dao/mysql_task.go
Normal file
41
app/admin/ep/merlin/dao/mysql_task.go
Normal file
@ -0,0 +1,41 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FindDeleteMachineTasks find delete machine tasks.
|
||||
func (d *Dao) FindDeleteMachineTasks() (tasks []*model.Task, err error) {
|
||||
tasks = []*model.Task{}
|
||||
err = pkgerr.WithStack(d.db.Where("status=? AND type=? AND DATEDIFF(NOW(),execute_time)=0 AND execute_time < NOW()", model.TaskInit, model.DeleteMachine).Find(&tasks).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateTaskStatusByMachines update task status by machines.
|
||||
func (d *Dao) UpdateTaskStatusByMachines(machineIDs []int64, status int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Task{}).Where("machine_id IN (?)", machineIDs).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// UpdateTaskStatusByTaskID update task status by taskId.
|
||||
func (d *Dao) UpdateTaskStatusByTaskID(taskID int64, status int) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.Task{}).Where("id IN (?)", taskID).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// InsertDeleteMachinesTasks insert delete machines tasks.
|
||||
// TODO:这块逻辑不是很好,如果一个写入失败希望继续写入失败的话最好返回失败list,后续联调时优化
|
||||
func (d *Dao) InsertDeleteMachinesTasks(ms []*model.Machine) (err error) {
|
||||
for _, machine := range ms {
|
||||
mrTask := &model.Task{
|
||||
TYPE: model.DeleteMachine,
|
||||
ExecuteTime: machine.EndTime,
|
||||
MachineID: machine.ID,
|
||||
Status: model.TaskInit,
|
||||
}
|
||||
if tempErr := d.db.Create(mrTask).Error; tempErr != nil {
|
||||
err = pkgerr.WithStack(tempErr)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
36
app/admin/ep/merlin/dao/mysql_task_test.go
Normal file
36
app/admin/ep/merlin/dao/mysql_task_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
testMachine = model.Machine{
|
||||
EndTime: time.Now().Add((-1) * time.Hour),
|
||||
ID: 123123,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Task(t *testing.T) {
|
||||
Convey("test InsertDeleteMachinesTasks", t, func() {
|
||||
err := d.InsertDeleteMachinesTasks([]*model.Machine{&testMachine})
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test FindDeleteMachineTasks", t, func() {
|
||||
tasks, err := d.FindDeleteMachineTasks()
|
||||
So(err, ShouldBeNil)
|
||||
So(len(tasks), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
Convey("test UpdateTaskStatusByMachines", t, func() {
|
||||
err := d.UpdateTaskStatusByMachines([]int64{testMachine.ID}, 2)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
}
|
31
app/admin/ep/merlin/dao/mysql_user.go
Normal file
31
app/admin/ep/merlin/dao/mysql_user.go
Normal file
@ -0,0 +1,31 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FindUserByUserName find user by username.
|
||||
func (d *Dao) FindUserByUserName(name string) (user *model.User, err error) {
|
||||
user = &model.User{}
|
||||
err = pkgerr.WithStack(d.db.Where("name = ?", name).First(user).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindUserByID find user by id.
|
||||
func (d *Dao) FindUserByID(ID int64) (user *model.User, err error) {
|
||||
user = &model.User{}
|
||||
err = pkgerr.WithStack(d.db.Where("id = ?", ID).First(user).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateUser create user.
|
||||
func (d *Dao) CreateUser(user *model.User) (err error) {
|
||||
return pkgerr.WithStack(d.db.Create(user).Error)
|
||||
}
|
||||
|
||||
// DelUser delete user.
|
||||
func (d *Dao) DelUser(user *model.User) (err error) {
|
||||
return pkgerr.WithStack(d.db.Delete(user).Error)
|
||||
}
|
43
app/admin/ep/merlin/dao/mysql_user_test.go
Normal file
43
app/admin/ep/merlin/dao/mysql_user_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
testTime = time.Now().Format("2006_01_02_15_04_05")
|
||||
testUser = model.User{
|
||||
Name: testTime,
|
||||
EMail: testTime + "@bilibili.com"}
|
||||
)
|
||||
|
||||
func Test_User(t *testing.T) {
|
||||
Convey("test CreateUser", t, func() {
|
||||
err := d.CreateUser(&testUser)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("find user by user name", t, func() {
|
||||
userInDb, err := d.FindUserByUserName(testUser.Name)
|
||||
So(userInDb.EMail, ShouldEqual, testUser.EMail)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("find user by id", t, func() {
|
||||
userID := testUser.ID
|
||||
userInDb, err := d.FindUserByID(userID)
|
||||
So(userInDb.EMail, ShouldEqual, testUser.EMail)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("delete user", t, func() {
|
||||
err := d.DelUser(&testUser)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
}
|
254
app/admin/ep/merlin/dao/paas.go
Normal file
254
app/admin/ep/merlin/dao/paas.go
Normal file
@ -0,0 +1,254 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_genPaasMachines = "/api/merlin/machine/create"
|
||||
_delPaasMachine = "/api/merlin/machine/free"
|
||||
_queryPaasMachineStatus = "/api/merlin/machine/status"
|
||||
_queryPaasMachine = "/api/merlin/machine/detail"
|
||||
_updatePaasMachineNode = "/api/merlin/machine/update"
|
||||
_updatePaasMachineSnapshot = "/api/merlin/machine/snapshot"
|
||||
_queryPaasClusters = "/api/merlin/clusters"
|
||||
_queryPaasClusterByNetwork = "/api/merlin/clusters/network/"
|
||||
_auth = "/api/v1/auth"
|
||||
_authHeader = "X-Authorization-Token"
|
||||
)
|
||||
|
||||
// GenPaasMachines create machine in paas.
|
||||
func (d *Dao) GenPaasMachines(c context.Context, mc *model.PaasGenMachineRequest) (instances []*model.CreateInstance, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasGenMachineResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _genPaasMachines, mc); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("gen paas machine url(%s) err(%v)", _genPaasMachines, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
instances = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// DelPaasMachine delete machine in paas.
|
||||
func (d *Dao) DelPaasMachine(c context.Context, pqadmr *model.PaasQueryAndDelMachineRequest) (instance *model.ReleaseInstance, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasDelMachineResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _delPaasMachine, pqadmr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("delete paas machine url(%s) err(%v)", _delPaasMachine, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
instance = &res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// QueryPaasMachineStatus query status of machine in paas.
|
||||
func (d *Dao) QueryPaasMachineStatus(c context.Context, pqadmr *model.PaasQueryAndDelMachineRequest) (machineStatus *model.MachineStatus, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasQueryMachineStatusResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _queryPaasMachineStatus, pqadmr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("query paas machine status url(%s) err(%v)", _queryPaasMachineStatus, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
machineStatus = &res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// SnapshotPaasMachineStatus Snapshot Paas Machine Status.
|
||||
func (d *Dao) SnapshotPaasMachineStatus(c context.Context, pqadmr *model.PaasQueryAndDelMachineRequest) (status int, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasSnapshotMachineResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _updatePaasMachineSnapshot, pqadmr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("snapshot machine status url(%s) err(%v)", _updatePaasMachineSnapshot, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
status = res.Status
|
||||
return
|
||||
}
|
||||
|
||||
// QueryPaasMachine query detail information of machine in paas.
|
||||
func (d *Dao) QueryPaasMachine(c context.Context, pqadmr *model.PaasQueryAndDelMachineRequest) (md *model.PaasMachineDetail, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasQueryMachineResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _queryPaasMachine, pqadmr); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("query paas machine url(%s) err(%v)", _queryPaasMachine, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
md = &res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// QueryClusters query cluster information in paas.
|
||||
func (d *Dao) QueryClusters(c context.Context) (clusters []*model.Cluster, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasQueryClustersResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodGet, _queryPaasClusters, nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.httpSearch url(%s) error(%v)", d.c.Paas.Host+"?"+_queryPaasClusters, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
clusters = res.Data.Items
|
||||
return
|
||||
}
|
||||
|
||||
// QueryCluster query cluster information in paas by giving network.
|
||||
func (d *Dao) QueryCluster(c context.Context, netWordID int64) (cluster *model.Cluster, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasQueryClusterResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodGet, _queryPaasClusterByNetwork+strconv.FormatInt(netWordID, 10), nil); err != nil {
|
||||
log.Error("http new request err(%v)", err)
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.httpSearch url(%s) error(%v)", d.c.Paas.Host+"?"+_queryPaasClusters, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
cluster = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// UpdatePaasMachineNode update paas machine node.
|
||||
func (d *Dao) UpdatePaasMachineNode(c context.Context, pumnr *model.PaasUpdateMachineNodeRequest) (data string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasUpdateMachineNodeResponse{}
|
||||
)
|
||||
if req, err = d.newPaasRequest(c, http.MethodPost, _updatePaasMachineNode, pumnr); err != nil {
|
||||
log.Error("http new request err(%v)", err)
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.httpSearch url(%s) error(%v)", d.c.Paas.Host+_updatePaasMachineNode, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
data = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) authPaas(c context.Context) (token string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.PaasAuthResponse{}
|
||||
authRequest = model.PaasAuthRequest{
|
||||
APIToken: d.c.Paas.Token,
|
||||
PlatformID: "merlin",
|
||||
}
|
||||
)
|
||||
if req, err = d.newRequest(http.MethodPost, d.c.Paas.Host+_auth, authRequest); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("query paas machine url(%s) err(%v)", _auth, err)
|
||||
err = ecode.MerlinPaasRequestErr
|
||||
return
|
||||
}
|
||||
if err = res.CheckStatus(); err != nil {
|
||||
return
|
||||
}
|
||||
token = res.Data.Token
|
||||
return
|
||||
}
|
||||
|
||||
// paasToken TODO:当前放在dao层有点不规范,放在service层,封装上又不如这样更好,后续再考虑一下.
|
||||
func (d *Dao) paasToken(c context.Context) (authToken string, err error) {
|
||||
var (
|
||||
item *memcache.Item
|
||||
conn = d.mc.Get(c)
|
||||
)
|
||||
defer conn.Close()
|
||||
if item, err = conn.Get(d.c.Paas.Token); err == nil {
|
||||
if err = json.Unmarshal(item.Value, &authToken); err != nil {
|
||||
log.Error("Json unmarshal err(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if authToken, err = d.authPaas(c); err != nil {
|
||||
return
|
||||
}
|
||||
item = &memcache.Item{Key: d.c.Paas.Token, Object: authToken, Flags: memcache.FlagJSON, Expiration: d.expire}
|
||||
d.tokenCacheSave(c, item)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) newPaasRequest(c context.Context, method, uri string, v interface{}) (req *http.Request, err error) {
|
||||
var authToken string
|
||||
if authToken, err = d.paasToken(c); err != nil {
|
||||
return
|
||||
}
|
||||
if req, err = d.newRequest(method, d.c.Paas.Host+uri, v); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set(_authHeader, authToken)
|
||||
return
|
||||
}
|
156
app/admin/ep/merlin/dao/paas_test.go
Normal file
156
app/admin/ep/merlin/dao/paas_test.go
Normal file
@ -0,0 +1,156 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
gmRequest = model.PaasGenMachineRequest{
|
||||
Env: model.Env{
|
||||
ClusterID: 3,
|
||||
NetworkID: 7,
|
||||
},
|
||||
Machines: []model.PaasMachine{
|
||||
{
|
||||
Name: "vm1",
|
||||
Image: "docker-reg.bilibili.co/zccdebian:1.0",
|
||||
CPURequest: 1000,
|
||||
MemoryRequest: 500,
|
||||
DiskRequest: 20,
|
||||
VolumnMount: "",
|
||||
},
|
||||
{
|
||||
Name: "vm2",
|
||||
Image: "docker-reg.bilibili.co/debian:latest",
|
||||
CPURequest: 1000,
|
||||
MemoryRequest: 500,
|
||||
DiskRequest: 20,
|
||||
VolumnMount: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
qdmRequest = model.PaasQueryAndDelMachineRequest{
|
||||
BusinessUnit: "ops",
|
||||
Project: "zcc",
|
||||
App: "zcc",
|
||||
ClusterID: 3,
|
||||
Name: "vm1",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_GenPaasMachines(t *testing.T) {
|
||||
Convey("create two machines in paas", t, WithPaasToken(func() {
|
||||
data := `{"status": 200,"message":"success","data":[{"instance_name": "vm1","instance_create_status": 2},{"instance_name": "vm2","instance_create_status": 1}]}`
|
||||
gmURL := d.c.Paas.Host + _genPaasMachines
|
||||
httpMock("POST", gmURL).Reply(200).JSON(data)
|
||||
res, err := d.GenPaasMachines(ctx(), &gmRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldResemble, []*model.CreateInstance{
|
||||
{
|
||||
Instance: model.Instance{InstanceName: "vm1"},
|
||||
InstanceCreateStatus: 2,
|
||||
},
|
||||
{
|
||||
Instance: model.Instance{InstanceName: "vm2"},
|
||||
InstanceCreateStatus: 1,
|
||||
},
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func Test_DelPaasMachine(t *testing.T) {
|
||||
Convey("Delete machine from paas", t, WithPaasToken(func() {
|
||||
data := `{"status": 200,"message": "success","data": {"instance_name": "vm1","instance_release_status": 1}}`
|
||||
dmURL := d.c.Paas.Host + _delPaasMachine
|
||||
httpMock("POST", dmURL).Reply(200).JSON(data)
|
||||
res, err := d.DelPaasMachine(ctx(), &qdmRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldResemble, &model.ReleaseInstance{
|
||||
Instance: model.Instance{InstanceName: "vm1"},
|
||||
InstanceReleaseStatus: 1,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func Test_QueryPaasMachineStatus(t *testing.T) {
|
||||
Convey("query machine status", t, WithPaasToken(func() {
|
||||
data := `{"status": 200,"message": "success","data": {"condition": "Running","message": "","detail_conditions": {"Initialized": "True","PodScheduled": "True","Ready": "True"},"instance_ip": "172.16.62.84","restart_count": 0}}`
|
||||
qmsURL := d.c.Paas.Host + _queryPaasMachineStatus
|
||||
httpMock("POST", qmsURL).Reply(200).JSON(data)
|
||||
res, err := d.QueryPaasMachineStatus(ctx(), &qdmRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldResemble, &model.MachineStatus{
|
||||
Condition: "Running",
|
||||
Message: "",
|
||||
DetailCondition: model.DetailCondition{
|
||||
Initialized: "True",
|
||||
PodScheduled: "True",
|
||||
Ready: "True",
|
||||
},
|
||||
InstanceIP: "172.16.62.84",
|
||||
RestartCount: 0,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func Test_QueryPaasMachine(t *testing.T) {
|
||||
Convey("query machine details", t, WithPaasToken(func() {
|
||||
data := `{"status": 200,"message": "success","data": {"condition": "Running","name": "vm1","image": "docker-reg.bilibili.co/zccdebian:1.0","cpu_request": 1000,"memory_request": 512,"disk_request": 0,"volumn_mount": "","cluster_name": "shyp-fat-k8s","env": "fat1","ip": "172.16.62.84"}}`
|
||||
qmdURL := d.c.Paas.Host + _queryPaasMachine
|
||||
httpMock("POST", qmdURL).Reply(200).JSON(data)
|
||||
res, err := d.QueryPaasMachine(ctx(), &qdmRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldResemble, &model.PaasMachineDetail{
|
||||
Condition: "Running",
|
||||
Name: "vm1",
|
||||
Image: "docker-reg.bilibili.co/zccdebian:1.0",
|
||||
CPURequest: 1000,
|
||||
MemoryRequest: 512,
|
||||
DiskRequest: 0,
|
||||
VolumnMount: "",
|
||||
ClusterName: "shyp-fat-k8s",
|
||||
Env: "fat1",
|
||||
IP: "172.16.62.84",
|
||||
})
|
||||
|
||||
}))
|
||||
}
|
||||
|
||||
func Test_QueryClusters(t *testing.T) {
|
||||
Convey("query clusters from paas", t, WithPaasToken(func() {
|
||||
data := `{"status": 200,"message": "success","count": 4,"data": {"items": [{"id": 1,"name": "shylf-uat-k8s","desc": "上海云立集成环境k8s集群","idc": "shylf","networks": [{"id": 16,"name": "shylf_uat_vlan1035","subnet": "172.22.35.0/24","capacity": 0.3346774193548387}],"resources": {"cpu_usage": 0.5977777777777777,"mem_usage": 0.19947637451689315,"pod_total": 439,"pod_capacity": 990,"nodes_num": 9}}]}}`
|
||||
qcURL := d.c.Paas.Host + _queryPaasClusters
|
||||
httpMock("GET", qcURL).Reply(200).JSON(data)
|
||||
res, err := d.QueryClusters(ctx())
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldResemble, []*model.Cluster{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "shylf-uat-k8s",
|
||||
Desc: "上海云立集成环境k8s集群",
|
||||
IDc: "shylf",
|
||||
Networks: []model.Network{
|
||||
{
|
||||
ID: 16,
|
||||
Name: "shylf_uat_vlan1035",
|
||||
Subnet: "172.22.35.0/24",
|
||||
Capacity: 0.3346774193548387,
|
||||
},
|
||||
},
|
||||
Resources: model.Resource{
|
||||
CPUUsage: 0.5977777777777777,
|
||||
MemUsage: 0.19947637451689315,
|
||||
PodTotal: 439,
|
||||
PodCapacity: 990,
|
||||
NodesNum: 9,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}))
|
||||
}
|
306
app/admin/ep/merlin/dao/tree.go
Normal file
306
app/admin/ep/merlin/dao/tree.go
Normal file
@ -0,0 +1,306 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_treeURI = "/v1/node/tree"
|
||||
_treeMachines = "/v1/instance/hostnames"
|
||||
_treeSon = "/v1/node/extree"
|
||||
_treeRole = "/v1/node/role"
|
||||
_treeAppInstance = "/v1/instance/app"
|
||||
_authURI = "/v1/auth"
|
||||
_authPlatformURI = "/v1/token"
|
||||
_treeOkCode = 90000
|
||||
_sessIDKey = "_AJSESSIONID"
|
||||
_treeRootName = "bilibili."
|
||||
_questionMark = "?"
|
||||
)
|
||||
|
||||
// UserTree get user tree node.
|
||||
func (d *Dao) UserTree(c context.Context, sessionID string) (tree *model.UserTree, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeResponse{}
|
||||
)
|
||||
if req, err = d.newTreeRequest(c, http.MethodGet, _treeURI, sessionID, nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeURI, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", _treeURI, res)
|
||||
return
|
||||
}
|
||||
tree = &res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// TreeSon get user tree node son node.
|
||||
func (d *Dao) TreeSon(c context.Context, sessionID, treePath string) (treeSon map[string]interface{}, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeSonResponse{}
|
||||
)
|
||||
if req, err = d.newTreeRequest(c, http.MethodGet, _treeSon+"/"+d.getTreeFullPath(treePath), sessionID, nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeSon, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", _treeSon, res)
|
||||
return
|
||||
}
|
||||
return res.Data, nil
|
||||
}
|
||||
|
||||
// TreeRoles get tree roles.
|
||||
func (d *Dao) TreeRoles(c context.Context, sessionID, treePath string) (treeRoles []*model.TreeRole, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeRoleResponse{}
|
||||
)
|
||||
if req, err = d.newTreeRequest(c, http.MethodGet, _treeRole+"/"+d.getTreeFullPath(treePath), sessionID, nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeRole, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", _treeRole, res)
|
||||
return
|
||||
}
|
||||
return res.Data, nil
|
||||
}
|
||||
|
||||
// TreeRolesAsPlatform get tree roles.
|
||||
func (d *Dao) TreeRolesAsPlatform(c context.Context, treePath string) (treeRoles []*model.TreeRole, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeRoleResponse{}
|
||||
)
|
||||
if req, err = d.newPlatformTreeRequest(c, http.MethodGet, _treeRole+"/"+d.getTreeFullPath(treePath), nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeRole, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", _treeRole, res)
|
||||
return
|
||||
}
|
||||
return res.Data, nil
|
||||
}
|
||||
|
||||
//QueryTreeInstances query tree instances
|
||||
func (d *Dao) QueryTreeInstances(c context.Context, sessionID string, tir *model.TreeInstanceRequest) (tid map[string]*model.TreeInstance, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeInstancesResponse{}
|
||||
)
|
||||
if req, err = d.newTreeRequest(c, http.MethodGet, _treeMachines+_questionMark+tir.ToQueryURI(), sessionID, nil); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeRole, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
log.Error("Status url(%s) res(%v)", _treeRole, res)
|
||||
err = ecode.MerlinTreeResponseErr
|
||||
return
|
||||
}
|
||||
tid = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// TreeAppInstance get user tree node app instance.
|
||||
func (d *Dao) TreeAppInstance(c context.Context, treePaths []string) (treeAppInstances map[string][]*model.TreeAppInstance, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.TreeAppInstanceResponse{}
|
||||
fullTreePaths []string
|
||||
)
|
||||
|
||||
for _, treePath := range treePaths {
|
||||
fullTreePaths = append(fullTreePaths, d.getTreeFullPath(treePath))
|
||||
}
|
||||
|
||||
treeAppInstanceRequest := &model.TreeAppInstanceRequest{
|
||||
Paths: fullTreePaths,
|
||||
}
|
||||
|
||||
if req, err = d.newPlatformTreeRequest(c, http.MethodPost, _treeAppInstance+"?type=container", treeAppInstanceRequest); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) err(%v)", _treeRole, err)
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", _treeRole, res)
|
||||
return
|
||||
}
|
||||
return res.Data, nil
|
||||
}
|
||||
|
||||
func (d *Dao) treeToken(c context.Context, sessionID string) (authToken string, err error) {
|
||||
var (
|
||||
conn = d.mc.Get(c)
|
||||
item *memcache.Item
|
||||
)
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
if item, err = conn.Get(sessionID); err == nil {
|
||||
if err = json.Unmarshal(item.Value, &authToken); err != nil {
|
||||
log.Error("treePlatformToken json parse error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if authToken, err = d.authTree(c, sessionID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
item = &memcache.Item{Key: sessionID, Object: authToken, Flags: memcache.FlagJSON, Expiration: d.expire}
|
||||
d.tokenCacheSave(c, item)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (d *Dao) authTree(c context.Context, sessionID string) (authToken string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
tokenURL = d.c.ServiceTree.Host + _authURI
|
||||
res struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
)
|
||||
if req, err = d.newRequest(http.MethodGet, tokenURL, nil); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Cookie", _sessIDKey+"="+sessionID)
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
log.Error("d.Token url(%s) res($s) err(%v)", tokenURL, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
log.Error("Status url(%s) res(%v)", tokenURL, res)
|
||||
return
|
||||
}
|
||||
authToken = res.Data["token"].(string)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) newTreeRequest(c context.Context, method, uri, sessionID string, v interface{}) (req *http.Request, err error) {
|
||||
var authToken string
|
||||
if authToken, err = d.treeToken(c, sessionID); err != nil {
|
||||
return
|
||||
}
|
||||
if req, err = d.newRequest(method, d.c.ServiceTree.Host+uri, v); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set(_authHeader, authToken)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) treePlatformToken(c context.Context) (authToken string, err error) {
|
||||
var (
|
||||
conn = d.mc.Get(c)
|
||||
item *memcache.Item
|
||||
username = d.c.ServiceTree.Key
|
||||
secret = d.c.ServiceTree.Secret
|
||||
)
|
||||
defer conn.Close()
|
||||
if item, err = conn.Get(secret); err == nil {
|
||||
if err = json.Unmarshal(item.Value, &authToken); err != nil {
|
||||
log.Error("treePlatformToken json parse error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if authToken, err = d.authPlatformTree(c, username, secret); err != nil {
|
||||
return
|
||||
}
|
||||
item = &memcache.Item{Key: secret, Object: authToken, Flags: memcache.FlagJSON, Expiration: d.expire}
|
||||
d.tokenCacheSave(c, item)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) authPlatformTree(c context.Context, username, platformID string) (authToken string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
tokenURL = d.c.ServiceTree.Host + _authPlatformURI
|
||||
res struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
)
|
||||
|
||||
treePlatformTokenRequest := &model.TreePlatformTokenRequest{
|
||||
UserName: username,
|
||||
PlatformID: platformID,
|
||||
}
|
||||
|
||||
if req, err = d.newRequest(http.MethodPost, tokenURL, treePlatformTokenRequest); err != nil {
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
err = ecode.MerlinTreeRequestErr
|
||||
log.Error("d.Token url(%s) res($s) err(%v)", tokenURL, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != _treeOkCode {
|
||||
log.Error("Status url(%s) res(%v)", tokenURL, res)
|
||||
return
|
||||
}
|
||||
authToken = res.Data["token"].(string)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) newPlatformTreeRequest(c context.Context, method, uri string, v interface{}) (req *http.Request, err error) {
|
||||
var authToken string
|
||||
if authToken, err = d.treePlatformToken(c); err != nil {
|
||||
return
|
||||
}
|
||||
if req, err = d.newRequest(method, d.c.ServiceTree.Host+uri, v); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set(_authHeader, authToken)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) getTreeFullPath(path string) string {
|
||||
return _treeRootName + path
|
||||
}
|
1564
app/admin/ep/merlin/dao/tree_test.go
Normal file
1564
app/admin/ep/merlin/dao/tree_test.go
Normal file
File diff suppressed because it is too large
Load Diff
41
app/admin/ep/merlin/dao/wechat.go
Normal file
41
app/admin/ep/merlin/dao/wechat.go
Normal file
@ -0,0 +1,41 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/merlin/conf"
|
||||
"go-common/app/admin/ep/merlin/model"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_wechatGroup = "/ep/admin/saga/v2/wechat/appchat/send"
|
||||
)
|
||||
|
||||
//WeChatSendMessage We Chat Send Message
|
||||
func (d *Dao) WeChatSendMessage(c context.Context, msgSendReq *model.MsgSendReq) (msgSendRes *model.MsgSendRes, err error) {
|
||||
var (
|
||||
url = conf.Conf.WeChat.WeChatHost + _wechatGroup
|
||||
req *http.Request
|
||||
res = &model.MsgSendRes{}
|
||||
)
|
||||
msgSendRequest, _ := json.Marshal(msgSendReq)
|
||||
log.Info("url:(%s)", url)
|
||||
log.Info("msgSendRequest:(%s)", string(msgSendRequest))
|
||||
|
||||
if req, err = d.newRequest(http.MethodPost, url, msgSendReq); err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.AddWechatSend url(%s) res($s) error(%v)", url, res, err)
|
||||
return
|
||||
}
|
||||
msgSendRes = res
|
||||
rsp, _ := json.Marshal(msgSendRes)
|
||||
log.Info("wechat send message response :(%s)", string(rsp))
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user