package controller
import (
"context"
"encoding/json"
"fmt"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond-operator/api/v1alpha1"
"github.com/goodrain/rainbond-operator/util/constants"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/api/util"
"github.com/goodrain/rainbond/builder/parser/code"
"github.com/goodrain/rainbond/db"
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/pkg/component/k8s"
utils "github.com/goodrain/rainbond/util"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
"io"
"k8s.io/apimachinery/pkg/types"
"net/http"
"os"
"path"
"path/filepath"
"strconv"
"strings"
httputil "github.com/goodrain/rainbond/util/http"
)
type ClusterController struct {
}
func (c *ClusterController) GetClusterInfo(w http.ResponseWriter, r *http.Request) {
nodes, err := handler.GetClusterHandler().GetClusterInfo(r.Context())
if err != nil {
logrus.Errorf("get cluster info: %v", err)
httputil.ReturnError(r, w, 500, err.Error())
return
}
httputil.ReturnSuccess(r, w, nodes)
}
func (c *ClusterController) MavenSettingList(w http.ResponseWriter, r *http.Request) {
httputil.ReturnSuccess(r, w, handler.GetClusterHandler().MavenSettingList(r.Context()))
}
func (c *ClusterController) MavenSettingAdd(w http.ResponseWriter, r *http.Request) {
var set handler.MavenSetting
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &set, nil); !ok {
return
}
if err := handler.GetClusterHandler().MavenSettingAdd(r.Context(), &set); err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, &set)
}
func (c *ClusterController) MavenSettingUpdate(w http.ResponseWriter, r *http.Request) {
type SettingUpdate struct {
Content string `json:"content" validate:"required"`
}
var su SettingUpdate
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &su, nil); !ok {
return
}
set := &handler.MavenSetting{
Name: chi.URLParam(r, "name"),
Content: su.Content,
}
if err := handler.GetClusterHandler().MavenSettingUpdate(r.Context(), set); err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, set)
}
func (c *ClusterController) MavenSettingDelete(w http.ResponseWriter, r *http.Request) {
err := handler.GetClusterHandler().MavenSettingDelete(r.Context(), chi.URLParam(r, "name"))
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, nil)
}
func (c *ClusterController) MavenSettingDetail(w http.ResponseWriter, r *http.Request) {
setting, err := handler.GetClusterHandler().MavenSettingDetail(r.Context(), chi.URLParam(r, "name"))
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, setting)
}
func (c *ClusterController) BatchGetGateway(w http.ResponseWriter, r *http.Request) {
ns, err := handler.GetClusterHandler().BatchGetGateway(r.Context())
if err != nil {
logrus.Errorf(err.Error())
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, ns)
}
func (c *ClusterController) GetNamespace(w http.ResponseWriter, r *http.Request) {
content := r.FormValue("content")
format := r.FormValue("format")
if format == "detail" {
ns, err := handler.GetClusterHandler().GetNamespaceDetail(r.Context(), content)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, ns)
return
}
ns, err := handler.GetClusterHandler().GetNamespace(r.Context(), content)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, ns)
}
func (c *ClusterController) GetNamespaceResource(w http.ResponseWriter, r *http.Request) {
content := r.FormValue("content")
namespace := r.FormValue("namespace")
rs, err := handler.GetClusterHandler().GetNamespaceSource(r.Context(), content, namespace)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, rs)
}
func (c *ClusterController) ConvertResource(w http.ResponseWriter, r *http.Request) {
content := r.FormValue("content")
namespace := r.FormValue("namespace")
rs, err := handler.GetClusterHandler().GetNamespaceSource(r.Context(), content, namespace)
if err != nil {
err.Handle(r, w)
return
}
appsServices, err := handler.GetClusterHandler().ConvertResource(r.Context(), namespace, rs)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, appsServices)
}
func (c *ClusterController) ResourceImport(w http.ResponseWriter, r *http.Request) {
content := r.FormValue("content")
namespace := r.FormValue("namespace")
eid := r.FormValue("eid")
rs, err := handler.GetClusterHandler().GetNamespaceSource(r.Context(), content, namespace)
if err != nil {
err.Handle(r, w)
return
}
appsServices, err := handler.GetClusterHandler().ConvertResource(r.Context(), namespace, rs)
if err != nil {
err.Handle(r, w)
return
}
rri, err := handler.GetClusterHandler().ResourceImport(namespace, appsServices, eid)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, rri)
}
func (c *ClusterController) GetResource(w http.ResponseWriter, r *http.Request) {
var hr model.HandleResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &hr, nil); !ok {
return
}
rri, err := handler.GetClusterHandler().GetAppK8SResource(r.Context(), hr.Namespace, hr.AppID, hr.Name, hr.ResourceYaml, hr.Kind)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, rri)
}
func (c *ClusterController) AddResource(w http.ResponseWriter, r *http.Request) {
var hr model.AddHandleResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &hr, nil); !ok {
return
}
rri, err := handler.GetClusterHandler().AddAppK8SResource(r.Context(), hr.Namespace, hr.AppID, hr.ResourceYaml)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, rri)
}
func (c *ClusterController) UpdateResource(w http.ResponseWriter, r *http.Request) {
var hr model.HandleResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &hr, nil); !ok {
return
}
rri, err := handler.GetClusterHandler().UpdateAppK8SResource(r.Context(), hr.Namespace, hr.AppID, hr.Name, hr.ResourceYaml, hr.Kind)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, rri)
}
func (c *ClusterController) DeleteResource(w http.ResponseWriter, r *http.Request) {
var hr model.HandleResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &hr, nil); !ok {
return
}
if hr.State == model.CreateSuccess || hr.State == model.UpdateSuccess {
handler.GetClusterHandler().DeleteAppK8SResource(r.Context(), hr.Namespace, hr.AppID, hr.Name, hr.ResourceYaml, hr.Kind)
}
err := db.GetManager().K8sResourceDao().DeleteK8sResource(hr.AppID, hr.Name, hr.Kind)
if err != nil {
e := &util.APIHandleError{Code: 400, Err: fmt.Errorf("delete app k8s resource failure: %v", err)}
e.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, nil)
}
func (c *ClusterController) BatchDeleteResource(w http.ResponseWriter, r *http.Request) {
var req model.SyncResources
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil); !ok {
return
}
k8sResources, err := db.GetManager().K8sResourceDao().ListByAppID(req.AppID)
if err != nil {
e := &util.APIHandleError{Code: 400, Err: fmt.Errorf("get k8s resource failure: %v", err)}
e.Handle(r, w)
return
}
resourceMap := make(map[string][]dbmodel.K8sResource)
for _, resource := range k8sResources {
resourceList, ok := resourceMap[resource.Name]
if ok {
resourceMap[resource.Name] = append(resourceList, resource)
continue
}
resourceMap[resource.Name] = []dbmodel.K8sResource{resource}
}
var deleteResourcesID []uint
for _, hr := range req.K8sResources {
if hr.State == model.CreateSuccess || hr.State == model.UpdateSuccess {
handler.GetClusterHandler().DeleteAppK8SResource(r.Context(), hr.Namespace, hr.AppID, hr.Name, hr.ResourceYaml, hr.Kind)
nameResource, ok := resourceMap[hr.Name]
if ok {
for _, dbResource := range nameResource {
if dbResource.Kind == hr.Kind {
deleteResourcesID = append(deleteResourcesID, dbResource.ID)
}
}
}
}
}
err = db.GetManager().K8sResourceDao().DeleteK8sResourceByIDs(deleteResourcesID)
if err != nil {
e := &util.APIHandleError{Code: 400, Err: fmt.Errorf("delete app k8s resource failure: %v", err)}
e.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, nil)
}
func (c *ClusterController) SyncResource(w http.ResponseWriter, r *http.Request) {
var req model.SyncResources
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil); !ok {
return
}
resources, err := handler.GetClusterHandler().SyncAppK8SResources(r.Context(), &req)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, resources)
}
func (c *ClusterController) YamlResourceName(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
h, err := handler.GetClusterHandler().AppYamlResourceName(yr)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, h)
}
func (c *ClusterController) YamlResourceDetailed(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
h, err := handler.GetClusterHandler().AppYamlResourceDetailed(yr, false)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, h)
}
func (c *ClusterController) YamlResourceImport(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
ar, err := handler.GetClusterHandler().AppYamlResourceDetailed(yr, true)
if err != nil {
err.Handle(r, w)
return
}
ac, err := handler.GetClusterHandler().AppYamlResourceImport(yr.Namespace, yr.TenantID, yr.AppID, ar)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, ac)
}
func (c *ClusterController) CreateShellPod(w http.ResponseWriter, r *http.Request) {
var sp model.ShellPod
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &sp, nil); !ok {
return
}
pod, err := handler.GetClusterHandler().CreateShellPod(sp.RegionName)
if err != nil {
logrus.Error("create shell pod error:", err)
return
}
httputil.ReturnSuccess(r, w, pod)
}
func (c *ClusterController) DeleteShellPod(w http.ResponseWriter, r *http.Request) {
var sp model.ShellPod
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &sp, nil); !ok {
return
}
err := handler.GetClusterHandler().DeleteShellPod(sp.PodName)
if err != nil {
logrus.Error("delete shell pod error:", err)
return
}
httputil.ReturnSuccess(r, w, "")
}
func (c *ClusterController) RbdLog(w http.ResponseWriter, r *http.Request) {
podName := r.URL.Query().Get("pod_name")
follow, _ := strconv.ParseBool(r.URL.Query().Get("follow"))
err := handler.GetClusterHandler().RbdLog(w, r, podName, follow)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
return
}
func (c *ClusterController) GetRbdPods(w http.ResponseWriter, r *http.Request) {
res, err := handler.GetClusterHandler().GetRbdPods()
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, res)
}
func (c *ClusterController) ListRainbondComponents(w http.ResponseWriter, r *http.Request) {
components, err := handler.GetClusterHandler().ListRainbondComponents(r.Context())
if err != nil {
logrus.Errorf("get rainbond components error: %v", err)
httputil.ReturnError(r, w, 500, err.Error())
return
}
httputil.ReturnSuccess(r, w, components)
}
func (c *ClusterController) Upgrade(w http.ResponseWriter, r *http.Request) {
body := make(map[string]string)
err := json.NewDecoder(r.Body).Decode(&body)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
res := make([]string, 0)
for k, v := range body {
var cpt v1alpha1.RbdComponent
err := k8s.Default().K8sClient.Get(context.Background(),
types.NamespacedName{Namespace: utils.GetenvDefault("RBD_NAMESPACE", constants.Namespace), Name: k}, &cpt)
if err != nil {
res = append(res, fmt.Sprintf(`%s获取异常%s`, k, err.Error()))
continue
}
cpt.Spec.Image = v
logrus.Infof("upgrade [%s] image to [%s]", k, v)
err = k8s.Default().K8sClient.Update(context.Background(), &cpt)
if err != nil {
res = append(res, fmt.Sprintf(`%s更新异常%s`, k, err.Error()))
continue
}
}
httputil.ReturnSuccess(r, w, res)
}
func (c *ClusterController) ListUpgradeStatus(w http.ResponseWriter, r *http.Request) {
status, err := handler.GetClusterHandler().ListUpgradeStatus()
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, status)
}
func (c *ClusterController) ListPlugins(w http.ResponseWriter, r *http.Request) {
official, _ := strconv.ParseBool(r.URL.Query().Get("official"))
res, err := handler.GetClusterHandler().ListPlugins(official)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, res)
}
func (c *ClusterController) CreateRBDPlugin(w http.ResponseWriter, r *http.Request) {
var req model.CreateRBDPluginReq
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil); !ok {
return
}
if err := handler.GetClusterHandler().CreatePlugin(&req); err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, nil)
}
func (c *ClusterController) ListAbilities(w http.ResponseWriter, r *http.Request) {
res, err := handler.GetClusterHandler().ListAbilities()
if err != nil {
httputil.ReturnError(r, w, 400, err.Error())
return
}
var abilities []model.AbilityResp
for _, ability := range res {
abilities = append(abilities, model.AbilityResp{
Name: ability.GetName(),
Kind: ability.GetKind(),
APIVersion: ability.GetAPIVersion(),
AbilityID: handler.GetClusterHandler().GenerateAbilityID(&ability),
})
}
httputil.ReturnSuccess(r, w, abilities)
}
func (c *ClusterController) GetAbility(w http.ResponseWriter, r *http.Request) {
abilityID := chi.URLParam(r, "ability_id")
res, err := handler.GetClusterHandler().GetAbility(abilityID)
if err != nil {
httputil.ReturnError(r, w, 400, err.Error())
return
}
httputil.ReturnSuccess(r, w, res)
}
func (c *ClusterController) UpdateAbility(w http.ResponseWriter, r *http.Request) {
abilityID := chi.URLParam(r, "ability_id")
var req model.UpdateAbilityReq
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &req, nil); !ok {
return
}
if err := handler.GetClusterHandler().UpdateAbility(abilityID, req.Object); err != nil {
httputil.ReturnError(r, w, 400, err.Error())
return
}
httputil.ReturnSuccess(r, w, nil)
}
func (c *ClusterController) GetLangVersion(w http.ResponseWriter, r *http.Request) {
language := r.URL.Query().Get("language")
show := r.URL.Query().Get("show")
buildStrategy := normalizeLongVersionBuildStrategy(r.URL.Query().Get("build_strategy"))
versions, err := db.GetManager().LongVersionDao().ListVersionByLanguageAndStrategy(language, show, buildStrategy)
if err != nil {
httputil.ReturnBcodeError(r, w, fmt.Errorf("update lang version failure: %v", err))
return
}
httputil.ReturnSuccess(r, w, versions)
}
func (c *ClusterController) UpdateLangVersion(w http.ResponseWriter, r *http.Request) {
var lang model.UpdateLangVersion
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &lang, nil); !ok {
httputil.ReturnError(r, w, 400, "failed to parse parameters")
return
}
existing, err := getExistingLongVersion(&lang)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("get lang version failure: %v", err))
return
}
updatedVersion := buildLangVersionForUpdate(existing, &lang)
result, err := db.GetManager().LongVersionDao().DefaultLangVersion(updatedVersion.Lang, updatedVersion.Version, updatedVersion.BuildStrategy, updatedVersion.Show, updatedVersion.FirstChoice, &updatedVersion.IsAllowed)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("update lang version failure: %v", err))
return
}
httputil.ReturnSuccess(r, w, result)
}
func (c *ClusterController) CreateLangVersion(w http.ResponseWriter, r *http.Request) {
var lang model.UpdateLangVersion
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &lang, nil); !ok {
httputil.ReturnError(r, w, 400, "failed to parse parameters")
return
}
newVersion := buildLangVersionForCreate(&lang)
existing, err := db.GetManager().LongVersionDao().GetVersionByLanguageAndVersionAndStrategy(newVersion.Lang, newVersion.Version, newVersion.BuildStrategy)
if err != nil && err != gorm.ErrRecordNotFound {
httputil.ReturnError(r, w, 400, fmt.Sprintf("get lang version failure: %v", err))
return
}
if err == gorm.ErrRecordNotFound {
created, err := db.GetManager().LongVersionDao().CreateLangVersion(newVersion.Lang, newVersion.Version, newVersion.EventID, newVersion.FileName, newVersion.BuildStrategy, newVersion.Show, newVersion.IsAllowed)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("create lang version failure: %v", err))
return
}
if created.EventID != "" {
sourceDir := path.Join(LSUploadPath, created.EventID)
destinationDir := path.Join(BaseUploadPath, created.EventID)
err = copyDirectory(sourceDir, destinationDir)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("rename lang version failure: %v", err))
return
}
}
httputil.ReturnSuccess(r, w, created)
return
}
_ = existing
httputil.ReturnSuccess(r, w, "exist")
return
}
func (c *ClusterController) DeleteLangVersion(w http.ResponseWriter, r *http.Request) {
var lang model.UpdateLangVersion
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &lang, nil); !ok {
httputil.ReturnError(r, w, 400, "failed to parse parameters")
return
}
eventID, err := db.GetManager().LongVersionDao().DeleteLangVersion(lang.Lang, lang.Version, normalizeLongVersionBuildStrategyPtr(lang.BuildStrategy))
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("delete lang version failure: %v", err))
return
}
if eventID != "" {
err = os.RemoveAll(path.Join(BaseUploadPath, eventID))
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("delete lang version pack failure: %v", err))
return
}
}
httputil.ReturnSuccess(r, w, "删除成功")
}
func getExistingLongVersion(req *model.UpdateLangVersion) (*dbmodel.EnterpriseLanguageVersion, error) {
if req.BuildStrategy != nil {
return db.GetManager().LongVersionDao().GetVersionByLanguageAndVersionAndStrategy(req.Lang, req.Version, normalizeLongVersionBuildStrategyPtr(req.BuildStrategy))
}
return db.GetManager().LongVersionDao().GetVersionByLanguageAndVersion(req.Lang, req.Version)
}
func buildLangVersionForCreate(req *model.UpdateLangVersion) *dbmodel.EnterpriseLanguageVersion {
return &dbmodel.EnterpriseLanguageVersion{
Lang: req.Lang,
Version: req.Version,
EventID: req.EventID,
FileName: req.FileName,
Show: req.Show,
FirstChoice: req.FirstChoice,
BuildStrategy: normalizeLongVersionBuildStrategyPtr(req.BuildStrategy),
IsAllowed: normalizeLongVersionIsAllowed(req.IsAllowed, true),
}
}
func buildLangVersionForUpdate(existing *dbmodel.EnterpriseLanguageVersion, req *model.UpdateLangVersion) *dbmodel.EnterpriseLanguageVersion {
version := *existing
version.Show = req.Show
version.FirstChoice = req.FirstChoice
version.BuildStrategy = normalizeLongVersionBuildStrategy(version.BuildStrategy)
if req.BuildStrategy != nil {
version.BuildStrategy = normalizeLongVersionBuildStrategyPtr(req.BuildStrategy)
}
version.IsAllowed = normalizeLongVersionIsAllowed(req.IsAllowed, version.IsAllowed)
return &version
}
func normalizeLongVersionBuildStrategyPtr(buildStrategy *string) string {
if buildStrategy == nil {
return dbmodel.LongVersionBuildStrategySlug
}
return normalizeLongVersionBuildStrategy(*buildStrategy)
}
func normalizeLongVersionBuildStrategy(buildStrategy string) string {
buildStrategy = strings.TrimSpace(buildStrategy)
if buildStrategy == "" {
return dbmodel.LongVersionBuildStrategySlug
}
return buildStrategy
}
func normalizeLongVersionIsAllowed(isAllowed *bool, defaultValue bool) bool {
if isAllowed == nil {
return defaultValue
}
return *isAllowed
}
func copyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(dst)
if err != nil {
return err
}
defer destinationFile.Close()
_, err = io.Copy(destinationFile, sourceFile)
if err != nil {
return err
}
err = destinationFile.Sync()
if err != nil {
return err
}
return nil
}
func copyDirectory(srcDir, dstDir string) error {
err := os.MkdirAll(dstDir, os.ModePerm)
if err != nil {
return err
}
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
relativePath, err := filepath.Rel(srcDir, path)
if err != nil {
return err
}
dstPath := filepath.Join(dstDir, relativePath)
if info.IsDir() {
return os.MkdirAll(dstPath, info.Mode())
}
if info.Mode()&os.ModeSymlink != 0 {
return fmt.Errorf("skipping symbolic link: %s", path)
}
return copyFile(path, dstPath)
})
return err
}
func (c *ClusterController) GetRegionStatus(w http.ResponseWriter, r *http.Request) {
token := chi.URLParam(r, "token")
if token != os.Getenv("HELM_TOKEN") {
httputil.ReturnError(r, w, 400, "failed to verify token")
return
}
regionInfo, err := handler.GetClusterHandler().GetClusterRegionStatus()
if err != nil {
httputil.ReturnError(r, w, 400, err.Error())
return
}
httputil.ReturnSuccess(r, w, regionInfo)
}
func (c *ClusterController) SetOverScore(w http.ResponseWriter, r *http.Request) {
var overScore model.OverScore
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &overScore, nil); !ok {
httputil.ReturnError(r, w, 400, "failed to parse parameters")
return
}
err := db.GetManager().OverScoreDao().UpdateOverScoreRat(overScore.OverScoreRate)
if err != nil {
httputil.ReturnError(r, w, 400, fmt.Sprintf("update over score failure: %v", err))
return
}
return
}
func (c *ClusterController) ListCNBFrameworks(w http.ResponseWriter, r *http.Request) {
lang := r.URL.Query().Get("lang")
if lang == "" {
lang = "nodejs"
}
frameworks := code.GetSupportedFrameworks(lang)
httputil.ReturnSuccess(r, w, frameworks)
}