show service name
This commit is contained in:
parent
3dad446d95
commit
9eb3fb3fce
8
go.mod
8
go.mod
|
|
@ -20,21 +20,20 @@ require (
|
|||
k8s.io/client-go v0.26.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/goccy/go-json v0.10.0
|
||||
github.com/thoas/go-funk v0.9.3
|
||||
)
|
||||
require github.com/thoas/go-funk v0.9.3
|
||||
|
||||
require (
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/imdario/mergo v0.3.6 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
|
|
@ -46,6 +45,7 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/net v0.6.0 // indirect
|
||||
|
|
|
|||
3
go.sum
3
go.sum
|
|
@ -142,6 +142,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
|||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
|
|
@ -190,6 +192,7 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
|
|||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
|
|
|
|||
5
main.go
5
main.go
|
|
@ -32,7 +32,8 @@ func main() {
|
|||
fp, _ := fs.Sub(f, "static")
|
||||
r.StaticFS("/static", http.FS(fp))
|
||||
|
||||
r.GET("/app", m.JWTAuthMiddleware, m.AppPage)
|
||||
r.GET("/index", m.JWTAuthMiddleware, m.AppPage)
|
||||
r.GET("/apps", m.JWTAuthMiddleware, m.GetAppsController)
|
||||
r.POST("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
|
||||
r.PUT("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
|
||||
r.DELETE("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
|
||||
|
|
@ -64,6 +65,6 @@ func Test(c *gin.Context) {
|
|||
c.SetCookie("Authorization", "Bearer "+token, 0, "", "", false, false)
|
||||
c.Header("Authorization", "Bearer "+token)
|
||||
c.Header("Cache-Control", "no-store")
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/app")
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/index")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,18 @@ func (a *AppModel) Fill() error {
|
|||
}
|
||||
|
||||
func (a *AppModel) Update() error {
|
||||
if a.SvcName == "" {
|
||||
a.SvcName = "svc"
|
||||
}
|
||||
db := DB()
|
||||
db.Save(a)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AppModel) Create() error {
|
||||
if a.SvcName == "" {
|
||||
a.SvcName = "svc"
|
||||
}
|
||||
db := DB()
|
||||
db.Create(a)
|
||||
return nil
|
||||
|
|
@ -66,13 +72,13 @@ func (a *AppModel) ContainerName() string {
|
|||
|
||||
func (a *AppModel) ServiceName() string {
|
||||
if strings.TrimSpace(a.SvcName) != "" {
|
||||
return a.SvcName
|
||||
return fmt.Sprintf("%s-%s", a.NamePrefix(), a.SvcName)
|
||||
}
|
||||
return a.DefaultServiceName()
|
||||
}
|
||||
|
||||
func (a *AppModel) DefaultServiceName() string {
|
||||
return fmt.Sprintf("%s-service", a.NamePrefix())
|
||||
return fmt.Sprintf("%s-svc", a.NamePrefix())
|
||||
}
|
||||
|
||||
func (a *AppModel) DeploymentName() string {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
package k8s_manager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/thoas/go-funk"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AppViewModel struct {
|
||||
*AppModel
|
||||
Status string
|
||||
Status string
|
||||
ServiceDisplayName string
|
||||
}
|
||||
|
||||
type AppsViewModel struct {
|
||||
|
|
@ -19,20 +20,32 @@ type AppsViewModel struct {
|
|||
Apps []AppViewModel
|
||||
}
|
||||
|
||||
func statusString(status *v1.DeploymentStatus, err error) string {
|
||||
func statusString(a *AppViewModel) string {
|
||||
_, err := K.GetDeploymentStatus(a.AppModel.DeploymentName())
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
return "Stopped"
|
||||
return "Halt"
|
||||
}
|
||||
return err.Error()
|
||||
} else {
|
||||
if status.AvailableReplicas > 0 {
|
||||
return "Running"
|
||||
} else {
|
||||
return "Error"
|
||||
pod := K.GetPodFromDeployment(a.AppModel.DeploymentName())
|
||||
if pod == nil {
|
||||
return "Internal Error 1."
|
||||
}
|
||||
if len(pod.Status.ContainerStatuses) == 0 {
|
||||
return "Internal Error 2."
|
||||
}
|
||||
containerState := pod.Status.ContainerStatuses[0].State
|
||||
if containerState.Waiting != nil {
|
||||
return containerState.Waiting.Reason
|
||||
} else if containerState.Running != nil {
|
||||
return "Start at " + containerState.Running.StartedAt.String()
|
||||
} else if containerState.Terminated != nil {
|
||||
b, _ := json.Marshal(containerState.Terminated)
|
||||
return "Terminated " + string(b)
|
||||
}
|
||||
return pod.Status.Message + "," + pod.Status.Reason
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func AppPage(c *gin.Context) {
|
||||
|
|
@ -40,8 +53,8 @@ func AppPage(c *gin.Context) {
|
|||
appsvm := funk.Map(GetApps(username), func(a AppModel) AppViewModel { return AppViewModel{AppModel: &a} }).([]AppViewModel)
|
||||
for i := range appsvm {
|
||||
a := &appsvm[i]
|
||||
d, e := K.GetDeploymentStatus(a.AppModel.DeploymentName())
|
||||
a.Status = statusString(d, e)
|
||||
a.Status = statusString(a)
|
||||
a.ServiceDisplayName = a.ServiceName()
|
||||
}
|
||||
vm := &AppsViewModel{
|
||||
Username: username,
|
||||
|
|
@ -90,3 +103,9 @@ func CreateUpdateDeleteApp(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetAppsController(c *gin.Context) {
|
||||
username := c.MustGet("username").(string)
|
||||
apps := GetApps(username)
|
||||
c.JSON(http.StatusOK, apps)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -21,7 +22,8 @@ type K8sClient struct {
|
|||
|
||||
func CreateClient() *K8sClient {
|
||||
var err error
|
||||
config, err := rest.InClusterConfig()
|
||||
// config, err := rest.InClusterConfig()
|
||||
config, err := clientcmd.BuildConfigFromFlags("", os.Getenv("KUBE_CONFIG"))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("InClusterConfig")
|
||||
return nil
|
||||
|
|
@ -64,6 +66,10 @@ func (c *K8sClient) UpdateDeployment(app *AppModel) {
|
|||
var rep int32 = 1
|
||||
labelKey, labelValue := app.GetLabel()
|
||||
labels := map[string]string{labelKey: labelValue}
|
||||
podLabels := map[string]string{
|
||||
labelKey: labelValue,
|
||||
"cg-deployment": app.DeploymentName(),
|
||||
}
|
||||
deployment := &appv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: app.DeploymentName(),
|
||||
|
|
@ -76,7 +82,7 @@ func (c *K8sClient) UpdateDeployment(app *AppModel) {
|
|||
},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: labels,
|
||||
Labels: podLabels,
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{{
|
||||
|
|
@ -160,6 +166,24 @@ func (c *K8sClient) DeleteApp(app *AppModel) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *K8sClient) DeleteAppService(app *AppModel) {
|
||||
k, v := app.GetLabel()
|
||||
label := labels.FormatLabels(map[string]string{k: v})
|
||||
svcs, err := c.CoreV1().Services(c.Namespace).List(context.Background(), metav1.ListOptions{
|
||||
LabelSelector: label,
|
||||
})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("DeleteAppService Get")
|
||||
return
|
||||
}
|
||||
for _, svc := range svcs.Items {
|
||||
err := c.CoreV1().Services(c.Namespace).Delete(context.Background(), svc.Name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("name", svc.Name).Error("Delete svc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *K8sClient) DeleteDeployment(depName string) {
|
||||
if !c.DeploymentExists(depName) {
|
||||
return
|
||||
|
|
@ -188,3 +212,17 @@ func (c *K8sClient) GetAllServices() *v1.ServiceList {
|
|||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *K8sClient) GetPodFromDeployment(deploymentName string) *v1.Pod {
|
||||
label := labels.FormatLabels(map[string]string{"cg-deployment": deploymentName})
|
||||
pods, err := c.CoreV1().Pods(c.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: label})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("GetPodFromDeployment")
|
||||
return nil
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
log.WithField("label", label).Error("GetPodFromDeployment no such label pod.")
|
||||
return nil
|
||||
}
|
||||
return &pods.Items[0]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
<th>启动命令</th>
|
||||
<th>环境变量</th>
|
||||
<th>状态</th>
|
||||
<th>服务名</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
<td class="app-field-cmd"> {{ $v.Command }}</td>
|
||||
<td class="app-field-env"> {{ $v.Env }}</td>
|
||||
<td class="app-field-status" id="app-status-{{ $v.Id }}"> {{ $v.Status }} </td>
|
||||
<td class="app-field-svc"> {{ $v.ServiceDisplayName }} </td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-success" onclick="startApp('{{$v.Id}}')">启动</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue