From 9eb3fb3fcef411101cd8a54c8f52361ce0c127b5 Mon Sep 17 00:00:00 2001 From: w-mj Date: Thu, 16 Feb 2023 14:54:44 +0800 Subject: [PATCH] show service name --- go.mod | 8 ++++---- go.sum | 3 +++ main.go | 5 +++-- src/app_model.go | 10 ++++++++-- src/app_viewmodel.go | 41 ++++++++++++++++++++++++++++----------- src/k8s_client.go | 44 +++++++++++++++++++++++++++++++++++++++--- template/app_view.html | 2 ++ 7 files changed, 91 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index aac74c7..f97c578 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 7f17669..4d79a9d 100644 --- a/go.sum +++ b/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= diff --git a/main.go b/main.go index b5158ac..003e17d 100644 --- a/main.go +++ b/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") } } diff --git a/src/app_model.go b/src/app_model.go index d58d6aa..71e7a03 100644 --- a/src/app_model.go +++ b/src/app_model.go @@ -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 { diff --git a/src/app_viewmodel.go b/src/app_viewmodel.go index be09714..5814975 100644 --- a/src/app_viewmodel.go +++ b/src/app_viewmodel.go @@ -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) +} diff --git a/src/k8s_client.go b/src/k8s_client.go index 66b30ff..fd71439 100644 --- a/src/k8s_client.go +++ b/src/k8s_client.go @@ -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] +} diff --git a/template/app_view.html b/template/app_view.html index e9acd07..cc379e0 100644 --- a/template/app_view.html +++ b/template/app_view.html @@ -34,6 +34,7 @@ 启动命令 环境变量 状态 + 服务名 操作 @@ -48,6 +49,7 @@ {{ $v.Command }} {{ $v.Env }} {{ $v.Status }} + {{ $v.ServiceDisplayName }}