diff --git a/api/api/api_interface.go b/api/api/api_interface.go index c3bbbd8e1..7880b11eb 100644 --- a/api/api/api_interface.go +++ b/api/api/api_interface.go @@ -142,7 +142,12 @@ type Gatewayer interface { RuleConfig(w http.ResponseWriter, r *http.Request) } -// ThirdPartyServicer is a interface for defining methods for third-party service. +// ThirdPartyServicer is an interface for defining methods for third-party service. type ThirdPartyServicer interface { Endpoints(w http.ResponseWriter, r *http.Request) } + +// Labeler is an interface for defining methods to get information of labels. +type Labeler interface { + Labels(w http.ResponseWriter, r *http.Request) +} diff --git a/api/api_routers/version2/v2Routers.go b/api/api_routers/version2/v2Routers.go index 10e96cf34..86b9c45e1 100644 --- a/api/api_routers/version2/v2Routers.go +++ b/api/api_routers/version2/v2Routers.go @@ -226,6 +226,7 @@ func (v2 *V2) clusterRouter() chi.Router { func (v2 *V2) resourcesRouter() chi.Router { r := chi.NewRouter() + r.Get("/labels", controller.GetManager().Labels) r.Post("/tenants", controller.GetManager().TenantResources) r.Post("/services", controller.GetManager().ServiceResources) r.Get("/tenants/sum", controller.GetManager().SumTenants) diff --git a/api/controller/app.go b/api/controller/app.go index dbf5563d8..8ac4713b6 100644 --- a/api/controller/app.go +++ b/api/controller/app.go @@ -1,6 +1,7 @@ package controller import ( + "encoding/json" "fmt" "net/http" diff --git a/api/controller/labels.go b/api/controller/labels.go new file mode 100644 index 000000000..2b1515c14 --- /dev/null +++ b/api/controller/labels.go @@ -0,0 +1,42 @@ +// RAINBOND, Application Management Platform +// Copyright (C) 2014-2017 Goodrain Co., Ltd. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. For any non-GPL usage of Rainbond, +// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd. +// must be obtained first. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package controller + +import ( + "github.com/goodrain/rainbond/cmd/api/option" + httputil "github.com/goodrain/rainbond/util/http" + "net/http" +) + +// LabelController implements Labeler. +type LabelController struct { + optconfig *option.Config +} + +// Labels - get -> list labels +func (l *LabelController) Labels(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case "GET": + l.listLabels(w, r) + } +} + +func (l *LabelController) listLabels(w http.ResponseWriter, r *http.Request) { + httputil.ReturnSuccess(r, w, l.optconfig.EnableFeature) +} diff --git a/api/controller/manager.go b/api/controller/manager.go index 21933b42f..45475c5ca 100644 --- a/api/controller/manager.go +++ b/api/controller/manager.go @@ -48,6 +48,7 @@ type V2Manager interface { api.AppInterface api.Gatewayer api.ThirdPartyServicer + api.Labeler } var defaultV2Manager V2Manager @@ -79,5 +80,7 @@ func NewManager(conf option.Config, statusCli *client.AppRuntimeSyncClient) (*V2 v2r.GatewayStruct.MQClient = mqClient v2r.GatewayStruct.cfg = &conf + + v2r.LabelController.optconfig = &conf return &v2r, nil } diff --git a/api/controller/resources.go b/api/controller/resources.go index 1511bd951..cb09fcff9 100644 --- a/api/controller/resources.go +++ b/api/controller/resources.go @@ -41,7 +41,7 @@ import ( "github.com/jinzhu/gorm" "github.com/pquerna/ffjson/ffjson" "github.com/renstorm/fuzzysearch/fuzzy" - "github.com/thedevsaddam/govalidator" + validator "github.com/thedevsaddam/govalidator" ) //V2Routes v2Routes @@ -52,6 +52,7 @@ type V2Routes struct { AppStruct GatewayStruct ThirdPartyServiceController + LabelController } //Show test @@ -600,14 +601,12 @@ func (t *TenantStruct) CreateService(w http.ResponseWriter, r *http.Request) { // schema: // "$ref": "#/responses/commandResponse" // description: 统一返回格式 - logrus.Debugf("trans create service service") var ss api_model.ServiceStruct body, err := ioutil.ReadAll(r.Body) if err != nil { httputil.ReturnError(r, w, 500, err.Error()) return } - err = ffjson.Unmarshal(body, &ss) if err != nil { httputil.ReturnError(r, w, 500, err.Error()) @@ -1615,7 +1614,7 @@ func (t *TenantStruct) AddProbe(w http.ResponseWriter, r *http.Request) { tspD.FailureThreshold = tsp.FailureThreshold tspD.HTTPHeader = tsp.HTTPHeader tspD.InitialDelaySecond = tsp.InitialDelaySecond - tspD.IsUsed = tsp.IsUsed + tspD.IsUsed = &tsp.IsUsed tspD.Mode = tsp.Mode tspD.Path = tsp.Path tspD.PeriodSecond = tsp.PeriodSecond @@ -1665,7 +1664,7 @@ func (t *TenantStruct) UpdateProbe(w http.ResponseWriter, r *http.Request) { tspD.FailureThreshold = tsp.FailureThreshold tspD.HTTPHeader = tsp.HTTPHeader tspD.InitialDelaySecond = tsp.InitialDelaySecond - tspD.IsUsed = tsp.IsUsed + tspD.IsUsed = &tsp.IsUsed tspD.Mode = tsp.Mode tspD.Path = tsp.Path tspD.PeriodSecond = tsp.PeriodSecond diff --git a/api/handler/gateway_action.go b/api/handler/gateway_action.go index 28aa13913..84307302d 100644 --- a/api/handler/gateway_action.go +++ b/api/handler/gateway_action.go @@ -54,7 +54,12 @@ func (g *GatewayAction) AddHTTPRule(req *apimodel.AddHTTPRuleStruct) (string, er ServiceID: req.ServiceID, ContainerPort: req.ContainerPort, Domain: req.Domain, - Path: req.Path, + Path: func() string { + if !strings.HasPrefix(req.Path, "/") { + return "/" + req.Path + } + return req.Path + }(), Header: req.Header, Cookie: req.Cookie, Weight: req.Weight, @@ -164,7 +169,12 @@ func (g *GatewayAction) UpdateHTTPRule(req *apimodel.UpdateHTTPRuleStruct) (stri if req.Domain != "" { rule.Domain = req.Domain } - rule.Path = req.Path + rule.Path = func() string { + if !strings.HasPrefix(req.Path, "/") { + return "/" + req.Path + } + return req.Path + }() rule.Header = req.Header rule.Cookie = req.Cookie rule.Weight = req.Weight @@ -611,6 +621,12 @@ func (g *GatewayAction) RuleConfig(req *apimodel.RuleConfigReq) error { }) setheaders := make(map[string]string) for _, item := range req.Body.SetHeaders { + if strings.TrimSpace(item.Key) == ""{ + continue + } + if strings.TrimSpace(item.Value) == "" { + item.Value = "empty" + } // filter same key setheaders["set-header-"+item.Key] = item.Value } diff --git a/api/handler/third_party_service_handler.go b/api/handler/third_party_service_handler.go index f97e1d868..1c00f9fa0 100644 --- a/api/handler/third_party_service_handler.go +++ b/api/handler/third_party_service_handler.go @@ -100,9 +100,9 @@ func (t *ThirdPartyServiceHanlder) ListEndpoints(sid string) ([]*model.EndpointR for _, item := range endpoints { m[item.UUID] = &model.EndpointResp{ EpID: item.UUID, - IP: func(ip string, port int) string { - if port != 0 { - return fmt.Sprintf("%s:%d", ip, port) + IP: func(ip string, p int) string { + if p != 0 { + return fmt.Sprintf("%s:%d", ip, p) } return ip }(item.IP, item.Port), @@ -126,13 +126,8 @@ func (t *ThirdPartyServiceHanlder) ListEndpoints(sid string) ([]*model.EndpointR continue } m[item.Uuid] = &model.EndpointResp{ - EpID: item.Uuid, - IP: func(ip string, port int32) string { - if port != 0 { - return fmt.Sprintf("%s:%d", ip, port) - } - return ip - }(item.Ip, item.Port), + EpID: item.Uuid, + IP: item.Ip, Status: item.Status, IsOnline: true, IsStatic: false, diff --git a/api/region/service.go b/api/region/service.go index 40a4ef4a1..aa21316a9 100644 --- a/api/region/service.go +++ b/api/region/service.go @@ -21,7 +21,6 @@ package region import ( "bytes" "fmt" - "github.com/goodrain/rainbond/api/model" "github.com/goodrain/rainbond/api/util" dbmodel "github.com/goodrain/rainbond/db/model" diff --git a/api/region/types.go b/api/region/types.go index 089a066ed..f32e766a7 100644 --- a/api/region/types.go +++ b/api/region/types.go @@ -25,8 +25,9 @@ type ServiceDeployInfo struct { Deployment string `protobuf:"bytes,3,opt,name=deployment,proto3" json:"deployment,omitempty"` Pods map[string]string `protobuf:"bytes,4,rep,name=pods,proto3" json:"pods,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Services map[string]string `protobuf:"bytes,5,rep,name=services,proto3" json:"services,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Secrets map[string]string `protobuf:"bytes,6,rep,name=secrets,proto3" json:"secrets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Ingresses map[string]string `protobuf:"bytes,7,rep,name=ingresses,proto3" json:"ingresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Replicatset map[string]string `protobuf:"bytes,8,rep,name=replicatset,proto3" json:"replicatset,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + Endpoints map[string]string `protobuf:"bytes,6,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Secrets map[string]string `protobuf:"bytes,7,rep,name=secrets,proto3" json:"secrets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Ingresses map[string]string `protobuf:"bytes,8,rep,name=ingresses,proto3" json:"ingresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Replicatset map[string]string `protobuf:"bytes,9,rep,name=replicatset,proto3" json:"replicatset,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` } diff --git a/builder/exector/exector.go b/builder/exector/exector.go index 3303259b2..ad2f8c7e7 100644 --- a/builder/exector/exector.go +++ b/builder/exector/exector.go @@ -136,11 +136,11 @@ func (e *exectorManager) AddTask(task *pb.TaskMessage) error { } func (e *exectorManager) exec(task *pb.TaskMessage) error { - creater, ok := workerCreaterList[task.TaskType] + creator, ok := workerCreaterList[task.TaskType] if !ok { return fmt.Errorf("`%s` tasktype can't support", task.TaskType) } - worker, err := creater(task.TaskBody, e) + worker, err := creator(task.TaskBody, e) if err != nil { logrus.Errorf("create worker for builder error.%s", err) return err diff --git a/builder/exector/export_app.go b/builder/exector/export_app.go index cf10e70a7..5188af708 100644 --- a/builder/exector/export_app.go +++ b/builder/exector/export_app.go @@ -19,16 +19,14 @@ package exector import ( - "time" - "fmt" "io/ioutil" "os" "os/exec" + "regexp" "strconv" "strings" - - "regexp" + "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/client" @@ -39,7 +37,7 @@ import ( "github.com/goodrain/rainbond/util" "github.com/pkg/errors" "github.com/tidwall/gjson" - "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v2" ) var re = regexp.MustCompile(`\s`) @@ -270,7 +268,7 @@ func (i *ExportApp) exportImage(serviceDir string, app gjson.Result) error { } //change save app image name imageName := sources.ImageNameWithNamespaceHandle(image) - saveImageName := fmt.Sprintf("%s/%s:%s", "goodrain.me", imageName.Name, imageName.Tag) + saveImageName := fmt.Sprintf("%s/%s:%s", builder.REGISTRYDOMAIN, imageName.Name, imageName.Tag) if err := sources.ImageTag(i.DockerClient, image, saveImageName, i.Logger, 2); err != nil { return err } @@ -351,7 +349,7 @@ func (i *ExportApp) savePlugins() error { } //change save app image name imageName := sources.ImageNameWithNamespaceHandle(image) - saveImageName := fmt.Sprintf("%s/%s:%s", "goodrain.me", imageName.Name, imageName.Tag) + saveImageName := fmt.Sprintf("%s/%s:%s", builder.REGISTRYDOMAIN, imageName.Name, imageName.Tag) if err := sources.ImageTag(i.DockerClient, image, saveImageName, i.Logger, 2); err != nil { return err } @@ -498,6 +496,7 @@ type Service struct { Volumes []string `yaml:"volumes,omitempty"` Command string `yaml:"command,omitempty"` Environment map[string]string `yaml:"environment,omitempty"` + DependsOn []string `yaml:"depends_on,omitempty"` Loggin struct { Driver string `yaml:"driver,omitempty"` Options struct { @@ -525,6 +524,7 @@ func (i *ExportApp) buildDockerComposeYaml() error { for _, app := range apps { image := app.Get("image").String() + shareImage := app.Get("share_image").String() appName := app.Get("service_cname").String() appName = unicode2zh(appName) volumes := make([]string, 0, 3) @@ -542,8 +542,10 @@ func (i *ExportApp) buildDockerComposeYaml() error { volumes = append(volumes, fmt.Sprintf("%s:%s", volumeName, volumePath)) } + lang := app.Get("language").String() // 如果该组件是源码方式部署,则挂载slug文件到runner容器内 - if checkIsRunner(image) { + if lang != "dockerfile" && checkIsRunner(image) { + shareImage = image shareSlugPath := app.Get("share_slug_path").String() tarFileName := buildToLinuxFileName(shareSlugPath) volume := fmt.Sprintf("__GROUP_DIR__/%s/%s:/tmp/slug/slug.tgz", appName, tarFileName) @@ -552,8 +554,10 @@ func (i *ExportApp) buildDockerComposeYaml() error { } // 处理环境变量 - for k, v := range app.Get("service_env_map_list").Map() { - envs[k] = v.String() + for _, item := range app.Get("service_env_map_list").Array() { + key := item.Get("attr_name").String() + value := item.Get("attr_value").String() + envs[key] = value } for _, item := range app.Get("service_connect_info_map_list").Array() { @@ -562,6 +566,7 @@ func (i *ExportApp) buildDockerComposeYaml() error { envs[key] = value } + var depServices []string // 如果该app依赖了另了个app-b,则把app-b中所有公开环境变量注入到该app for _, item := range app.Get("dep_service_map_list").Array() { serviceKey := item.Get("dep_service_key").String() @@ -569,10 +574,14 @@ func (i *ExportApp) buildDockerComposeYaml() error { for k, v := range depEnvs { envs[k] = v } + + if svc := i.getDependedService(serviceKey, &apps); svc != "" { + depServices = append(depServices, svc) + } } service := &Service{ - Image: image, + Image: shareImage, ContainerName: appName, Restart: "always", NetworkMode: "host", @@ -583,6 +592,9 @@ func (i *ExportApp) buildDockerComposeYaml() error { service.Loggin.Driver = "json-file" service.Loggin.Options.MaxSize = "5m" service.Loggin.Options.MaxFile = "2" + if depServices != nil && len(depServices) > 0 { + service.DependsOn = depServices + } y.Services[appName] = service } @@ -607,7 +619,7 @@ func (i *ExportApp) buildDockerComposeYaml() error { func (i *ExportApp) getPublicEnvByKey(serviceKey string, apps *[]gjson.Result) map[string]string { envs := make(map[string]string, 5) for _, app := range *apps { - appKey := app.Get("service_key").String() + appKey := app.Get("service_share_uuid").String() if appKey == serviceKey { for _, item := range app.Get("service_connect_info_map_list").Array() { key := item.Get("attr_name").String() @@ -621,6 +633,15 @@ func (i *ExportApp) getPublicEnvByKey(serviceKey string, apps *[]gjson.Result) m return envs } +func (i *ExportApp) getDependedService(key string, apps *[]gjson.Result) string { + for _, app := range *apps { + if key == app.Get("service_share_uuid").String() { + return app.Get("service_cname").String() + } + } + return "" +} + func (i *ExportApp) buildStartScript() error { if err := exec.Command("cp", "/src/export-app/run.sh", i.SourceDir).Run(); err != nil { err = errors.New("Failed to generate start script to: " + i.SourceDir) diff --git a/builder/exector/export_app_test.go b/builder/exector/export_app_test.go new file mode 100644 index 000000000..658aa5fae --- /dev/null +++ b/builder/exector/export_app_test.go @@ -0,0 +1,35 @@ +// RAINBOND, Application Management Platform +// Copyright (C) 2014-2017 Goodrain Co., Ltd. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. For any non-GPL usage of Rainbond, +// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd. +// must be obtained first. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package exector + +import ( + "github.com/goodrain/rainbond/event" + "testing" +) + +func TestExportApp_parseApps(t *testing.T) { + e := &ExportApp{ + SourceDir: "./", + Logger: event.GetTestLogger(), + } + err := e.buildDockerComposeYaml() + if err != nil { + t.Error(err) + } +} diff --git a/builder/exector/import_app.go b/builder/exector/import_app.go index d6989de88..01730f3b9 100644 --- a/builder/exector/import_app.go +++ b/builder/exector/import_app.go @@ -32,6 +32,7 @@ import ( simplejson "github.com/bitly/go-simplejson" "github.com/docker/docker/client" "github.com/goodrain/rainbond/api/model" + "github.com/goodrain/rainbond/builder" "github.com/goodrain/rainbond/builder/sources" "github.com/goodrain/rainbond/db" "github.com/goodrain/rainbond/event" @@ -388,7 +389,7 @@ func (i *ImportApp) importPlugins() error { // 上传之前先要根据新的仓库地址修改镜像名 image := i.oldPluginPath[plugin.Get("service_key").String()] imageName := sources.ImageNameWithNamespaceHandle(image) - saveImageName := fmt.Sprintf("%s/%s:%s", "goodrain.me", imageName.Name, imageName.Tag) + saveImageName := fmt.Sprintf("%s/%s:%s", builder.REGISTRYDOMAIN, imageName.Name, imageName.Tag) newImageName := plugin.Get("share_image").String() if err := sources.ImageTag(i.DockerClient, saveImageName, newImageName, i.Logger, 2); err != nil { return fmt.Errorf("change plugin image tag(%s => %s) error %s", saveImageName, newImageName, err.Error()) @@ -440,7 +441,7 @@ func (i *ImportApp) loadApps() error { pass := app.Get("service_image.hub_password").String() // 上传之前先要根据新的仓库地址修改镜像名 image := app.Get("share_image").String() - if err := sources.ImageTag(i.DockerClient, fmt.Sprintf("%s/%s:%s", "goodrain.me", oldImageName.Name, oldImageName.Tag), image, i.Logger, 15); err != nil { + if err := sources.ImageTag(i.DockerClient, fmt.Sprintf("%s/%s:%s", builder.REGISTRYDOMAIN, oldImageName.Name, oldImageName.Tag), image, i.Logger, 15); err != nil { return fmt.Errorf("change image tag(%s => %s) error %s", fmt.Sprintf("%s/%s:%s", i.ServiceImage.HubUrl, oldImageName.Name, oldImageName.Tag), image, err.Error()) } // 开始上传 diff --git a/builder/exector/metadata.json b/builder/exector/metadata.json new file mode 100644 index 000000000..2cbae7b49 --- /dev/null +++ b/builder/exector/metadata.json @@ -0,0 +1 @@ +{"describe": "NextCloud-\u4e2a\u4eba\u79c1\u6709\u7f51\u76d8\u7684\u6700\u4f73\u9009\u62e9,\u652f\u6301\u6587\u6863\u591a\u4eba\u534f\u540c\u5728\u7ebf\u7f16\u8f91\u3002", "group_version": "v16.0.0", "image_base64_string": null, "template_version": "v2", "apps": [{"deploy_version": "20190318181959", "service_name": "", "image": "hub.goodrain.com/goodrain/gr6faafe_goodrain-apps_redis:20180620210426_v3.2.11", "service_volume_map_list": [{"file_content": "", "category": "app_publish", "volume_path": "/data", "volume_type": "share-file", "volume_name": "GR6FAAFE_1"}], "extend_method": "state", "service_key": "b2a88a74806f48d480b0e15c2c1b237d", "category": "app_publish", "service_region": "rainbond", "share_type": "image", "extend_method_map": {"min_node": 1, "step_memory": 128, "is_restart": 0, "step_node": 1, "max_memory": 65536, "max_node": 1, "min_memory": 256}, "version": "81701", "service_source": "market", "memory": 256, "service_type": "application", "service_env_map_list": [{"attr_name": "TZ", "name": "\u65f6\u533a", "is_change": true, "attr_value": "Asia/Shanghai"}, {"attr_name": "TCP_KEEPALIVE", "name": "\u662f\u5426\u5f00\u542f\u957f\u94fe\u63a5\uff0c0\u4e3a\u5173\u95ed", "is_change": true, "attr_value": "300"}, {"attr_name": "DATABASES", "name": "\u53ef\u7528\u6570\u636e\u5e93\u6570\u91cf", "is_change": true, "attr_value": "16"}, {"attr_name": "LOGLEVEL", "name": "\u65e5\u5fd7\u8bb0\u5f55\u7b49\u7ea7\uff1adebug\u3001verbose\u3001notice\u3001warning", "is_change": true, "attr_value": "notice"}, {"attr_name": "SLOWLOG_LOG_SLOWER_THAN", "name": "\u6162\u65e5\u5fd7\u8bbe\u5b9a\u65f6\u95f4\uff0c\u5355\u4f4d\u5fae\u79d2\uff0c0\u4e3a\u6bcf\u6761\u90fd\u8bb0\u5f55", "is_change": true, "attr_value": "10000"}, {"attr_name": "SLOWLOG_MAX_LEN", "name": "\u6162\u65e5\u5fd7\u957f\u5ea6", "is_change": true, "attr_value": "128"}, {"attr_name": "MAXCLIENTS", "name": "\u5ba2\u6237\u7aef\u6700\u5927\u8fde\u63a5\u6570", "is_change": true, "attr_value": "10000"}, {"attr_name": "TIMEOUT", "name": "\u5ba2\u6237\u7aef\u8fde\u63a5\u65f6\u7684\u8d85\u65f6\u65f6\u95f4", "is_change": true, "attr_value": "100"}, {"attr_name": "DBFILENAME", "name": "\u672c\u5730\u6301\u4e45\u5316\u6570\u636e\u5e93\u6587\u4ef6\u540d", "is_change": true, "attr_value": "dump.rdb"}], "service_related_plugin_config": [], "service_alias": "gr04ea71", "service_cname": "Redis-3.2.11", "port_map_list": [{"port_alias": "REDIS", "protocol": "tcp", "tenant_id": "157b2015f1c74b219f38849f7857d382", "container_port": 6379, "is_outer_service": false, "is_inner_service": true}], "share_image": "hub.goodrain.com/goodrain/gr6faafe_goodrain-apps_redis:20190318181959_v16.0.0", "dep_service_map_list": [], "probes": [{"http_header": "", "initial_delay_second": 2, "is_used": true, "cmd": "", "probe_id": "9a0760d48b62459bb18f82271b985c30", "period_second": 3, "port": 6379, "mode": "readiness", "failure_threshold": 3, "path": "", "scheme": "tcp", "success_threshold": 1, "ID": 777, "timeout_second": 30, "service_id": "55fafdfac23b47ecb607d860b604ea71"}], "language": "", "need_share": true, "tenant_id": "157b2015f1c74b219f38849f7857d382", "cmd": "", "creater": 3150, "service_share_uuid": "b2a88a74806f48d480b0e15c2c1b237d+55fafdfac23b47ecb607d860b604ea71", "service_image": {"hub_user": "goodrain-admin", "is_trust": true, "namespace": "goodrain", "hub_url": "hub.goodrain.com", "hub_password": "goodrain123465"}, "service_connect_info_map_list": [{"name": "\u8fde\u63a5\u5bc6\u7801", "attr_name": "REDIS_PASS", "attr_value": "**None**", "is_change": true, "container_port": 0}], "service_id": "55fafdfac23b47ecb607d860b604ea71"}, {"deploy_version": "20190317214343", "service_name": "", "image": "hub.goodrain.com/goodrain/mysql:20181019160510_20181019160510_5.7.23", "service_volume_map_list": [{"file_content": "", "category": "app_publish", "volume_path": "/var/lib/mysql", "volume_type": "share-file", "volume_name": "GREAF238_1"}, {"file_content": "", "category": "app_publish", "volume_path": "/var/log/mysql", "volume_type": "share-file", "volume_name": "GREAF238_2"}], "extend_method": "state", "service_key": "ea30f85acb714fc080251b0417cf6544", "category": "app_publish", "service_region": "rainbond", "share_type": "image", "extend_method_map": {"min_node": 1, "step_memory": 128, "is_restart": 0, "step_node": 1, "max_memory": 65536, "max_node": 1, "min_memory": 512}, "version": "percona-5.7", "service_source": "market", "memory": 512, "service_type": "application", "service_env_map_list": [{"attr_name": "PERCONA_MAJOR", "name": "PERCONA_MAJOR", "is_change": true, "attr_value": "5.7"}, {"attr_name": "PERCONA_VERSION", "name": "PERCONA_VERSION", "is_change": true, "attr_value": "5.7.23-23-1.stretch"}, {"attr_name": "MYSQL_VERSION", "name": "MYSQL_VERSION", "is_change": true, "attr_value": "5.7.23"}, {"attr_name": "TZ", "name": "TZ", "is_change": true, "attr_value": "Asia/Shanghai"}, {"attr_name": "GOSU_VERSION", "name": "GOSU_VERSION", "is_change": true, "attr_value": "1.10"}, {"attr_name": "MYSQLC_MYSQLD_MAX_CONNECTIONS", "name": "\u914d\u7f6e-\u6700\u5927\u8fde\u63a5\u6570", "is_change": true, "attr_value": "3000"}, {"attr_name": "MYSQLC_MYSQLD_THREAD_CACHE_SIZE", "name": "\u914d\u7f6e-threadcache\u6c60\u4e2d\u53ef\u4ee5\u7f13\u5b58\u8fde\u63a5\u7ebf\u7a0b\u7684\u6700\u5927\u6570\u91cf", "is_change": true, "attr_value": "64"}, {"attr_name": "MYSQLC_MYSQLD_PORT", "name": "\u914d\u7f6e-\u76d1\u542c\u7aef\u53e3", "is_change": true, "attr_value": "3306"}, {"attr_name": "MYSQL_ROOT_PASSWORD", "name": "root\u5bc6\u7801", "is_change": true, "attr_value": "asdaCJASDVMKCLSAKDVMC"}], "service_related_plugin_config": [{"attr": [{"protocol": "mysql", "dest_service_alias": "", "container_port": 3306, "create_time": "2019-03-17 21:43:43", "attrs": "{\"OPEN\": \"YES\"}", "dest_service_id": "", "build_version": "20190227212402", "service_id": "e01167679d2f45b1a4d4f241b2b10f0c", "injection": "auto", "plugin_id": "79b17da80bf1447fa4c019e41f1aa66c", "ID": 2289, "service_meta_type": "upstream_port"}], "create_time": "2019-03-17 21:43:43", "plugin_status": true, "build_version": "20190227212402", "service_id": "e01167679d2f45b1a4d4f241b2b10f0c", "plugin_id": "79b17da80bf1447fa4c019e41f1aa66c", "plugin_key": "perf_analyze_plugin", "ID": 189, "service_meta_type": ""}], "service_alias": "grb10f0c", "service_cname": "MySQL5.7", "port_map_list": [{"port_alias": "MYSQL", "protocol": "mysql", "tenant_id": "157b2015f1c74b219f38849f7857d382", "container_port": 3306, "is_outer_service": false, "is_inner_service": true}], "share_image": "hub.goodrain.com/goodrain/mysql:20190317214343_v16.0.0", "dep_service_map_list": [], "probes": [{"http_header": "", "initial_delay_second": 2, "is_used": true, "cmd": "", "probe_id": "d3d70ac49d6a4ba2af181428b3af8a1b", "period_second": 3, "port": 3306, "mode": "readiness", "failure_threshold": 3, "path": "", "scheme": "tcp", "success_threshold": 1, "ID": 716, "timeout_second": 30, "service_id": "e01167679d2f45b1a4d4f241b2b10f0c"}], "language": "", "need_share": true, "tenant_id": "157b2015f1c74b219f38849f7857d382", "cmd": "", "creater": 3150, "service_share_uuid": "ea30f85acb714fc080251b0417cf6544+e01167679d2f45b1a4d4f241b2b10f0c", "service_image": {"hub_user": "goodrain-admin", "is_trust": true, "namespace": "goodrain", "hub_url": "hub.goodrain.com", "hub_password": "goodrain123465"}, "service_connect_info_map_list": [{"name": "\u6570\u636e\u5e93\u540d", "attr_name": "MYSQL_DATABASE", "attr_value": "default", "is_change": true, "container_port": 0}, {"name": "admin", "attr_name": "MYSQL_USER", "attr_value": "admin", "is_change": true, "container_port": 0}, {"name": "\u5bc6\u7801", "attr_name": "MYSQL_PASSWORD", "attr_value": "**None**", "is_change": true, "container_port": 0}], "service_id": "e01167679d2f45b1a4d4f241b2b10f0c"}, {"deploy_version": "20190320172220", "service_name": "", "image": "goodrain.me/runner:latest", "service_volume_map_list": [{"file_content": "", "category": "application", "volume_path": "/var/www/html", "volume_type": "share-file", "volume_name": "GRD35B4F_1"}], "extend_method": "stateless", "service_key": "5d9b134116854ea39c570fdf44a53e23", "category": "application", "service_region": "rainbond", "share_type": "image", "extend_method_map": {"min_node": 1, "step_memory": 128, "is_restart": 0, "step_node": 1, "max_memory": 65536, "max_node": 20, "min_memory": 1024}, "version": "latest", "service_source": "source_code", "memory": 1024, "service_type": "application", "service_env_map_list": [{"attr_name": "NEXTCLOUD_VERSION", "name": "NEXTCLOUD_VERSION", "is_change": true, "attr_value": "15.0.5"}], "service_related_plugin_config": [], "service_alias": "grd35b4f", "service_cname": "nextcloud-server", "port_map_list": [{"port_alias": "GRD35B4F80", "protocol": "http", "tenant_id": "157b2015f1c74b219f38849f7857d382", "container_port": 80, "is_outer_service": true, "is_inner_service": false}], "share_image": "hub.goodrain.com/goodrain/grd35b4f_goodrain_nextcloud-server:20190320172220_v16.0.0", "dep_service_map_list": [{"dep_service_key": "b2a88a74806f48d480b0e15c2c1b237d+55fafdfac23b47ecb607d860b604ea71"}, {"dep_service_key": "ea30f85acb714fc080251b0417cf6544+e01167679d2f45b1a4d4f241b2b10f0c"}], "probes": [{"http_header": "", "initial_delay_second": 2, "is_used": true, "cmd": "", "probe_id": "c02e145336bf4ad59da96f27078dc30e", "period_second": 3, "port": 80, "mode": "readiness", "failure_threshold": 3, "path": "", "scheme": "tcp", "success_threshold": 1, "ID": 911, "timeout_second": 20, "service_id": "6ee0d5bc96ff928d117f1c00c0d35b4f"}], "language": "dockerfile", "need_share": true, "tenant_id": "157b2015f1c74b219f38849f7857d382", "cmd": "", "creater": 3150, "service_share_uuid": "5d9b134116854ea39c570fdf44a53e23+6ee0d5bc96ff928d117f1c00c0d35b4f", "service_image": {"hub_user": "goodrain-admin", "is_trust": true, "namespace": "goodrain", "hub_url": "hub.goodrain.com", "hub_password": "goodrain123465"}, "service_connect_info_map_list": [], "service_id": "6ee0d5bc96ff928d117f1c00c0d35b4f"}, {"deploy_version": "20190319101324", "service_name": "", "image": "barnett/collabora:190114", "service_volume_map_list": [], "extend_method": "stateless", "service_key": "802967c1bd5d41e99a52b4c6f5ccec91", "category": "app_publish", "service_region": "rainbond", "share_type": "image", "extend_method_map": {"min_node": 1, "step_memory": 128, "is_restart": 0, "step_node": 1, "max_memory": 65536, "max_node": 20, "min_memory": 2048}, "version": "190114", "service_source": "docker_image", "memory": 2048, "service_type": "application", "service_env_map_list": [{"attr_name": "domain", "name": "", "is_change": true, "attr_value": "80\\.grd35b4f\\.52bli69h\\.0196bd\\.grapps\\.cn"}], "service_related_plugin_config": [], "service_alias": "gra660c5", "service_cname": "collabora-online", "port_map_list": [{"port_alias": "GRA660C59980", "protocol": "tcp", "tenant_id": "157b2015f1c74b219f38849f7857d382", "container_port": 9980, "is_outer_service": true, "is_inner_service": false}], "share_image": "hub.goodrain.com/goodrain/collabora:20190319101324_v16.0.0", "dep_service_map_list": [], "probes": [], "language": "", "need_share": true, "tenant_id": "157b2015f1c74b219f38849f7857d382", "cmd": "", "creater": 3150, "service_share_uuid": "802967c1bd5d41e99a52b4c6f5ccec91+3a542db90d9c607cba4c1caecca660c5", "service_image": {"hub_user": "goodrain-admin", "is_trust": true, "namespace": "goodrain", "hub_url": "hub.goodrain.com", "hub_password": "goodrain123465"}, "service_connect_info_map_list": [], "service_id": "3a542db90d9c607cba4c1caecca660c5"}], "group_name": "Nextcloud", "plugins": [{"category": "analyst-plugin:perf", "origin": "local_market", "config_groups": [{"config_name": "\u7aef\u53e3\u662f\u5426\u5f00\u542f\u5206\u6790", "ID": 18, "options": [{"attr_info": "\u662f\u5426\u5f00\u542f\u5f53\u524d\u7aef\u53e3\u5206\u6790\uff0c\u7528\u6237\u81ea\u52a9\u9009\u62e9\u670d\u52a1\u7aef\u53e3", "protocol": "http,mysql", "attr_default_value": "YES", "attr_name": "OPEN", "attr_alt_value": "YES,NO", "ID": 108, "is_change": true, "build_version": "20190227212402", "plugin_id": "79b17da80bf1447fa4c019e41f1aa66c", "attr_type": "radio", "service_meta_type": "upstream_port"}], "build_version": "20190227212402", "plugin_id": "79b17da80bf1447fa4c019e41f1aa66c", "injection": "auto", "service_meta_type": "upstream_port"}], "desc": "\u5b9e\u65f6\u5206\u6790\u5e94\u7528\u7684\u541e\u5410\u7387\u3001\u54cd\u5e94\u65f6\u95f4\u3001\u5728\u7ebf\u4eba\u6570\u7b49\u6307\u6807", "tenant_id": "157b2015f1c74b219f38849f7857d382", "region": "rainbond", "plugin_alias": "\u670d\u52a1\u5b9e\u65f6\u6027\u80fd\u5206\u6790", "plugin_name": "gr79b17d", "ID": 18, "create_user": 3150, "create_time": "2019-02-27 21:24:02", "origin_share_id": "perf_analyze_plugin", "plugin_image": {"hub_user": "goodrain-admin", "is_trust": true, "namespace": "goodrain", "hub_url": "hub.goodrain.com", "hub_password": "goodrain123465"}, "build_version": "20190227212402", "share_image": "hub.goodrain.com/goodrain/plugin_tcm_79b17da80bf1447fa4c019e41f1aa66c:latest_20192272124333977015_20190227212402", "plugin_id": "79b17da80bf1447fa4c019e41f1aa66c", "plugin_key": "perf_analyze_plugin", "build_source": "image", "image": "goodrain.me/tcm", "code_repo": ""}], "group_key": "5acfa319e8084a16abc1806cfd79cad6", "suffix": ""} \ No newline at end of file diff --git a/builder/exector/plugin_dockerfile.go b/builder/exector/plugin_dockerfile.go index 78dff668c..b10aa81f3 100644 --- a/builder/exector/plugin_dockerfile.go +++ b/builder/exector/plugin_dockerfile.go @@ -107,7 +107,7 @@ func (e *exectorManager) runD(t *model.BuildPluginTaskBody, logger event.Logger) logger.Info("代码检测为dockerfile,开始编译", map[string]string{"step": "build-exector"}) mm := strings.Split(t.GitURL, "/") n1 := strings.Split(mm[len(mm)-1], ".")[0] - buildImageName := fmt.Sprintf("goodrain.me/plugin_%s_%s:%s", n1, t.PluginID, t.DeployVersion) + buildImageName := fmt.Sprintf(builder.REGISTRYDOMAIN+"/plugin_%s_%s:%s", n1, t.PluginID, t.DeployVersion) buildOptions := types.ImageBuildOptions{ Tags: []string{buildImageName}, Remove: true, diff --git a/builder/repostory.go b/builder/repostory.go index 5f405156e..4078a874e 100644 --- a/builder/repostory.go +++ b/builder/repostory.go @@ -48,7 +48,7 @@ var REGISTRYUSER = "" var REGISTRYPASS = "" //RUNNERIMAGENAME runner image name -var RUNNERIMAGENAME = "goodrain.me/runner" +var RUNNERIMAGENAME = REGISTRYDOMAIN + "/runner" //BUILDERIMAGENAME builder image name -var BUILDERIMAGENAME = "goodrain.me/builder" +var BUILDERIMAGENAME = REGISTRYDOMAIN + "/builder" diff --git a/db/model/tenant.go b/db/model/tenant.go index 5f684f1b8..6708e2dc4 100644 --- a/db/model/tenant.go +++ b/db/model/tenant.go @@ -409,7 +409,7 @@ type TenantServiceProbe struct { //检测超时时间 TimeoutSecond int `gorm:"column:timeout_second;size:3;default:30" json:"timeout_second" validate:"timeout_second"` //是否启用 - IsUsed int `gorm:"column:is_used;size:1;default:1" json:"is_used" validate:"is_used"` + IsUsed *int `gorm:"column:is_used;size:1;default:1" json:"is_used" validate:"is_used"` //标志为失败的检测次数 FailureThreshold int `gorm:"column:failure_threshold;size:2;default:3" json:"failure_threshold" validate:"failure_threshold"` //标志为成功的检测次数 diff --git a/db/mysql/dao/gateway.go b/db/mysql/dao/gateway.go index 2f940f83a..a778997e9 100644 --- a/db/mysql/dao/gateway.go +++ b/db/mysql/dao/gateway.go @@ -168,10 +168,7 @@ func (h *HTTPRuleDaoImpl) UpdateModel(mo model.Interface) error { if !ok { return fmt.Errorf("Failed to convert %s to *model.HTTPRule", reflect.TypeOf(mo).String()) } - - return h.DB.Table(hr.TableName()). - Where("uuid = ?", hr.UUID). - Update(hr).Error + return h.DB.Save(hr).Error } // GetHTTPRuleByID gets a HTTPRule based on uuid diff --git a/db/mysql/dao/k8s.go b/db/mysql/dao/k8s.go index f7d87dc6f..c4c42e74e 100644 --- a/db/mysql/dao/k8s.go +++ b/db/mysql/dao/k8s.go @@ -50,7 +50,8 @@ func (t *ServiceProbeDaoImpl) UpdateModel(mo model.Interface) error { probe := mo.(*model.TenantServiceProbe) if probe.ID == 0 { var oldProbe model.TenantServiceProbe - if err := t.DB.Where("service_id = ? and mode = ? and probe_id=?", probe.ServiceID, probe.Mode, probe.ProbeID).Find(&oldProbe).Error; err != nil { + if err := t.DB.Where("service_id = ? and probe_id=?", probe.ServiceID, + probe.ProbeID).Find(&oldProbe).Error; err != nil { return err } if oldProbe.ID == 0 { diff --git a/gateway/annotations/proxy/proxy.go b/gateway/annotations/proxy/proxy.go index fe49a254e..27500147d 100644 --- a/gateway/annotations/proxy/proxy.go +++ b/gateway/annotations/proxy/proxy.go @@ -116,7 +116,15 @@ func (l1 *Config) Equal(l2 *Config) bool { if l1.ProxyBuffering != l2.ProxyBuffering { return false } - // TODO: ProxySetHeaders + + if len(l1.SetHeaders) != len(l2.SetHeaders) { + return false + } + for k, v := range l1.SetHeaders { + if l2.SetHeaders[k] != v { + return false + } + } return true } @@ -219,6 +227,9 @@ func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) { fmt.Sprintf("%s/%s", ing.GetNamespace(), ing.GetName()), err) } for k, v := range setHeaders { + if v == "empty" { + v = "" + } config.SetHeaders[k] = v } diff --git a/gateway/annotations/proxy/proxy_test.go b/gateway/annotations/proxy/proxy_test.go index 3552ce829..23bdf2a83 100644 --- a/gateway/annotations/proxy/proxy_test.go +++ b/gateway/annotations/proxy/proxy_test.go @@ -92,7 +92,7 @@ func TestProxy(t *testing.T) { data[parser.GetAnnotationWithPrefix("proxy-read-timeout")] = "3" data[parser.GetAnnotationWithPrefix("proxy-buffers-number")] = "8" data[parser.GetAnnotationWithPrefix("proxy-buffer-size")] = "1k" - data[parser.GetAnnotationWithPrefix("proxy-body-size")] = "2k" + data[parser.GetAnnotationWithPrefix("proxy-body-size")] = "2" data[parser.GetAnnotationWithPrefix("proxy-next-upstream")] = "off" data[parser.GetAnnotationWithPrefix("proxy-next-upstream-tries")] = "3" data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off" @@ -122,8 +122,8 @@ func TestProxy(t *testing.T) { if p.BufferSize != "1k" { t.Errorf("expected 1k as buffer-size but returned %v", p.BufferSize) } - if p.BodySize != "2k" { - t.Errorf("expected 2k as body-size but returned %v", p.BodySize) + if p.BodySize != 2 { + t.Errorf("expected 2 as body-size but returned %v", p.BodySize) } if p.NextUpstream != "off" { t.Errorf("expected off as next-upstream but returned %v", p.NextUpstream) @@ -168,7 +168,7 @@ func TestProxyWithNoAnnotation(t *testing.T) { if p.BufferSize != "10k" { t.Errorf("expected 10k as buffer-size but returned %v", p.BufferSize) } - if p.BodySize != "3k" { + if p.BodySize != 3 { t.Errorf("expected 3k as body-size but returned %v", p.BodySize) } if p.NextUpstream != "error" { diff --git a/gateway/store/store.go b/gateway/store/store.go index 713ed3529..74c30ae62 100644 --- a/gateway/store/store.go +++ b/gateway/store/store.go @@ -29,9 +29,6 @@ import ( "strings" "sync" - "github.com/goodrain/rainbond/db/model" - "k8s.io/apimachinery/pkg/labels" - "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/goodrain/rainbond/cmd/gateway/option" @@ -40,7 +37,7 @@ import ( "github.com/goodrain/rainbond/gateway/controller/config" "github.com/goodrain/rainbond/gateway/defaults" "github.com/goodrain/rainbond/gateway/util" - v1 "github.com/goodrain/rainbond/gateway/v1" + "github.com/goodrain/rainbond/gateway/v1" corev1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -377,97 +374,74 @@ func (s *k8sStore) extractAnnotations(ing *extensions.Ingress) { func (s *k8sStore) ListPool() ([]*v1.Pool, []*v1.Pool) { var httpPools []*v1.Pool var tcpPools []*v1.Pool + l7Pools := make(map[string]*v1.Pool) + l4Pools := make(map[string]*v1.Pool) + for _, item := range s.listers.Endpoint.List() { + ep := item.(*corev1.Endpoints) - f := func(backendMap map[string][]backend, poolMap map[string]struct{}) map[string]*v1.Pool { - pools := make(map[string]*v1.Pool) - for k, v := range backendMap { - service, err := s.listers.Service.ByKey(k) - if err != nil { - logrus.Warningf("Key: %s;error getting service: %v", k, err) - continue - } - originPort := service.GetLabels()["origin_port"] - var pluginPort int32 - if originPort != "" { - port, err := strconv.Atoi(originPort) - if err != nil { - logrus.Warningf("Origin port: %s; error converting to type int: %v", err) - pluginPort = 0 - } else { - pluginPort = int32(port) + if ep.Subsets != nil || len(ep.Subsets) != 0 { + epn := ep.ObjectMeta.Name + // l7 + backends := l7PoolBackendMap[ep.ObjectMeta.Name] + for _, backend := range backends { + pool := l7Pools[backend.name] + if pool == nil { + pool = &v1.Pool{ + Nodes: []*v1.Node{}, + } + pool.Name = backend.name + pool.UpstreamHashBy = backend.hashBy + l7Pools[backend.name] = pool } - } - - // list related endpoints - labelname, ok := service.GetLabels()["name"] - if !ok { - logrus.Warningf("Key: %s;label 'name' not found", k) - continue - } - selector, err := labels.Parse(fmt.Sprintf("name=%s", labelname)) - if err != nil { - logrus.Warningf("Label: %s; error parsing labels: %s", - fmt.Sprintf("name=%s", labelname), err.Error()) - continue - } - endpoints, err := s.sharedInformer.Core().V1().Endpoints().Lister().Endpoints(service.GetNamespace()).List(selector) - if err != nil { - logrus.Warningf("Label: %s; error listing endpoints: %v", - fmt.Sprintf("name=%s", labelname), err) - continue - } - - for _, ep := range endpoints { - if ep.Subsets == nil || len(ep.Subsets) == 0 { - continue - } - if ep.GetLabels()["service_kind"] != model.ServiceKindThirdParty.String() { - if ep.Subsets[0].Ports[0].Port != service.Spec.Ports[0].TargetPort.IntVal { - continue + for _, ss := range ep.Subsets { + var addresses []corev1.EndpointAddress + if ss.Addresses != nil && len(ss.Addresses) > 0 { + addresses = append(addresses, ss.Addresses...) + } else { + addresses = append(addresses, ss.NotReadyAddresses...) + } + for _, address := range addresses { + if _, ok := l7PoolMap[epn]; ok { // l7 + pool.Nodes = append(pool.Nodes, &v1.Node{ + Host: address.IP, + Port: ss.Ports[0].Port, + Weight: backend.weight, + }) + } } } - - for _, backend := range v { - pool := pools[backend.name] - if pool == nil { - pool = &v1.Pool{ - Nodes: []*v1.Node{}, - } - pool.Name = backend.name - pool.UpstreamHashBy = backend.hashBy - pools[backend.name] = pool + } + // l4 + backends = l4PoolBackendMap[ep.ObjectMeta.Name] + for _, backend := range backends { + pool := l4Pools[backend.name] + if pool == nil { + pool = &v1.Pool{ + Nodes: []*v1.Node{}, } - for _, ss := range ep.Subsets { - var addresses []corev1.EndpointAddress - if ss.Addresses != nil && len(ss.Addresses) > 0 { - addresses = append(addresses, ss.Addresses...) - } else { - addresses = append(addresses, ss.NotReadyAddresses...) - } - for _, address := range addresses { - if _, ok := poolMap[k]; ok { // l7 - pool.Nodes = append(pool.Nodes, &v1.Node{ - Host: address.IP, - Port: func(pluginPort, addressPort int32) int32 { - if pluginPort != 0 { - return pluginPort - } - return addressPort - }(pluginPort, ss.Ports[0].Port), - Weight: backend.weight, - }) - } + pool.Name = backend.name + l4Pools[backend.name] = pool + } + for _, ss := range ep.Subsets { + var addresses []corev1.EndpointAddress + if ss.Addresses != nil && len(ss.Addresses) > 0 { + addresses = append(addresses, ss.Addresses...) + } else { + addresses = append(addresses, ss.NotReadyAddresses...) + } + for _, address := range addresses { + if _, ok := l4PoolMap[epn]; ok { // l7 + pool.Nodes = append(pool.Nodes, &v1.Node{ + Host: address.IP, + Port: ss.Ports[0].Port, + Weight: backend.weight, + }) } } } } } - return pools } - - l7Pools := f(l7PoolBackendMap, l7PoolMap) - l4Pools := f(l4PoolBackendMap, l4PoolMap) - // change map to slice TODO: use map directly for _, pool := range l7Pools { httpPools = append(httpPools, pool) @@ -491,20 +465,20 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V if !s.ingressIsValid(ing) { continue } + ingKey := k8s.MetaNamespaceKey(ing) anns, err := s.GetIngressAnnotations(ingKey) if err != nil { logrus.Errorf("Error getting Ingress annotations %q: %v", ingKey, err) } if anns.L4.L4Enable && anns.L4.L4Port != 0 { - svcKey := fmt.Sprintf("%v/%v", ing.Namespace, ing.Spec.Backend.ServiceName) - // region l4 host := strings.Replace(anns.L4.L4Host, " ", "", -1) if host == "" { host = s.conf.IP } host = s.conf.IP + svcKey := fmt.Sprintf("%v/%v", ing.Namespace, ing.Spec.Backend.ServiceName) protocol := s.GetServiceProtocol(svcKey, ing.Spec.Backend.ServicePort.IntVal) listening := fmt.Sprintf("%s:%v", host, anns.L4.L4Port) if string(protocol) == string(v1.ProtocolUDP) { @@ -521,11 +495,12 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V vs.Namespace = anns.Namespace vs.ServiceID = anns.Labels["service_id"] } - l4PoolMap[svcKey] = struct{}{} + + l4PoolMap[ing.Spec.Backend.ServiceName] = struct{}{} l4vsMap[listening] = vs l4vs = append(l4vs, vs) backend := backend{name: backendName, weight: anns.Weight.Weight} - l4PoolBackendMap[svcKey] = append(l4PoolBackendMap[svcKey], backend) + l4PoolBackendMap[ing.Spec.Backend.ServiceName] = append(l4PoolBackendMap[ing.Spec.Backend.ServiceName], backend) // endregion } else { // region l7 @@ -577,14 +552,15 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V vs.SSLCert = hostSSLMap[DefVirSrvName] } } + l7vsMap[virSrvName] = vs l7vs = append(l7vs, vs) } + for _, path := range rule.IngressRuleValue.HTTP.Paths { - svckey := fmt.Sprintf("%s/%s", ing.Namespace, path.Backend.ServiceName) locKey := fmt.Sprintf("%s_%s", virSrvName, path.Path) location := srvLocMap[locKey] - l7PoolMap[svckey] = struct{}{} + l7PoolMap[path.Backend.ServiceName] = struct{}{} // if location do not exists, then creates a new one if location == nil { location = &v1.Location{ @@ -593,10 +569,9 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V } srvLocMap[locKey] = location vs.Locations = append(vs.Locations, location) + // the first ingress proxy takes effect + location.Proxy = anns.Proxy } - - location.Proxy = anns.Proxy - // If their ServiceName is the same, then the new one will overwrite the old one. nameCondition := &v1.Condition{} var backendName string @@ -619,7 +594,7 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V if anns.UpstreamHashBy != "" { backend.hashBy = anns.UpstreamHashBy } - l7PoolBackendMap[svckey] = append(l7PoolBackendMap[svckey], backend) + l7PoolBackendMap[path.Backend.ServiceName] = append(l7PoolBackendMap[path.Backend.ServiceName], backend) } } // endregion @@ -630,57 +605,47 @@ func (s *k8sStore) ListVirtualService() (l7vs []*v1.VirtualService, l4vs []*v1.V // ingressIsValid checks if the specified ingress is valid func (s *k8sStore) ingressIsValid(ing *extensions.Ingress) bool { - var svcKey string + + var endpointKey string if ing.Spec.Backend != nil { // stream - svcKey = fmt.Sprintf("%s/%s", ing.Namespace, ing.Spec.Backend.ServiceName) + endpointKey = fmt.Sprintf("%s/%s", ing.Namespace, ing.Spec.Backend.ServiceName) } else { // http Loop: for _, rule := range ing.Spec.Rules { for _, path := range rule.IngressRuleValue.HTTP.Paths { - svcKey = fmt.Sprintf("%s/%s", ing.Namespace, path.Backend.ServiceName) - if svcKey != "" { + endpointKey = fmt.Sprintf("%s/%s", ing.Namespace, path.Backend.ServiceName) + if endpointKey != "" { break Loop } } } } - service, err := s.listers.Service.ByKey(svcKey) + item, exists, err := s.listers.Endpoint.GetByKey(endpointKey) if err != nil { - logrus.Warningf("Key: %s; error getting key: %v", err) + logrus.Errorf("Can not get endpoint by key(%s): %v", endpointKey, err) return false } - labelname := fmt.Sprintf("name=%s", service.GetLabels()["name"]) - selector, err := labels.Parse(labelname) - if err != nil { - logrus.Warningf("Label: %s;error parsing labels: %v", labelname, err) + if !exists { + logrus.Warningf("Endpoint \"%s\" does not exist.", endpointKey) return false } - eps, err := s.sharedInformer.Core().V1().Endpoints().Lister().Endpoints(service.GetNamespace()).List(selector) - if err != nil { - logrus.Warningf("selector: %s; error listing endpoints: %v", - fmt.Sprintf("name=%s", labelname), err) + endpoint, ok := item.(*corev1.Endpoints) + if !ok { + logrus.Errorf("Cant not convert %v to %v", reflect.TypeOf(item), reflect.TypeOf(endpoint)) return false } - if eps == nil || len(eps) == 0 { - logrus.Warningf("Selector: %s; empty endpoints", fmt.Sprintf("name=%s", labelname)) + if endpoint.Subsets == nil || len(endpoint.Subsets) == 0 { + logrus.Warningf("Endpoints(%s) is empty, ignore it", endpointKey) + return false } - - result := false - for _, ep := range eps { - if ep.Subsets != nil && len(ep.Subsets) > 0 { - e := ep.Subsets[0] - if ep.GetLabels()["service_kind"] != model.ServiceKindThirdParty.String() && - e.Ports[0].Port != service.Spec.Ports[0].Port { - continue - } - if !((e.Addresses == nil || len(e.Addresses) == 0) && (e.NotReadyAddresses == nil || len(e.NotReadyAddresses) == 0)) { - result = true - break - } + for _, ep := range endpoint.Subsets { + if (ep.Addresses == nil || len(ep.Addresses) == 0) && (ep.NotReadyAddresses == nil || len(ep.NotReadyAddresses) == 0) { + logrus.Warningf("Endpoints(%s) is empty, ignore it", endpointKey) + return false } } - return result + return true } // GetIngress returns the Ingress matching key. @@ -701,20 +666,6 @@ func (s *k8sStore) ListIngresses() []*extensions.Ingress { return ingresses } -// GetServiceNameLabelByKey returns name in the labels of corev1.Service -// matching key(name/namespace). -func (s *k8sStore) GetServiceNameLabelByKey(key string) (string, error) { - svc, err := s.listers.Service.ByKey(key) - if err != nil { - return "", err - } - name, ok := svc.Labels["name"] - if !ok { - return "", fmt.Errorf("label \"name\" not found") - } - return name, nil -} - // GetServiceProtocol returns the Service matching key and port. func (s *k8sStore) GetServiceProtocol(key string, port int32) corev1.Protocol { svcs, err := s.listers.Service.ByKey(key) diff --git a/gateway/v1/location.go b/gateway/v1/location.go index 95880122a..38b901a93 100644 --- a/gateway/v1/location.go +++ b/gateway/v1/location.go @@ -75,6 +75,10 @@ func (l *Location) Equals(c *Location) bool { } } + if !l.Proxy.Equal(&c.Proxy) { + return false + } + return true } diff --git a/gateway/v1/node.go b/gateway/v1/node.go index a298b6375..778c8186e 100644 --- a/gateway/v1/node.go +++ b/gateway/v1/node.go @@ -46,6 +46,9 @@ func (n *Node) Equals(c *Node) bool { // if n.Host != c.Host { return false } + if n.Port != c.Port { + return false + } if n.Protocol != c.Protocol { return false } @@ -61,5 +64,11 @@ func (n *Node) Equals(c *Node) bool { // if n.Weight != c.Weight { return false } + if n.MaxFails != c.MaxFails { + return false + } + if n.FailTimeout != c.FailTimeout { + return false + } return true } diff --git a/gateway/v1/node_test.go b/gateway/v1/node_test.go index 84a920f04..ef277a09f 100644 --- a/gateway/v1/node_test.go +++ b/gateway/v1/node_test.go @@ -18,42 +18,21 @@ package v1 -import "testing" +import ( + "testing" +) func TestNode_Equals(t *testing.T) { - n := &Node{ - Meta: Meta{ - Index: 888, - Name: "foo-node", - Namespace: "ns", - PluginName: "Nginx", - }, - Host: "www.goodrain.com", - Port: 80, - Protocol: "Http", - State: "ok", - PoolName: "foo-poolName", - Ready: true, - Weight: 5, - } - c := &Node{ - Meta: Meta{ - Index: 888, - Name: "foo-node", - Namespace: "ns", - PluginName: "Nginx", - }, - Host: "www.goodrain.com", - Port: 80, - Protocol: "Http", - State: "ok", - PoolName: "foo-poolName", - Ready: true, - Weight: 5, - } + n := newFakeNode() + c := newFakeNode() if !n.Equals(c) { t.Errorf("n should equal c") } + f := newFakeNode() + f.MaxFails = 5 + if n.Equals(f) { + t.Errorf("n should not equal c") + } } func newFakeNode() *Node { @@ -71,5 +50,7 @@ func newFakeNode() *Node { PoolName: "foo-poolName", Ready: true, Weight: 5, + MaxFails: 3, + FailTimeout: "5", } } diff --git a/gateway/v1/ssl_cert.go b/gateway/v1/ssl_cert.go index 68a5c9a20..f3fa23f3e 100644 --- a/gateway/v1/ssl_cert.go +++ b/gateway/v1/ssl_cert.go @@ -47,7 +47,7 @@ func (s *SSLCert) Equals(c *SSLCert) bool { if !s.Meta.Equals(c.Meta) { return false } - if s.CertificatePem != c.CertificatePem { + if (s.Certificate == nil) != (c.Certificate == nil) { return false } if s.Certificate != nil && c.Certificate != nil { @@ -55,9 +55,6 @@ func (s *SSLCert) Equals(c *SSLCert) bool { return false } } - if !(s.Certificate == nil && c.Certificate == nil) { - return false - } if s.CertificateStr != c.CertificateStr { return false } diff --git a/gateway/v1/ssl_cert_test.go b/gateway/v1/ssl_cert_test.go index 5f200f9e9..177400a78 100644 --- a/gateway/v1/ssl_cert_test.go +++ b/gateway/v1/ssl_cert_test.go @@ -30,14 +30,24 @@ func TestSSLCert_Equals(t *testing.T) { if !s.Equals(c) { t.Errorf("s should equal c.") } + s.Certificate = nil + if s.Equals(c) { + t.Errorf("s should not equal c.") + } + c.Certificate = nil + if !s.Equals(c) { + t.Errorf("s should equal c.") + } } func newFakeSSLCert() *SSLCert { meta := newFakeMeta() + certificate := &x509.Certificate{} + certificate.Raw = []byte("foobar") return &SSLCert{ Meta: &meta, CertificateStr: "dummy certificate str", - Certificate: &x509.Certificate{}, + Certificate: certificate, PrivateKey: "dummy private key", CertificatePem: "/expert/servers/nginx/certificate/dummy-secret.pem", CN: []string{ diff --git a/gateway/v1/virtual_service.go b/gateway/v1/virtual_service.go index 5475eeea5..dd5de61b0 100644 --- a/gateway/v1/virtual_service.go +++ b/gateway/v1/virtual_service.go @@ -174,6 +174,17 @@ func (v *VirtualService) Equals(c *VirtualService) bool { if !v.SSLCert.Equals(c.SSLCert) { return false } + if v.ForceSSLRedirect != c.ForceSSLRedirect { + return false + } + if len(v.ExtensionConfig) != len(c.ExtensionConfig) { + return false + } + for key, ve := range v.ExtensionConfig { + if c.ExtensionConfig[key] != ve { + return false + } + } return true } diff --git a/grctl/cmd/service.go b/grctl/cmd/service.go index 9124586fe..258d6878c 100644 --- a/grctl/cmd/service.go +++ b/grctl/cmd/service.go @@ -392,6 +392,36 @@ func showServiceDeployInfo(c *cli.Context) error { } fmt.Println("------------Service------------") fmt.Println(serviceTable.Render()) + //show endpoints + if deployInfo.Endpoints != nil && len(deployInfo.Endpoints) > 0 { + epTable := termtables.CreateTable() + epTable.AddHeaders("Name", "IP", "Port", "Protocol") + for epname := range deployInfo.Endpoints { + if clients.K8SClient != nil { + ep, _ := clients.K8SClient.CoreV1().Endpoints(tenantID).Get(epname, metav1.GetOptions{}) + if ep != nil { + for i := range ep.Subsets { + ss := &ep.Subsets[i] + for j := range ss.Ports { + port := &ss.Ports[j] + for k := range ss.Addresses { + address := &ss.Addresses[k] + epTable.AddRow(ep.Name, address.IP, port.Port, port.Protocol) + } + for k := range ss.NotReadyAddresses { + address := &ss.NotReadyAddresses[k] + epTable.AddRow(ep.Name, address.IP, port.Port, port.Protocol) + } + } + } + } + } else { + epTable.AddRow(epname, "-", "-", "-") + } + } + fmt.Println("------------endpoints------------") + fmt.Println(epTable.Render()) + } //show ingress ingressTable := termtables.CreateTable() ingressTable.AddHeaders("Name", "Host") diff --git a/release.sh b/release.sh index c769c2800..fc7443c83 100755 --- a/release.sh +++ b/release.sh @@ -7,7 +7,12 @@ BASE_NAME=rainbond GO_VERSION=1.11 GATEWAY_GO_VERSION=1.11-alpine3.8 -VERSION=master +VERSION=5.1.1 +if [ -z "$TRAVIS_TAG" ]; then + VERSION=$TRAVIS_BRANCH-dev +else + VERSION=$TRAVIS_TAG +fi buildTime=$(date +%F-%H) git_commit=$(git log -n 1 --pretty --format=%h) diff --git a/util/prober/manager.go b/util/prober/manager.go index 6542e4d66..43bffcedd 100644 --- a/util/prober/manager.go +++ b/util/prober/manager.go @@ -20,7 +20,6 @@ package prober import ( "context" - "encoding/json" "errors" "sync" "time" @@ -39,12 +38,13 @@ type Prober interface { CloseWatch(serviceName string, id string) error Start() AddServices(in []*v1.Service) - CheckAndAddService(in *v1.Service) bool + CheckIfExist(in *v1.Service) bool SetServices([]*v1.Service) GetServices() []*v1.Service GetServiceHealth() map[string]*v1.HealthStatus SetAndUpdateServices([]*v1.Service) error AddAndUpdateServices([]*v1.Service) error + UpdateServiceProbe(service *v1.Service) UpdateServicesProbe(services []*v1.Service) Stop() error DisableWatcher(serviceName, watcherID string) @@ -276,22 +276,30 @@ func (p *probeManager) AddServices(in []*v1.Service) { } // CheckAndAddService checks if the input service exists, if it does not exist, add it. -func (p *probeManager) CheckAndAddService(in *v1.Service) bool { +func (p *probeManager) CheckIfExist(in *v1.Service) bool { exist := false for _, svc := range p.services { if svc.Name == in.Name { - logrus.Debugf("svc name: %s; in name: %s;", svc.Name, in.Name) exist = true } } - if !exist { - b, _ := json.Marshal(in) - logrus.Debugf("add service: %s", string(b)) - p.services = append(p.services, in) - } return exist } +func (p *probeManager) isNeedUpdate(new *v1.Service) bool { + var old *v1.Service + for _, svc := range p.services { + if svc.Name == new.Name { + old = svc + } + } + if old == nil { + // not found old one + return true + } + return !new.Equal(old) +} + func (p *probeManager) GetServiceHealth() map[string]*v1.HealthStatus { return p.status } @@ -361,21 +369,46 @@ func (p *probeManager) updateAllServicesProbe() { } } +// UpdateServiceProbe updates and runs one service probe. +func (p *probeManager) UpdateServiceProbe(service *v1.Service) { + if service.ServiceHealth == nil || service.Disable || !p.isNeedUpdate(service) { + return + } + logrus.Debugf("Probe: %s; update probe.", service.Name) + // stop old probe + old := p.serviceProbe[service.Name] + if old != nil { + old.Stop() + } + // create new probe + serviceProbe := probe.CreateProbe(p.ctx, p.statusChan, service) + if serviceProbe != nil { + p.serviceProbe[service.Name] = serviceProbe + serviceProbe.Check() + } +} + // UpdateServicesProbe updates and runs services probe. func (p *probeManager) UpdateServicesProbe(services []*v1.Service) { - logrus.Debugf("update services probe...") + if services == nil || len(services) == 0 { + logrus.Debug("Empty services") + return + } + oldSvcs := p.ListServicesBySid(services[0].Sid) for _, v := range services { - if v.ServiceHealth == nil { - continue - } - if v.Disable { + delete(oldSvcs, v.Name) + if v.ServiceHealth == nil || v.Disable || !p.isNeedUpdate(v) { continue } + logrus.Debugf("Probe: %s; update probe.", v.Name) // stop old probe old := p.serviceProbe[v.Name] if old != nil { old.Stop() } + if !p.CheckIfExist(v) { + p.services = append(p.services, v) + } // create new probe serviceProbe := probe.CreateProbe(p.ctx, p.statusChan, v) if serviceProbe != nil { @@ -383,6 +416,20 @@ func (p *probeManager) UpdateServicesProbe(services []*v1.Service) { serviceProbe.Check() } } + for _, svc := range oldSvcs { + p.StopProbes([]string{svc.Name}) + } +} + +// ListServicesBySid lists services corresponding to sid. +func (p *probeManager) ListServicesBySid(sid string) map[string]*v1.Service { + res := make(map[string]*v1.Service) + for _, svc := range p.services { + if svc.Sid == sid { + res[svc.Name] = svc + } + } + return res } // GetProbe returns a probe associated with name. @@ -397,6 +444,7 @@ func (p *probeManager) StopProbes(names []string) { logrus.Debugf("Name: %s; Probe not found.", name) continue } + logrus.Debugf("Name: %s; Probe stopped", name) probe.Stop() delete(p.serviceProbe, name) for idx, svc := range p.services { diff --git a/util/prober/probes/probe.go b/util/prober/probes/probe.go index 9b15666d2..a14d48b0d 100644 --- a/util/prober/probes/probe.go +++ b/util/prober/probes/probe.go @@ -20,7 +20,6 @@ package probe import ( "context" - "github.com/Sirupsen/logrus" "github.com/goodrain/rainbond/util/prober/types/v1" ) @@ -34,7 +33,6 @@ type Probe interface { func CreateProbe(ctx context.Context, statusChan chan *v1.HealthStatus, v *v1.Service) Probe { ctx, cancel := context.WithCancel(ctx) if v.ServiceHealth.Model == "tcp" { - logrus.Debug("creat tcp probe...") t := &TCPProbe{ Name: v.ServiceHealth.Name, Address: v.ServiceHealth.Address, @@ -47,7 +45,6 @@ func CreateProbe(ctx context.Context, statusChan chan *v1.HealthStatus, v *v1.Se return t } if v.ServiceHealth.Model == "http" { - logrus.Debug("creat http probe...") t := &HTTPProbe{ Name: v.ServiceHealth.Name, Address: v.ServiceHealth.Address, diff --git a/util/prober/probes/tcp.go b/util/prober/probes/tcp.go index 60149e7ae..4e330f659 100644 --- a/util/prober/probes/tcp.go +++ b/util/prober/probes/tcp.go @@ -32,7 +32,7 @@ func (h *TCPProbe) Stop() { // TCPCheck - func (h *TCPProbe) TCPCheck() { - logrus.Debug("tcp check...") + logrus.Debugf("TCP check; Name: %s; Address: %s", h.Name, h.Address) timer := time.NewTimer(time.Second * time.Duration(h.TimeInterval)) defer timer.Stop() for { diff --git a/util/prober/types/v1/types.go b/util/prober/types/v1/types.go index 3269da38f..0e70cc398 100644 --- a/util/prober/types/v1/types.go +++ b/util/prober/types/v1/types.go @@ -25,27 +25,78 @@ const ( StatHealthy string = "healthy" // StatUnhealthy - StatUnhealthy string = "unhealthy" - // StaTDeath - + // StatDeath - StatDeath string = "death" ) -//Service Service +// Service Service type Service struct { + Sid string `json:"service_id"` Name string `json:"name"` ServiceHealth *Health `json:"health"` Disable bool `json:"disable"` } +// Equal check if the left service(l) is equal to the right service(r) +func (l *Service) Equal(r *Service) bool { + if l == r { + return true + } + if l.Sid != r.Sid { + return false + } + if l.Name != r.Name { + return false + } + if l.Disable != r.Disable { + return false + } + if !l.ServiceHealth.Equal(r.ServiceHealth) { + return false + } + return true +} + //Health ServiceHealth type Health struct { Name string `json:"name"` Model string `json:"model"` + IP string `json:"ip"` Port int `json:"port"` Address string `json:"address"` TimeInterval int `json:"time_interval"` MaxErrorsNum int `json:"max_errors_num"` } +// Equal check if the left health(l) is equal to the right health(r) +func (l *Health) Equal(r *Health) bool { + if l == r { + return true + } + if l.Name != r.Name { + return false + } + if l.Model != r.Model { + return false + } + if l.IP != r.IP { + return false + } + if l.Port != r.Port { + return false + } + if l.Address != r.Address { + return false + } + if l.TimeInterval != r.TimeInterval { + return false + } + if l.MaxErrorsNum != r.MaxErrorsNum { + return false + } + return true +} + //HealthStatus health status type HealthStatus struct { Name string `json:"name"` diff --git a/worker/appm/controller/restart.go b/worker/appm/controller/restart.go index 2b74efeb9..df0bf8e16 100644 --- a/worker/appm/controller/restart.go +++ b/worker/appm/controller/restart.go @@ -55,8 +55,10 @@ func (s *restartController) Begin() { s.manager.callback(s.controllerID, nil) } func (s *restartController) restartOne(app v1.AppService) error { - stopController := stopController{ + //Restart the control set timeout interval is 5m + stopController := &stopController{ manager: s.manager, + waiting: time.Minute * 5, } if err := stopController.stopOne(app); err != nil { app.Logger.Error("(Restart)Stop app failure %s,you could waiting stoped and manual start it", GetCallbackLoggerOption()) diff --git a/worker/appm/controller/stop.go b/worker/appm/controller/stop.go index 2b7535eee..c522fb8d7 100644 --- a/worker/appm/controller/stop.go +++ b/worker/appm/controller/stop.go @@ -35,6 +35,7 @@ type stopController struct { controllerID string appService []v1.AppService manager *Manager + waiting time.Duration } func (s *stopController) Begin() { @@ -143,6 +144,9 @@ func (s *stopController) WaitingReady(app v1.AppService) error { if storeAppService != nil && storeAppService.Replicas > 0 { timeout = time.Duration(storeAppService.Replicas) * timeout } + if s.waiting != 0 { + timeout = s.waiting + } if err := WaitStop(s.manager.store, storeAppService, timeout, app.Logger, s.stopChan); err != nil { return err } diff --git a/worker/appm/controller/upgrade.go b/worker/appm/controller/upgrade.go index d9d731324..554ffb561 100644 --- a/worker/appm/controller/upgrade.go +++ b/worker/appm/controller/upgrade.go @@ -20,15 +20,16 @@ package controller import ( "fmt" + "github.com/goodrain/rainbond/worker/appm/f" "sync" "time" "github.com/Sirupsen/logrus" - v1 "github.com/goodrain/rainbond/worker/appm/types/v1" + "github.com/goodrain/rainbond/worker/appm/types/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/types" ) type upgradeController struct { @@ -140,7 +141,6 @@ func (s *upgradeController) upgradeService(newapp v1.AppService) { } func (s *upgradeController) upgradeOne(app v1.AppService) error { - //first: check and create namespace _, err := s.manager.client.CoreV1().Namespaces().Get(app.TenantID, metav1.GetOptions{}) if err != nil { @@ -167,27 +167,16 @@ func (s *upgradeController) upgradeOne(app v1.AppService) error { } } - if ingresses := app.GetIngress(); ingresses != nil { - for _, ingress := range ingresses { - _, err := s.manager.client.Extensions().Ingresses(ingress.Namespace).Update(ingress) - if err != nil { - app.Logger.Error(fmt.Sprintf("upgrade ingress %s failure %s", app.ServiceAlias, err.Error()), getLoggerOption("failure")) - logrus.Errorf("upgrade ingress %s failure %s", app.ServiceAlias, err.Error()) - } - } - } - //upgrade k8s service + oldApp := s.manager.store.GetAppService(app.ServiceID) s.upgradeService(app) - //upgrade k8s secrets - if secrets := app.GetSecrets(); secrets != nil { - for _, secret := range secrets { - _, err := s.manager.client.CoreV1().Secrets(secret.Namespace).Update(secret) - if err != nil { - app.Logger.Error(fmt.Sprintf("upgrade secret %s failure %s", app.ServiceAlias, err.Error()), getLoggerOption("failure")) - logrus.Errorf("upgrade secret %s failure %s", app.ServiceAlias, err.Error()) - } - } + handleErr := func(msg string, err error) error { + // ignore ingress and secret error + logrus.Warning(msg) + return nil } + _ = f.UpgradeSecrets(s.manager.client, &app, oldApp.GetSecrets(), app.GetSecrets(), handleErr) + _ = f.UpgradeIngress(s.manager.client, &app, oldApp.GetIngress(), app.GetIngress(), handleErr) + return s.WaitingReady(app) } diff --git a/worker/appm/conversion/plugin.go b/worker/appm/conversion/plugin.go index c34a37c31..d516c3f89 100644 --- a/worker/appm/conversion/plugin.go +++ b/worker/appm/conversion/plugin.go @@ -24,6 +24,8 @@ import ( "os" "strings" + "github.com/goodrain/rainbond/builder" + "github.com/Sirupsen/logrus" api_model "github.com/goodrain/rainbond/api/model" @@ -149,7 +151,7 @@ func createUDPDefaultPluginContainer(serviceID string, envs []v1.EnvVar) v1.Cont }}, Env: envs, TerminationMessagePath: "", - Image: "goodrain.me/adapter", + Image: builder.REGISTRYDOMAIN + "/adapter", Resources: createAdapterResources(128, 500), } } @@ -239,7 +241,7 @@ func applyDefaultMeshPluginConfig(as *typesv1.AppService, dbmanager db.Manager) if err != nil { return "", err } - pluginID := "tcpmesh" + util.NewUUID() + pluginID := "tcpmesh" + as.ServiceID cm := &v1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("config-%s-%s", as.ServiceID, pluginID), diff --git a/worker/appm/f/function.go b/worker/appm/f/function.go index b4a6717f6..f84eb7787 100644 --- a/worker/appm/f/function.go +++ b/worker/appm/f/function.go @@ -20,9 +20,8 @@ package f import ( "fmt" - "github.com/Sirupsen/logrus" - v1 "github.com/goodrain/rainbond/worker/appm/types/v1" + "github.com/goodrain/rainbond/worker/appm/types/v1" corev1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" @@ -54,7 +53,7 @@ func ApplyOne(clientset *kubernetes.Clientset, app *v1.AppService) error { } // update endpoints for _, ep := range app.GetEndpoints() { - ensureEndpoints(ep, clientset) + EnsureEndpoints(ep, clientset) } // update ingress for _, ing := range app.GetIngress() { @@ -76,16 +75,6 @@ func ApplyOne(clientset *kubernetes.Clientset, app *v1.AppService) error { logrus.Warningf("error deleting secret(%v): %v", secret, err) } } - // delete delEndpoints - for _, ep := range app.GetDelEndpoints() { - err := clientset.CoreV1().Endpoints(ep.Namespace).Delete(ep.Name, &metav1.DeleteOptions{}) - if err != nil { - // don't return error, hope it is ok next time - logrus.Warningf("error deleting endpoints(%v): %v", ep, err) - continue - } - logrus.Debugf("successfully deleted endpoints(%v)", ep) - } // delete delServices for _, svc := range app.GetDelServices() { err := clientset.CoreV1().Services(svc.Namespace).Delete(svc.Name, &metav1.DeleteOptions{}) @@ -151,9 +140,9 @@ func ensureSecret(secret *corev1.Secret, clientSet kubernetes.Interface) { } } -func ensureEndpoints(ep *corev1.Endpoints, clientSet kubernetes.Interface) { +// EnsureEndpoints creates or updates endpoints. +func EnsureEndpoints(ep *corev1.Endpoints, clientSet kubernetes.Interface) { _, err := clientSet.CoreV1().Endpoints(ep.Namespace).Update(ep) - if err != nil { if k8sErrors.IsNotFound(err) { _, err := clientSet.CoreV1().Endpoints(ep.Namespace).Create(ep) @@ -166,15 +155,166 @@ func ensureEndpoints(ep *corev1.Endpoints, clientSet kubernetes.Interface) { } } -// If the port has three different values, one of them cannot be 0 -func checkRbdEndpoints(rbdEndpoints []*v1.RbdEndpoints) bool { - if len(rbdEndpoints) < 2 { - return true +// UpgradeIngress is used to update *extensions.Ingress. +func UpgradeIngress(clientset *kubernetes.Clientset, + as *v1.AppService, + old, new []*extensions.Ingress, + handleErr func(msg string, err error) error) error { + var oldMap = make(map[string]*extensions.Ingress, len(old)) + for i, item := range old { + oldMap[item.Name] = old[i] } - for _, item := range rbdEndpoints { - if item.Port == 0 { - return false + for _, n := range new { + if o, ok := oldMap[n.Name]; ok { + n.UID = o.UID + n.ResourceVersion = o.ResourceVersion + ing, err := clientset.ExtensionsV1beta1().Ingresses(n.Namespace).Update(n) + if err != nil { + if err := handleErr(fmt.Sprintf("error updating ingress: %+v: err: %v", + ing, err), err); err != nil { + return err + } + continue + } + as.SetIngress(ing) + delete(oldMap, o.Name) + logrus.Debugf("ServiceID: %s; successfully update ingress: %s", as.ServiceID, ing.Name) + } else { + logrus.Debugf("ingress: %+v", n) + ing, err := clientset.ExtensionsV1beta1().Ingresses(n.Namespace).Create(n) + if err != nil { + if err := handleErr(fmt.Sprintf("error creating ingress: %+v: err: %v", + ing, err), err); err != nil { + return err + } + continue + } + as.SetIngress(ing) + logrus.Debugf("ServiceID: %s; successfully create ingress: %s", as.ServiceID, ing.Name) } } - return true + for _, ing := range oldMap { + if ing != nil { + if err := clientset.ExtensionsV1beta1().Ingresses(ing.Namespace).Delete(ing.Name, + &metav1.DeleteOptions{}); err != nil { + if err := handleErr(fmt.Sprintf("error deleting ingress: %+v: err: %v", + ing, err), err); err != nil { + return err + } + continue + } + logrus.Debugf("ServiceID: %s; successfully delete ingress: %s", as.ServiceID, ing.Name) + } + } + return nil +} + +// UpgradeSecrets is used to update *corev1.Secret. +func UpgradeSecrets(clientset *kubernetes.Clientset, + as *v1.AppService, old, new []*corev1.Secret, + handleErr func(msg string, err error) error) error { + var oldMap = make(map[string]*corev1.Secret, len(old)) + for i, item := range old { + oldMap[item.Name] = old[i] + } + for _, n := range new { + if o, ok := oldMap[n.Name]; ok { + n.UID = o.UID + n.ResourceVersion = o.ResourceVersion + sec, err := clientset.CoreV1().Secrets(n.Namespace).Update(n) + if err != nil { + if err := handleErr(fmt.Sprintf("error updating secret: %+v: err: %v", + sec, err), err); err != nil { + return err + } + continue + } + as.SetSecret(sec) + delete(oldMap, o.Name) + logrus.Debugf("ServiceID: %s; successfully update secret: %s", as.ServiceID, sec.Name) + } else { + sec, err := clientset.CoreV1().Secrets(n.Namespace).Create(n) + if err != nil { + if err := handleErr(fmt.Sprintf("error creating secret: %+v: err: %v", + sec, err), err); err != nil { + return err + } + continue + } + as.SetSecret(sec) + logrus.Debugf("ServiceID: %s; successfully create secret: %s", as.ServiceID, sec.Name) + } + } + for _, sec := range oldMap { + if sec != nil { + if err := clientset.CoreV1().Secrets(sec.Namespace).Delete(sec.Name, &metav1.DeleteOptions{}); err != nil { + if err := handleErr(fmt.Sprintf("error deleting secret: %+v: err: %v", + sec, err), err); err != nil { + return err + } + continue + } + logrus.Debugf("ServiceID: %s; successfully delete secret: %s", as.ServiceID, sec.Name) + } + } + return nil +} + +// UpgradeEndpoints is used to update *corev1.Endpoints. +func UpgradeEndpoints(clientset *kubernetes.Clientset, + as *v1.AppService, old, new []*corev1.Endpoints, + handleErr func(msg string, err error) error) error { + var oldMap = make(map[string]*corev1.Endpoints, len(old)) + for i, item := range old { + oldMap[item.Name] = old[i] + } + for _, n := range new { + if o, ok := oldMap[n.Name]; ok { + ep, err := clientset.CoreV1().Endpoints(n.Namespace).Update(n) + if err != nil { + if e := handleErr(fmt.Sprintf("error updating endpoints: %+v: err: %v", + ep, err), err); e != nil { + return e + } + continue + } + as.AddEndpoints(ep) + delete(oldMap, o.Name) + logrus.Debugf("ServiceID: %s; successfully update endpoints: %s", as.ServiceID, ep.Name) + } else { + _, err := clientset.CoreV1().Endpoints(n.Namespace).Create(n) + if err != nil { + if err := handleErr(fmt.Sprintf("error creating endpoints: %+v: err: %v", + n, err), err); err != nil { + return err + } + continue + } + as.AddEndpoints(n) + logrus.Debugf("ServiceID: %s; successfully create endpoints: %s", as.ServiceID, n.Name) + } + } + for _, sec := range oldMap { + if sec != nil { + if err := clientset.CoreV1().Endpoints(sec.Namespace).Delete(sec.Name, &metav1.DeleteOptions{}); err != nil { + if err := handleErr(fmt.Sprintf("error deleting endpoints: %+v: err: %v", + sec, err), err); err != nil { + return err + } + continue + } + logrus.Debugf("ServiceID: %s; successfully delete endpoints: %s", as.ServiceID, sec.Name) + } + } + return nil +} + +// UpdateEndpoints uses clientset to update the given Endpoints. +func UpdateEndpoints(ep *corev1.Endpoints, clientSet *kubernetes.Clientset) { + _, err := clientSet.CoreV1().Endpoints(ep.Namespace).Update(ep) + if err != nil { + logrus.Warningf("error updating endpoints: %+v; err: %v", ep, err) + return + } + logrus.Debugf("Key: %s/%s; Successfully update endpoints", ep.GetNamespace(), ep.GetName()) } diff --git a/worker/appm/prober/prober.go b/worker/appm/prober/prober.go index 96c65159d..a52d48423 100644 --- a/worker/appm/prober/prober.go +++ b/worker/appm/prober/prober.go @@ -21,15 +21,13 @@ package prober import ( "context" "fmt" - "strconv" - "strings" "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/goodrain/rainbond/db" "github.com/goodrain/rainbond/db/model" uitlprober "github.com/goodrain/rainbond/util/prober" - "github.com/goodrain/rainbond/util/prober/types/v1" + v1 "github.com/goodrain/rainbond/util/prober/types/v1" "github.com/goodrain/rainbond/worker/appm/store" "github.com/goodrain/rainbond/worker/appm/thirdparty/discovery" appmv1 "github.com/goodrain/rainbond/worker/appm/types/v1" @@ -41,8 +39,8 @@ import ( type Prober interface { Start() Stop() - AddProbe(ep *corev1.Endpoints) - StopProbe(ep *corev1.Endpoints) + UpdateProbes(info []*store.ProbeInfo) + StopProbe(uuids []string) } // NewProber creates a new third-party service prober. @@ -100,19 +98,14 @@ func (t *tpProbe) Start() { evt := event.(store.Event) switch evt.Type { case store.CreateEvent: - logrus.Debug("create probe") - ep := evt.Obj.(*corev1.Endpoints) - t.AddProbe(ep) + infos := evt.Obj.([]*store.ProbeInfo) + t.UpdateProbes(infos) case store.UpdateEvent: - logrus.Debug("update probe") - old := evt.Old.(*corev1.Endpoints) - ep := evt.Obj.(*corev1.Endpoints) - t.StopProbe(old) - t.AddProbe(ep) + infos := evt.Obj.([]*store.ProbeInfo) + t.UpdateProbes(infos) case store.DeleteEvent: - logrus.Debug("delete probe") - ep := evt.Obj.(*corev1.Endpoints) - t.StopProbe(ep) + uuids := evt.Obj.([]string) + t.StopProbe(uuids) } case <-t.ctx.Done(): return @@ -126,83 +119,83 @@ func (t *tpProbe) Stop() { t.cancel() } -func (t *tpProbe) AddProbe(ep *corev1.Endpoints) { - service, probeInfo, sid := t.createServices(ep) - if service == nil { - logrus.Debugf("Empty service, stop creating probe") - return - } - ip := ep.GetLabels()["ip"] - port, _ := strconv.Atoi(ep.GetLabels()["port"]) - // watch - logrus.Debug("enable watcher...") - if t.utilprober.CheckAndAddService(service) { - logrus.Debugf("Service: %+v; Exists", service) - return - } - go func(service *v1.Service) { - watcher := t.utilprober.WatchServiceHealthy(service.Name) - t.utilprober.EnableWatcher(watcher.GetServiceName(), watcher.GetID()) - defer watcher.Close() - defer t.utilprober.DisableWatcher(watcher.GetServiceName(), watcher.GetID()) - for { - select { - case event := <-watcher.Watch(): - if event == nil { - return - } - switch event.Status { - case v1.StatHealthy: - obj := &appmv1.RbdEndpoint{ - UUID: service.Name, - IP: ip, - Port: port, - Sid: sid, +func (t *tpProbe) UpdateProbes(infos []*store.ProbeInfo) { + var services []*v1.Service + for _, info := range infos { + service, probeInfo := t.createServices(info) + if service == nil { + logrus.Debugf("Empty service, stop creating probe") + continue + } + services = append(services, service) + // watch + if t.utilprober.CheckIfExist(service) { + continue + } + go func(service *v1.Service, info *store.ProbeInfo) { + watcher := t.utilprober.WatchServiceHealthy(service.Name) + t.utilprober.EnableWatcher(watcher.GetServiceName(), watcher.GetID()) + defer watcher.Close() + defer t.utilprober.DisableWatcher(watcher.GetServiceName(), watcher.GetID()) + for { + select { + case event := <-watcher.Watch(): + if event == nil { + return } - t.updateCh.In() <- discovery.Event{ - Type: discovery.HealthEvent, - Obj: obj, - } - case v1.StatDeath, v1.StatUnhealthy: - if event.ErrorNumber > service.ServiceHealth.MaxErrorsNum { - if probeInfo.Mode == model.OfflineFailureAction.String() { - obj := &appmv1.RbdEndpoint{ - UUID: service.Name, - IP: ip, - Port: port, - Sid: sid, - } - t.updateCh.In() <- discovery.Event{ - Type: discovery.DeleteEvent, - Obj: obj, - } - } else { - obj := &appmv1.RbdEndpoint{ - UUID: service.Name, - IP: ip, - Port: port, - Sid: sid, - } - t.updateCh.In() <- discovery.Event{ - Type: discovery.UnhealthyEvent, - Obj: obj, + switch event.Status { + case v1.StatHealthy: + obj := &appmv1.RbdEndpoint{ + UUID: info.UUID, + IP: info.IP, + Port: int(info.Port), + Sid: info.Sid, + } + t.updateCh.In() <- discovery.Event{ + Type: discovery.HealthEvent, + Obj: obj, + } + case v1.StatDeath, v1.StatUnhealthy: + if event.ErrorNumber > service.ServiceHealth.MaxErrorsNum { + if probeInfo.Mode == model.OfflineFailureAction.String() { + obj := &appmv1.RbdEndpoint{ + UUID: info.UUID, + IP: info.IP, + Port: int(info.Port), + Sid: info.Sid, + } + t.updateCh.In() <- discovery.Event{ + Type: discovery.DeleteEvent, + Obj: obj, + } + } else { + obj := &appmv1.RbdEndpoint{ + UUID: info.UUID, + IP: info.IP, + Port: int(info.Port), + Sid: info.Sid, + } + t.updateCh.In() <- discovery.Event{ + Type: discovery.UnhealthyEvent, + Obj: obj, + } } } } + case <-t.ctx.Done(): + // TODO: should stop for one service, not all services. + return } - case <-t.ctx.Done(): - return } - } - }(service) - // start - t.utilprober.UpdateServicesProbe([]*v1.Service{service}) + }(service, info) + } + t.utilprober.UpdateServicesProbe(services) } -func (t *tpProbe) StopProbe(ep *corev1.Endpoints) { - name := t.createServiceNames(ep) - logrus.Debugf("Name: %s; Stop probe.", name) - t.utilprober.StopProbes([]string{name}) +func (t *tpProbe) StopProbe(uuids []string) { + for _, name := range uuids { + t.utilprober.StopProbes([]string{name}) + } } // GetProbeInfo returns probe info associated with sid. @@ -210,12 +203,11 @@ func (t *tpProbe) StopProbe(ep *corev1.Endpoints) { // If there is no probe in the database, return a default probe func (t *tpProbe) GetProbeInfo(sid string) (*model.TenantServiceProbe, error) { probes, err := t.dbm.ServiceProbeDao().GetServiceProbes(sid) - if err != nil || probes == nil || len(probes) == 0 || probes[0].IsUsed == 0 { + if err != nil || probes == nil || len(probes) == 0 || *(probes[0].IsUsed) == 0 { if err != nil { logrus.Warningf("ServiceID: %s; error getting probes: %v", sid, err) } // no defined probe, use default one - logrus.Debugf("no defined probe, use default one") return &model.TenantServiceProbe{ Scheme: "tcp", PeriodSecond: 5, @@ -226,31 +218,23 @@ func (t *tpProbe) GetProbeInfo(sid string) (*model.TenantServiceProbe, error) { return probes[0], nil } -func (t *tpProbe) createServices(ep *corev1.Endpoints) (*v1.Service, *model.TenantServiceProbe, string) { - sid := ep.GetLabels()["service_id"] - ip := ep.GetLabels()["ip"] - port := ep.GetLabels()["port"] - if strings.TrimSpace(sid) == "" { - logrus.Warningf("Endpoints key: %s; ServiceID not found, stop creating probe", - fmt.Sprintf("%s/%s", ep.Namespace, ep.Name)) - return nil, nil, "" - } - probeInfo, err := t.GetProbeInfo(sid) +func (t *tpProbe) createServices(probeInfo *store.ProbeInfo) (*v1.Service, *model.TenantServiceProbe) { + tsp, err := t.GetProbeInfo(probeInfo.Sid) if err != nil { logrus.Warningf("ServiceID: %s; Unexpected error occurred, ignore the creation of "+ - "probes: %s", sid, err.Error()) - return nil, nil, "" + "probes: %s", probeInfo.Sid, err.Error()) + return nil, nil } - if probeInfo.Mode == "liveness" { - probeInfo.Mode = model.IgnoreFailureAction.String() + if tsp.Mode == "liveness" { + tsp.Mode = model.IgnoreFailureAction.String() } - service := createService(probeInfo) - service.Name = ep.GetLabels()["uuid"] - portint, _ := strconv.Atoi(port) - service.ServiceHealth.Port = portint - service.ServiceHealth.Name = service.Name // TODO: no need? - service.ServiceHealth.Address = fmt.Sprintf("%s:%s", ip, port) - return service, probeInfo, sid + service := createService(tsp) + service.Sid = probeInfo.Sid + service.Name = probeInfo.UUID + service.ServiceHealth.Port = int(probeInfo.Port) + service.ServiceHealth.Name = service.Name + service.ServiceHealth.Address = fmt.Sprintf("%s:%d", probeInfo.IP, probeInfo.Port) + return service, tsp } func (t *tpProbe) createServiceNames(ep *corev1.Endpoints) string { diff --git a/worker/appm/store/store.go b/worker/appm/store/store.go index 5972e72b6..f3819dc2b 100644 --- a/worker/appm/store/store.go +++ b/worker/appm/store/store.go @@ -20,6 +20,7 @@ package store import ( "context" + "encoding/json" "fmt" "sync" "time" @@ -78,7 +79,14 @@ const ( type Event struct { Type EventType Obj interface{} - Old interface{} +} + +// ProbeInfo holds the context of a probe. +type ProbeInfo struct { + Sid string `json:"sid"` + UUID string `json:"uuid"` + IP string `json:"ip"` + Port int32 `json:"port"` } //appRuntimeStore app runtime store @@ -154,21 +162,22 @@ func NewStore(clientset *kubernetes.Clientset, epEventHandler := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { ep := obj.(*corev1.Endpoints) - logrus.Debugf("received add endpoints: %+v", ep) serviceID := ep.Labels["service_id"] version := ep.Labels["version"] createrID := ep.Labels["creater_id"] if serviceID != "" && createrID != "" { appservice, err := store.getAppService(serviceID, version, createrID, true) if err == conversion.ErrServiceNotFound { - store.conf.KubeClient.CoreV1().Endpoints(ep.Namespace).Delete(ep.Name, &metav1.DeleteOptions{}) + logrus.Debugf("ServiceID: %s; Action: AddFunc; service not found", serviceID) } if appservice != nil { appservice.AddEndpoints(ep) - if isThirdParty(ep) { + if isThirdParty(ep) && ep.Subsets != nil && len(ep.Subsets) > 0 { + logrus.Debugf("received add endpoints: %+v", ep) + probeInfos := listProbeInfos(ep, serviceID) probeCh.In() <- Event{ Type: CreateEvent, - Obj: obj, + Obj: probeInfos, } } return @@ -177,7 +186,6 @@ func NewStore(clientset *kubernetes.Clientset, }, DeleteFunc: func(obj interface{}) { ep := obj.(*corev1.Endpoints) - logrus.Debugf("received delete endpoints: %+v", ep) serviceID := ep.Labels["service_id"] version := ep.Labels["version"] createrID := ep.Labels["creater_id"] @@ -186,12 +194,18 @@ func NewStore(clientset *kubernetes.Clientset, if appservice != nil { appservice.DelEndpoints(ep) if appservice.IsClosed() { + logrus.Debugf("ServiceID: %s; Action: DeleteFunc;service is closed", serviceID) store.DeleteAppService(appservice) } if isThirdParty(ep) { + logrus.Debugf("received delete endpoints: %+v", ep) + var uuids []string + for _, item := range ep.Subsets { + uuids = append(uuids, item.Ports[0].Name) + } probeCh.In() <- Event{ Type: DeleteEvent, - Obj: obj, + Obj: uuids, } } } @@ -206,20 +220,18 @@ func NewStore(clientset *kubernetes.Clientset, if serviceID != "" && createrID != "" { appservice, err := store.getAppService(serviceID, version, createrID, true) if err == conversion.ErrServiceNotFound { - logrus.Debug("ServiceID: error service not found") - store.conf.KubeClient.CoreV1().Endpoints(cep.Namespace).Delete(cep.Name, &metav1.DeleteOptions{}) + logrus.Debugf("ServiceID: %s; Action: UpdateFunc; service not found", serviceID) } if appservice != nil { appservice.AddEndpoints(cep) if isThirdParty(cep) { + curInfos := listProbeInfos(cep, serviceID) probeCh.In() <- Event{ Type: UpdateEvent, - Obj: cur, - Old: old, + Obj: curInfos, } } } - //} } }, } @@ -236,6 +248,67 @@ func NewStore(clientset *kubernetes.Clientset, return store } +func listProbeInfos(ep *corev1.Endpoints, sid string) []*ProbeInfo { + var probeInfos []*ProbeInfo + for _, subset := range ep.Subsets { + uuid := subset.Ports[0].Name + port := subset.Ports[0].Port + for _, address := range subset.NotReadyAddresses { + info := &ProbeInfo{ + Sid: sid, + UUID: uuid, + IP: address.IP, + Port: port, + } + probeInfos = append(probeInfos, info) + } + for _, address := range subset.Addresses { + info := &ProbeInfo{ + Sid: sid, + UUID: uuid, + IP: address.IP, + Port: port, + } + probeInfos = append(probeInfos, info) + } + } + return probeInfos +} + +func upgradeProbe(ch chan<- interface{}, old, cur []*ProbeInfo) { + ob, _ := json.Marshal(old) + cb, _ := json.Marshal(cur) + logrus.Debugf("Old probe infos: %s", string(ob)) + logrus.Debugf("Current probe infos: %s", string(cb)) + oldMap := make(map[string]*ProbeInfo, len(old)) + for i := 0; i < len(old); i++ { + oldMap[old[i].UUID] = old[i] + } + for _, c := range cur { + if info := oldMap[c.UUID]; info != nil { + delete(oldMap, c.UUID) + logrus.Debugf("UUID: %s; update probe", c.UUID) + ch <- Event{ + Type: UpdateEvent, + Obj: c, + } + } else { + logrus.Debugf("UUID: %s; create probe", c.UUID) + ch <- Event{ + Type: CreateEvent, + Obj: []*ProbeInfo{c}, + } + } + } + for _, info := range oldMap { + logrus.Debugf("UUID: %s; delete probe", info.UUID) + ch <- Event{ + Type: DeleteEvent, + Obj: info, + } + } +} + func (a *appRuntimeStore) init() error { //init leader namespace leaderNamespace := a.conf.LeaderElectionNamespace diff --git a/worker/appm/thirdparty/discovery/discovery.go b/worker/appm/thirdparty/discovery/discovery.go index 2c9a93604..f9988450b 100644 --- a/worker/appm/thirdparty/discovery/discovery.go +++ b/worker/appm/thirdparty/discovery/discovery.go @@ -35,9 +35,11 @@ const ( // UpdateEvent event associated with an object update in a service discovery center UpdateEvent EventType = "UPDATE" // DeleteEvent event associated when an object is removed from a service discovery center - DeleteEvent EventType = "DELETE" + DeleteEvent EventType = "DELETE" + // UnhealthyEvent - UnhealthyEvent EventType = "UNHEALTHY" - HealthEvent EventType = "HEALTH" + // HealthEvent - + HealthEvent EventType = "HEALTH" ) // Event holds the context of an event. diff --git a/worker/appm/thirdparty/thirdparty.go b/worker/appm/thirdparty/thirdparty.go index 4bf1a646d..5c632d543 100644 --- a/worker/appm/thirdparty/thirdparty.go +++ b/worker/appm/thirdparty/thirdparty.go @@ -21,19 +21,18 @@ package thirdparty import ( "encoding/json" "fmt" - "github.com/goodrain/rainbond/worker/util" - "strconv" + "sync" "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/goodrain/rainbond/db" "github.com/goodrain/rainbond/db/model" + "github.com/goodrain/rainbond/worker/appm/f" "github.com/goodrain/rainbond/worker/appm/store" "github.com/goodrain/rainbond/worker/appm/thirdparty/discovery" "github.com/goodrain/rainbond/worker/appm/types/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -63,7 +62,7 @@ func NewThirdPartier(clientset *kubernetes.Clientset, } type thirdparty struct { - clientset kubernetes.Interface + clientset *kubernetes.Clientset store store.Storer // a collection of stop channel for every service. @@ -87,13 +86,14 @@ func (t *thirdparty) Start() { } logrus.Debugf("Received event: %+v", evt) if evt.Type == v1.StartEvent { // no need to distinguish between event types + needWatch := false stopCh := t.svcStopCh[evt.Sid] - if stopCh != nil { + if stopCh == nil { logrus.Debugf("ServiceID: %s; already started.", evt.Sid) - continue + needWatch = true + t.svcStopCh[evt.Sid] = make(chan struct{}) } - t.svcStopCh[evt.Sid] = make(chan struct{}) - go t.runStart(evt.Sid) + go t.runStart(evt.Sid, needWatch) } if evt.Type == v1.StopEvent { stopCh := t.svcStopCh[evt.Sid] @@ -114,7 +114,7 @@ func (t *thirdparty) Start() { go t.runUpdate(devent) case <-t.stopCh: for _, stopCh := range t.svcStopCh { - close(stopCh) + close(stopCh) // TODO: close of closed channel } break } @@ -122,38 +122,33 @@ func (t *thirdparty) Start() { }() } -func (t *thirdparty) runStart(sid string) { - logrus.Debugf("ServiceID: %s; run start...", sid) +func (t *thirdparty) runStart(sid string, needWatch bool) { as := t.store.GetAppService(sid) - // TODO: when an error occurs, consider retrying. - rbdeps, d := t.ListRbdEndpoints(sid) - b, _ := json.Marshal(rbdeps) - logrus.Debugf("ServiceID: %s; rbd endpoints: %+v", sid, string(b)) - // TODO: empty rbdeps - if rbdeps == nil || len(rbdeps) == 0 { - logrus.Warningf("ServiceID: %s;Empty rbd endpoints, stop starting third-party service.", sid) + var err error + for i := 3; i > 0; i-- { // retry 3 times + rbdeps, ir := t.ListRbdEndpoints(sid) + if rbdeps == nil || len(rbdeps) == 0 { + logrus.Warningf("ServiceID: %s;Empty rbd endpoints, stop starting third-party service.", sid) + continue + } + + var eps []*corev1.Endpoints + eps, err = t.k8sEndpoints(as, rbdeps) + if err != nil { + logrus.Warningf("ServiceID: %s; error creating k8s endpoints: %s", sid, err.Error()) + continue + } + for _, ep := range eps { + f.EnsureEndpoints(ep, t.clientset) + } + + if needWatch && ir != nil { + ir.Watch() + } + logrus.Infof("ServiceID: %s; successfully running start task", sid) return } - - eps, err := t.createK8sEndpoints(as, rbdeps) - if err != nil { - logrus.Errorf("ServiceID: %s; error creating k8s endpoints: %s", sid, err.Error()) - return - } - // find out old endpoints, and delete it. - old := as.GetEndpoints() - // TODO: can do better - del := findDeletedEndpoints(old, eps) - for _, ep := range del { - deleteEndpoints(ep, t.clientset) - } - for _, ep := range eps { - ensureEndpoints(ep, t.clientset) - } - - if d != nil { - d.Watch() - } + logrus.Errorf("ServiceID: %s; error running start task: %v", sid, err) } // ListRbdEndpoints lists all rbd endpoints, include static and dynamic. @@ -181,28 +176,20 @@ func (t *thirdparty) ListRbdEndpoints(sid string) ([]*v1.RbdEndpoint, Interacter return res, d } -func findDeletedEndpoints(old, new []*corev1.Endpoints) []*corev1.Endpoints { - if old == nil { - logrus.Debugf("empty old endpoints.") - return nil - } - var res []*corev1.Endpoints - for _, o := range old { - del := true - for _, n := range new { - if o.Name == n.Name { - del = false - break +func deleteSubset(as *v1.AppService, rbdep *v1.RbdEndpoint) { + eps := as.GetEndpoints() + for _, ep := range eps { + for idx, item := range ep.Subsets { + if item.Ports[0].Name == rbdep.UUID { + logrus.Debugf("UUID: %s; subset deleted", rbdep.UUID) + ep.Subsets[idx] = ep.Subsets[len(ep.Subsets)-1] + ep.Subsets = ep.Subsets[:len(ep.Subsets)-1] } } - if del { - res = append(res, o) - } } - return res } -func (t *thirdparty) createK8sEndpoints(as *v1.AppService, epinfo []*v1.RbdEndpoint) ([]*corev1.Endpoints, error) { +func (t *thirdparty) k8sEndpoints(as *v1.AppService, epinfo []*v1.RbdEndpoint) ([]*corev1.Endpoints, error) { ports, err := db.GetManager().TenantServicesPortDao().GetPortsByServiceID(as.ServiceID) if err != nil { return nil, err @@ -213,258 +200,201 @@ func (t *thirdparty) createK8sEndpoints(as *v1.AppService, epinfo []*v1.RbdEndpo } p := ports[0] - logrus.Debugf("create outer third-party service") - f := func() []*corev1.Endpoints { - var eps []*corev1.Endpoints - for _, epi := range epinfo { - port, realport := func(targetPort int, realPort int) (int32, bool) { // final port - if realPort == 0 { - return int32(targetPort), false - } - return int32(realPort), true - }(p.ContainerPort, epi.Port) - ep := corev1.Endpoints{} - ep.Namespace = as.TenantID - if p.IsInnerService { - ep.Name = util.CreateEndpointsName(as.TenantName, as.ServiceAlias, epi.UUID) - ep.Name = epi.UUID - ep.Labels = as.GetCommonLabels(map[string]string{ - "name": as.ServiceAlias + "Service", - "service-kind": model.ServiceKindThirdParty.String(), - }) - } - if p.IsOuterService { - ep.Name = util.CreateEndpointsName(as.TenantName, as.ServiceAlias, epi.UUID) + "out" - ep.Labels = as.GetCommonLabels(map[string]string{ - "name": as.ServiceAlias + "ServiceOUT", - "service-kind": model.ServiceKindThirdParty.String(), - }) - } - ep.Labels["uuid"] = epi.UUID - ep.Labels["ip"] = epi.IP - ep.Labels["port"] = strconv.Itoa(int(port)) - ep.Labels["real-port"] = strconv.FormatBool(realport) - subset := corev1.EndpointSubset{ - Ports: []corev1.EndpointPort{ - { - Port: port, - }, - }, - Addresses: []corev1.EndpointAddress{ - { - IP: epi.IP, - }, - }, - } - ep.Subsets = append(ep.Subsets, subset) - eps = append(eps, &ep) - } - return eps - } - var res []*corev1.Endpoints if p.IsInnerService { - res = append(res, f()...) + ep := &corev1.Endpoints{} + ep.Namespace = as.TenantID + // inner or outer + if p.IsInnerService { + ep.Name = fmt.Sprintf("service-%d-%d", p.ID, p.ContainerPort) + ep.Labels = as.GetCommonLabels(map[string]string{ + "name": as.ServiceAlias + "Service", + "service-kind": model.ServiceKindThirdParty.String(), + }) + } + res = append(res, ep) } if p.IsOuterService { - res = append(res, f()...) + ep := &corev1.Endpoints{} + ep.Namespace = as.TenantID + // inner or outer + if p.IsOuterService { + ep.Name = fmt.Sprintf("service-%d-%dout", p.ID, p.ContainerPort) + ep.Labels = as.GetCommonLabels(map[string]string{ + "name": as.ServiceAlias + "ServiceOUT", + "service-kind": model.ServiceKindThirdParty.String(), + }) + } + res = append(res, ep) + } + + var subsets []corev1.EndpointSubset + for _, epi := range epinfo { + subset := corev1.EndpointSubset{ + Ports: []corev1.EndpointPort{ + { + Name: epi.UUID, + Port: func(targetPort int, realPort int) int32 { + if realPort == 0 { + return int32(targetPort) + } + return int32(realPort) + }(p.ContainerPort, epi.Port), + Protocol: corev1.ProtocolTCP, + }, + }, + Addresses: []corev1.EndpointAddress{ + { + IP: epi.IP, + }, + }, + } + subsets = append(subsets, subset) + } + for _, item := range res { + item.Subsets = subsets } return res, nil } -func deleteEndpoints(ep *corev1.Endpoints, clientset kubernetes.Interface) { - err := clientset.CoreV1().Endpoints(ep.Namespace).Delete(ep.Name, &metav1.DeleteOptions{}) +func updateSubset(as *v1.AppService, rbdep *v1.RbdEndpoint) error { + ports, err := db.GetManager().TenantServicesPortDao().GetPortsByServiceID(as.ServiceID) if err != nil { - logrus.Debugf("Ignore; error deleting endpoints%+v: %v", ep, err) + return err } -} - -func ensureEndpoints(ep *corev1.Endpoints, clientSet kubernetes.Interface) { - logrus.Debugf("ensure endpoints: %+v", ep) - _, err := clientSet.CoreV1().Endpoints(ep.Namespace).Update(ep) - - if err != nil { - if k8sErrors.IsNotFound(err) { - _, err := clientSet.CoreV1().Endpoints(ep.Namespace).Create(ep) - if err != nil { - logrus.Warningf("error creating endpoints %+v: %v", ep, err) + // third-party service can only have one port + if ports == nil || len(ports) == 0 { + return fmt.Errorf("Port not found") + } + p := ports[0] + subset := corev1.EndpointSubset{ + Ports: []corev1.EndpointPort{ + { + Name: rbdep.UUID, + Port: func(targetPort int, realPort int) int32 { + if realPort == 0 { + return int32(targetPort) + } + return int32(realPort) + }(p.ContainerPort, rbdep.Port), + Protocol: corev1.ProtocolTCP, + }, + }, + Addresses: []corev1.EndpointAddress{ + { + IP: rbdep.IP, + }, + }, + } + for _, ep := range as.GetEndpoints() { + exist := false + for idx, item := range ep.Subsets { + if item.Ports[0].Name == subset.Ports[0].Name { + ep.Subsets[idx] = item + exist = true + break } - return } - logrus.Warningf("error updating endpoints %+v: %v", ep, err) - } -} - -func ensureConfigMap(cm *corev1.ConfigMap, clientSet kubernetes.Interface) { - _, err := clientSet.CoreV1().ConfigMaps(cm.Namespace).Update(cm) - - if err != nil { - if k8sErrors.IsNotFound(err) { - _, err := clientSet.CoreV1().ConfigMaps(cm.Namespace).Create(cm) - if err != nil { - logrus.Warningf("error creating ConfigMaps %+v: %v", cm, err) - } - return + if !exist { + ep.Subsets = append(ep.Subsets, subset) } - logrus.Warningf("error updating ConfigMaps %+v: %v", cm, err) } + return nil } func (t *thirdparty) runUpdate(event discovery.Event) { - ep := event.Obj.(*v1.RbdEndpoint) - as := t.store.GetAppService(ep.Sid) - switch event.Type { - case discovery.CreateEvent: - b, _ := json.Marshal(ep) - logrus.Debugf("Run update; Event received: Type: %v; Body: %s", event.Type, string(b)) - endpoints, err := t.createK8sEndpoints(as, []*v1.RbdEndpoint{ep}) - if err != nil { - logrus.Warningf("ServiceID: %s; error creating k8s endpoints struct: %s", - ep.Sid, err.Error()) - return - } - for _, ep := range endpoints { - ensureEndpoints(ep, t.clientset) - } - case discovery.UpdateEvent: - b, _ := json.Marshal(ep) - logrus.Debugf("Run update; Event received: Type: %v; Body: %s", event.Type, string(b)) - // TODO: Compare old and new endpoints - // TODO: delete old endpoints - if !ep.IsOnline { - eps := ListOldEndpoints(as, ep) - for _, item := range eps { - deleteEndpoints(item, t.clientset) + fc := func(as *v1.AppService, rbdep *v1.RbdEndpoint, ready bool, msg string, condition func(subset corev1.EndpointSubset) bool) { + var wait sync.WaitGroup + go func() { + wait.Add(1) + defer wait.Done() + for _, ep := range as.GetEndpoints() { + for idx, subset := range ep.Subsets { + if subset.Ports[0].Name == rbdep.UUID && condition(subset) { + logrus.Debugf("Executed; health: %v; msg: %s", ready, msg) + ep.Subsets[idx] = createSubset(rbdep, ready) + f.UpdateEndpoints(ep, t.clientset) + } + } } - return - } - endpoints, err := t.createK8sEndpoints(as, []*v1.RbdEndpoint{ep}) + }() + wait.Wait() + } + + rbdep := event.Obj.(*v1.RbdEndpoint) + as := t.store.GetAppService(rbdep.Sid) + b, _ := json.Marshal(rbdep) + msg := fmt.Sprintf("Run update; Event received: Type: %v; Body: %s", event.Type, string(b)) + switch event.Type { + case discovery.CreateEvent, discovery.UpdateEvent: + logrus.Debug(msg) + err := updateSubset(as, rbdep) if err != nil { - logrus.Warningf("ServiceID: %s; error creating k8s endpoints struct: %s", - ep.Sid, err.Error()) + logrus.Warningf("ServiceID: %s; error adding subset: %s", + rbdep.Sid, err.Error()) return } - for _, ep := range endpoints { - ensureEndpoints(ep, t.clientset) - } + _ = f.UpgradeEndpoints(t.clientset, as, as.GetEndpoints(), as.GetEndpoints(), + func(msg string, err error) error { + logrus.Warning(msg) + return nil + }) case discovery.DeleteEvent: - b, _ := json.Marshal(ep) - logrus.Debugf("Run update; Event received: Type: %v; Body: %s", event.Type, string(b)) - eps := ListOldEndpoints(as, ep) - for _, item := range eps { - deleteEndpoints(item, t.clientset) - } + logrus.Debug(msg) + deleteSubset(as, rbdep) + eps := as.GetEndpoints() + _ = f.UpgradeEndpoints(t.clientset, as, as.GetEndpoints(), eps, + func(msg string, err error) error { + logrus.Warning(msg) + return nil + }) case discovery.HealthEvent: - subset := createSubset(ep, false) - eps := ListOldEndpoints(as, ep) - for _, ep := range eps { - if !isHealth(ep) { - ep.Subsets = []corev1.EndpointSubset{ - subset, - } - ensureEndpoints(ep, t.clientset) - } + isUnhealthy := func(subset corev1.EndpointSubset) bool { + return !isHealthy(subset) } + fc(as, rbdep, true, msg, isUnhealthy) case discovery.UnhealthyEvent: - subset := createSubset(ep, true) - eps := ListOldEndpoints(as, ep) - for _, ep := range eps { - if isHealth(ep) { - ep.Subsets = []corev1.EndpointSubset{ - subset, - } - ensureEndpoints(ep, t.clientset) - } - } + fc(as, rbdep, false, msg, isHealthy) } } func (t *thirdparty) runDelete(sid string) { as := t.store.GetAppService(sid) // TODO: need to delete? - - if services := as.GetServices(); services != nil { - for _, service := range services { - err := t.clientset.CoreV1().Services(as.TenantID).Delete(service.Name, &metav1.DeleteOptions{}) - if err != nil && !errors.IsNotFound(err) { - logrus.Warningf("error deleting service: %v", err) - } - } - } - if secrets := as.GetSecrets(); secrets != nil { - for _, secret := range secrets { - if secret != nil { - err := t.clientset.CoreV1().Secrets(as.TenantID).Delete(secret.Name, &metav1.DeleteOptions{}) - if err != nil && !errors.IsNotFound(err) { - logrus.Warningf("error deleting secrets: %v", err) - } - t.store.OnDelete(secret) - } - } - } - if ingresses := as.GetIngress(); ingresses != nil { - for _, ingress := range ingresses { - err := t.clientset.ExtensionsV1beta1().Ingresses(as.TenantID).Delete(ingress.Name, &metav1.DeleteOptions{}) - if err != nil && !errors.IsNotFound(err) { - logrus.Warningf("error deleting ingress: %v", err) - } - t.store.OnDelete(ingress) - } - } - if configs := as.GetConfigMaps(); configs != nil { - for _, config := range configs { - err := t.clientset.CoreV1().ConfigMaps(as.TenantID).Delete(config.Name, &metav1.DeleteOptions{}) - if err != nil && !errors.IsNotFound(err) { - logrus.Warningf("error deleting config map: %v", err) - } - t.store.OnDelete(config) - } - } if eps := as.GetEndpoints(); eps != nil { for _, ep := range eps { logrus.Debugf("Endpoints delete: %+v", ep) err := t.clientset.CoreV1().Endpoints(as.TenantID).Delete(ep.Name, &metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { - logrus.Warningf("error deleting endpoin empty old app servicets: %v", err) + logrus.Warningf("error deleting endpoint empty old app endpoints: %v", err) } t.store.OnDelete(ep) } } } -func ListOldEndpoints(as *v1.AppService, ep *v1.RbdEndpoint) []*corev1.Endpoints { - var res []*corev1.Endpoints - for _, item := range as.GetEndpoints() { - if item.GetLabels()["uuid"] == ep.UUID { - res = append(res, item) - } - } - return res -} - -func createSubset(ep *v1.RbdEndpoint, notReady bool) corev1.EndpointSubset { +func createSubset(ep *v1.RbdEndpoint, ready bool) corev1.EndpointSubset { address := corev1.EndpointAddress{ IP: ep.IP, } port := corev1.EndpointPort{ - Port: int32(ep.Port), + Name: ep.UUID, + Port: int32(ep.Port), + Protocol: corev1.ProtocolTCP, } subset := corev1.EndpointSubset{} - if notReady { - subset.NotReadyAddresses = append(subset.Addresses, address) - } else { + if ready { subset.Addresses = append(subset.Addresses, address) + } else { + subset.NotReadyAddresses = append(subset.NotReadyAddresses, address) } subset.Ports = append(subset.Ports, port) return subset } -func isHealth(ep *corev1.Endpoints) bool { - if ep.Subsets == nil || len(ep.Subsets) == 0 { - return false - } - if ep.Subsets[0].Addresses != nil && len(ep.Subsets[0].Addresses) > 0 { +func isHealthy(subset corev1.EndpointSubset) bool { + if subset.Addresses != nil && len(subset.Addresses) > 0 { return true } return false diff --git a/worker/appm/types/v1/v1.go b/worker/appm/types/v1/v1.go index a41df16b3..c0d23d0a7 100644 --- a/worker/appm/types/v1/v1.go +++ b/worker/appm/types/v1/v1.go @@ -23,6 +23,8 @@ import ( "os" "strconv" + "github.com/goodrain/rainbond/builder" + "github.com/Sirupsen/logrus" "github.com/goodrain/rainbond/db/model" "github.com/goodrain/rainbond/event" @@ -104,7 +106,6 @@ type AppService struct { services []*corev1.Service delServices []*corev1.Service endpoints []*corev1.Endpoints - delEndpoints []*corev1.Endpoints configMaps []*corev1.ConfigMap ingresses []*extensions.Ingress delIngs []*extensions.Ingress // ingresses which need to be deleted @@ -317,11 +318,6 @@ func (a *AppService) GetEndpointsByName(name string) *corev1.Endpoints { return nil } -// GetDelEndpoints returns endpoints that need to be deleted in AppService -func (a *AppService) GetDelEndpoints() []*corev1.Endpoints { - return a.delEndpoints -} - //DelEndpoints deletes *corev1.Endpoints func (a *AppService) DelEndpoints(ep *corev1.Endpoints) { for i, c := range a.endpoints { @@ -576,7 +572,7 @@ func GetTCPMeshImageName() string { if d := os.Getenv("TCPMESH_DEFAULT_IMAGE_NAME"); d != "" { return d } - return "goodrain.me/mesh_plugin" + return builder.REGISTRYDOMAIN + "/mesh_plugin" } //GetProbeMeshImageName get probe init mesh image name @@ -584,5 +580,5 @@ func GetProbeMeshImageName() string { if d := os.Getenv("PROBE_MESH_IMAGE_NAME"); d != "" { return d } - return "goodrain.me/rbd-init-probe" + return builder.REGISTRYDOMAIN + "/rbd-init-probe" } diff --git a/worker/master/volumes/provider/lib/controller/controller.go b/worker/master/volumes/provider/lib/controller/controller.go index 9584ede05..50dadea5b 100644 --- a/worker/master/volumes/provider/lib/controller/controller.go +++ b/worker/master/volumes/provider/lib/controller/controller.go @@ -615,7 +615,8 @@ func (ctrl *ProvisionController) processNextClaimWorkItem() bool { if err := ctrl.syncClaimHandler(key); err != nil { if ctrl.claimQueue.NumRequeues(obj) < ctrl.failedProvisionThreshold { - logrus.Warningf("Retrying syncing claim %q because failures %v < threshold %v", key, ctrl.claimQueue.NumRequeues(obj), ctrl.failedProvisionThreshold) + logrus.Warningf("Retrying syncing claim %q because failures %v < threshold %v", + key, ctrl.claimQueue.NumRequeues(obj), ctrl.failedProvisionThreshold) ctrl.claimQueue.AddRateLimited(obj) } else { logrus.Errorf("Giving up syncing claim %q because failures %v >= threshold %v", key, ctrl.claimQueue.NumRequeues(obj), ctrl.failedProvisionThreshold) diff --git a/worker/server/pb/app_runtime_server.pb.go b/worker/server/pb/app_runtime_server.pb.go index bd6f875c4..788d45ad9 100644 --- a/worker/server/pb/app_runtime_server.pb.go +++ b/worker/server/pb/app_runtime_server.pb.go @@ -427,10 +427,11 @@ type DeployInfo struct { Deployment string `protobuf:"bytes,3,opt,name=deployment,proto3" json:"deployment,omitempty"` Pods map[string]string `protobuf:"bytes,4,rep,name=pods,proto3" json:"pods,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Services map[string]string `protobuf:"bytes,5,rep,name=services,proto3" json:"services,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Secrets map[string]string `protobuf:"bytes,6,rep,name=secrets,proto3" json:"secrets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Ingresses map[string]string `protobuf:"bytes,7,rep,name=ingresses,proto3" json:"ingresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Replicatset map[string]string `protobuf:"bytes,8,rep,name=replicatset,proto3" json:"replicatset,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + Endpoints map[string]string `protobuf:"bytes,6,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Secrets map[string]string `protobuf:"bytes,7,rep,name=secrets,proto3" json:"secrets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Ingresses map[string]string `protobuf:"bytes,8,rep,name=ingresses,proto3" json:"ingresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Replicatset map[string]string `protobuf:"bytes,9,rep,name=replicatset,proto3" json:"replicatset,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -496,6 +497,13 @@ func (m *DeployInfo) GetServices() map[string]string { return nil } +func (m *DeployInfo) GetEndpoints() map[string]string { + if m != nil { + return m.Endpoints + } + return nil +} + func (m *DeployInfo) GetSecrets() map[string]string { if m != nil { return m.Secrets @@ -916,6 +924,7 @@ func init() { proto.RegisterMapType((map[string]*Container)(nil), "pb.ServiceAppPod.ContainersEntry") proto.RegisterType((*Container)(nil), "pb.Container") proto.RegisterType((*DeployInfo)(nil), "pb.DeployInfo") + proto.RegisterMapType((map[string]string)(nil), "pb.DeployInfo.EndpointsEntry") proto.RegisterMapType((map[string]string)(nil), "pb.DeployInfo.IngressesEntry") proto.RegisterMapType((map[string]string)(nil), "pb.DeployInfo.PodsEntry") proto.RegisterMapType((map[string]string)(nil), "pb.DeployInfo.ReplicatsetEntry") @@ -932,72 +941,73 @@ func init() { func init() { proto.RegisterFile("app_runtime_server.proto", fileDescriptor_f94cf1a886c479d6) } var fileDescriptor_f94cf1a886c479d6 = []byte{ - // 1026 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xdb, 0x6e, 0xdb, 0x46, - 0x10, 0xd5, 0xdd, 0xd2, 0xc8, 0x92, 0xe3, 0x49, 0x9d, 0xd0, 0x4a, 0xdc, 0x24, 0x2c, 0x52, 0xf8, - 0x21, 0x50, 0x0b, 0x17, 0x46, 0x1d, 0x27, 0x68, 0x21, 0xc4, 0x86, 0x2b, 0xc0, 0x4d, 0x0d, 0xda, - 0x79, 0x16, 0x68, 0x72, 0xe3, 0x6e, 0x2d, 0x2e, 0xb7, 0xdc, 0xa5, 0x01, 0x3e, 0xb6, 0xbf, 0x90, - 0x1f, 0xea, 0x17, 0xf4, 0xad, 0xff, 0x53, 0xec, 0x85, 0x14, 0x75, 0x09, 0x5c, 0xb7, 0x05, 0xf2, - 0xb6, 0x3c, 0x3b, 0x67, 0x66, 0xe7, 0x0c, 0x67, 0x76, 0xc1, 0xf1, 0x39, 0x9f, 0x24, 0x29, 0x93, - 0x34, 0x22, 0x13, 0x41, 0x92, 0x1b, 0x92, 0x0c, 0x79, 0x12, 0xcb, 0x18, 0x6b, 0xfc, 0xd2, 0x5d, - 0x83, 0xe6, 0x71, 0xc4, 0x65, 0xe6, 0x7e, 0x05, 0xfd, 0x73, 0x92, 0xdc, 0xd0, 0x80, 0x78, 0xe4, - 0xd7, 0x94, 0x08, 0x89, 0x3b, 0x00, 0xc2, 0x20, 0x13, 0x1a, 0x3a, 0xd5, 0xa7, 0xd5, 0xdd, 0x8e, - 0xd7, 0xb1, 0xc8, 0x38, 0x74, 0xf7, 0x60, 0xc3, 0x12, 0x44, 0xce, 0x78, 0x02, 0xdd, 0x19, 0x43, - 0x58, 0x0a, 0x14, 0x14, 0xe1, 0xbe, 0x80, 0xde, 0x05, 0x61, 0x3e, 0x93, 0x39, 0xe3, 0x11, 0x74, - 0xa4, 0x06, 0x66, 0x21, 0xda, 0x06, 0x18, 0x87, 0xee, 0x6f, 0x55, 0xe8, 0x9d, 0x4b, 0x5f, 0xa6, - 0xe2, 0x47, 0x22, 0x84, 0x7f, 0x45, 0x70, 0x1f, 0x5a, 0x42, 0x03, 0x4e, 0xf5, 0x69, 0x7d, 0xb7, - 0xbb, 0xb7, 0x33, 0xe4, 0x97, 0xc3, 0x39, 0x13, 0xfb, 0x75, 0xcc, 0x64, 0x92, 0x79, 0xd6, 0x78, - 0xf0, 0x12, 0xba, 0x25, 0x18, 0xef, 0x41, 0xfd, 0x9a, 0x64, 0x36, 0x9c, 0x5a, 0xe2, 0x67, 0xd0, - 0xbc, 0xf1, 0xa7, 0x29, 0x71, 0x6a, 0x1a, 0x33, 0x1f, 0x87, 0xb5, 0x83, 0xaa, 0x9b, 0x41, 0xf7, - 0x88, 0x8a, 0xeb, 0xfc, 0x00, 0x5f, 0x43, 0x33, 0xa4, 0xe2, 0x3a, 0x8f, 0x3f, 0x50, 0xf1, 0x4b, - 0xfb, 0x7a, 0x6d, 0x83, 0x1b, 0xc3, 0xc1, 0x01, 0xc0, 0x0c, 0xbc, 0x2d, 0x74, 0xb5, 0x1c, 0xfa, - 0x10, 0x36, 0xad, 0xc0, 0x23, 0xce, 0xcf, 0xe2, 0xf0, 0x94, 0x0a, 0x89, 0xcf, 0xa1, 0xc1, 0xe3, - 0x30, 0x8f, 0xbf, 0xa9, 0xf3, 0x2f, 0x1b, 0x79, 0x7a, 0xdb, 0xfd, 0xb3, 0x06, 0xbd, 0x39, 0xfc, - 0x96, 0x6a, 0xaa, 0x42, 0x84, 0x84, 0x4f, 0xe3, 0x4c, 0xed, 0x1a, 0x15, 0xda, 0x06, 0x18, 0x87, - 0xaa, 0xae, 0x76, 0x53, 0x66, 0x9c, 0x38, 0x75, 0x53, 0x57, 0x03, 0x5d, 0x64, 0x9c, 0xe0, 0x36, - 0xb4, 0x79, 0x1c, 0x4e, 0x98, 0x1f, 0x11, 0xa7, 0xa1, 0x77, 0xd7, 0x78, 0x1c, 0xbe, 0xf5, 0x23, - 0x82, 0x5b, 0xd0, 0x52, 0x5b, 0x94, 0x3b, 0x4d, 0xa3, 0x2d, 0x8f, 0xc3, 0x31, 0x57, 0xc7, 0x51, - 0xb0, 0xad, 0x66, 0xcb, 0x1c, 0x87, 0xc7, 0xa1, 0xa9, 0x13, 0x8e, 0x00, 0x82, 0x98, 0x49, 0x9f, - 0x32, 0x92, 0x08, 0x67, 0x4d, 0x27, 0xfb, 0x6c, 0x29, 0xd9, 0xe1, 0x9b, 0xc2, 0xc6, 0x68, 0x5e, - 0x22, 0x0d, 0x4e, 0x61, 0x63, 0x61, 0x7b, 0x85, 0xfa, 0x5f, 0x94, 0xd5, 0xef, 0xee, 0xf5, 0x54, - 0x88, 0x82, 0x55, 0x2e, 0xc6, 0x3b, 0xe8, 0x14, 0x38, 0x3e, 0x87, 0x7e, 0x11, 0xc8, 0x24, 0x6d, - 0x5c, 0xf6, 0x0a, 0x54, 0xa7, 0xfe, 0x0c, 0xd6, 0x23, 0x12, 0xc5, 0x49, 0x36, 0x99, 0xd2, 0x88, - 0x4a, 0x1d, 0xa3, 0xee, 0x75, 0x0d, 0x76, 0xaa, 0x20, 0xf7, 0xaf, 0x26, 0xc0, 0x91, 0x91, 0x99, - 0xbd, 0x8f, 0xf1, 0x31, 0x74, 0x94, 0x3b, 0xc1, 0xfd, 0x20, 0xf7, 0x39, 0x03, 0xd0, 0x85, 0x75, - 0xa5, 0x17, 0x79, 0x9f, 0x4e, 0x89, 0x20, 0xd2, 0x96, 0x69, 0x0e, 0xc3, 0xcf, 0xc1, 0xd6, 0x25, - 0x22, 0x4c, 0xce, 0x57, 0x4a, 0x21, 0xf8, 0xc2, 0xfe, 0x3f, 0x0d, 0x2d, 0xa9, 0xa3, 0xff, 0xdf, - 0x22, 0xfe, 0xf0, 0x2c, 0x0e, 0xad, 0x92, 0xda, 0x0a, 0x0f, 0xa0, 0x6d, 0x7f, 0x11, 0xe1, 0x34, - 0x35, 0xe3, 0xf1, 0x02, 0x23, 0x1f, 0x01, 0x86, 0x55, 0x58, 0xe3, 0x3e, 0xac, 0x09, 0x12, 0x24, - 0x44, 0xaa, 0xe2, 0x2a, 0xe2, 0xa3, 0x25, 0xa2, 0xde, 0x35, 0xbc, 0xdc, 0x16, 0x5f, 0x41, 0x87, - 0xb2, 0xab, 0x84, 0x08, 0x41, 0xf2, 0xb2, 0xef, 0x2c, 0x10, 0xc7, 0xf9, 0xbe, 0xa1, 0xce, 0xec, - 0x71, 0x04, 0xdd, 0x84, 0xf0, 0x29, 0x0d, 0x7c, 0xa9, 0xe4, 0x69, 0x6b, 0xfa, 0x93, 0x05, 0xba, - 0x37, 0xb3, 0x30, 0x0e, 0xca, 0x1c, 0x7c, 0x50, 0x0c, 0x98, 0x8e, 0x96, 0x2e, 0x9f, 0x20, 0xdf, - 0x42, 0xa7, 0xd0, 0xe6, 0x2e, 0xf3, 0x63, 0xf0, 0xaa, 0xe8, 0xc3, 0x7f, 0x41, 0x3e, 0x84, 0xf5, - 0xb2, 0x4c, 0x77, 0xe2, 0xbe, 0x86, 0xfe, 0xbc, 0x52, 0x77, 0x62, 0x7f, 0x07, 0xf7, 0x16, 0x85, - 0xba, 0xd3, 0xd8, 0xfc, 0xa3, 0x0a, 0xfd, 0x7c, 0xd2, 0x8b, 0x38, 0x4d, 0x02, 0xa2, 0x86, 0x48, - 0xc0, 0xd3, 0x49, 0x62, 0x26, 0xbf, 0x76, 0x53, 0xf7, 0x20, 0xe0, 0x69, 0xe9, 0x2e, 0x50, 0x06, - 0xe5, 0x5e, 0x69, 0x07, 0x3c, 0xd5, 0x8d, 0xa2, 0x5a, 0xce, 0xf6, 0x52, 0xee, 0xa0, 0xae, 0x2d, - 0x7a, 0x06, 0xcd, 0x7d, 0x2c, 0xb6, 0x5c, 0x63, 0xa9, 0xe5, 0xf0, 0x4b, 0xd8, 0x48, 0x52, 0xc6, - 0x28, 0xbb, 0x9a, 0xa8, 0x9b, 0x91, 0xa5, 0x91, 0x9e, 0x4c, 0x75, 0xaf, 0x67, 0xe1, 0x11, 0xe7, - 0x6f, 0xd3, 0xc8, 0xfd, 0xbd, 0x0a, 0xdb, 0xa3, 0x30, 0xbc, 0xf8, 0x99, 0x26, 0xe1, 0x99, 0x9f, - 0xc8, 0xec, 0x98, 0x85, 0x3c, 0xa6, 0x4c, 0xaa, 0xeb, 0x0e, 0x11, 0x1a, 0x69, 0x5a, 0x0c, 0x52, - 0xbd, 0x56, 0x02, 0x89, 0x62, 0x7a, 0xaa, 0x25, 0xf6, 0xa1, 0x46, 0xb9, 0xed, 0xc2, 0x1a, 0xe5, - 0x8a, 0xc5, 0xe3, 0xc4, 0x1c, 0xab, 0xe9, 0xe9, 0xb5, 0x4a, 0x9b, 0x8a, 0x49, 0xcc, 0xa6, 0x94, - 0x11, 0x7d, 0x92, 0xb6, 0xd7, 0xa6, 0xe2, 0x27, 0xfd, 0xad, 0x0f, 0xf1, 0x8e, 0x7f, 0xe2, 0x43, - 0x8c, 0x60, 0xfb, 0x88, 0x4c, 0xff, 0xcb, 0x19, 0xdc, 0x0f, 0x55, 0xc0, 0x65, 0x07, 0xff, 0x63, - 0x02, 0xb3, 0xc6, 0x6d, 0x96, 0x1b, 0x77, 0x3e, 0xb1, 0xd6, 0x42, 0x62, 0xdf, 0xc3, 0xfd, 0x15, - 0x59, 0xe1, 0x2e, 0xd4, 0xe3, 0xcb, 0x5f, 0xec, 0x15, 0xfb, 0x40, 0xcd, 0x8f, 0x65, 0x2b, 0x4f, - 0x99, 0xec, 0x7d, 0x68, 0x40, 0x7f, 0xc4, 0xb9, 0x67, 0x5e, 0x57, 0xe7, 0x19, 0x0b, 0xf0, 0x00, - 0xd6, 0x4f, 0x88, 0x1c, 0x71, 0x6e, 0x6f, 0xb2, 0xfb, 0xa5, 0x5b, 0x2b, 0x7f, 0x28, 0x0d, 0x36, - 0x97, 0xde, 0x2d, 0x6e, 0x05, 0x5f, 0x02, 0x18, 0xa6, 0x9a, 0x34, 0x88, 0x25, 0x5e, 0x4e, 0xdb, - 0x5a, 0xba, 0x01, 0xd5, 0x9b, 0xc0, 0xad, 0xe0, 0x3e, 0xf4, 0x4e, 0x88, 0x2c, 0x5d, 0x24, 0xab, - 0xd8, 0xfd, 0xf9, 0x49, 0xe8, 0x56, 0xf0, 0x35, 0x6c, 0x9e, 0x10, 0xb9, 0xd0, 0xa7, 0xfa, 0x6c, - 0x73, 0xaf, 0xb4, 0x01, 0x96, 0x21, 0x63, 0xe6, 0x56, 0xf0, 0x07, 0x78, 0xa8, 0xc2, 0xaf, 0x52, - 0x70, 0x55, 0xf8, 0x87, 0xab, 0x85, 0x14, 0x6e, 0x05, 0xdf, 0xc0, 0xd6, 0xca, 0x4e, 0x43, 0x3d, - 0xfb, 0x3f, 0xda, 0x84, 0x83, 0x8e, 0xda, 0x36, 0xcf, 0x57, 0xed, 0x64, 0x65, 0xa7, 0x18, 0x27, - 0x1f, 0x6d, 0xa2, 0x25, 0x27, 0x2b, 0x7f, 0x75, 0xb4, 0xb7, 0xd0, 0xf4, 0x1f, 0x38, 0xb9, 0x6c, - 0xe9, 0xe7, 0xf5, 0x37, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x52, 0x20, 0xc0, 0x7a, 0x0b, - 0x00, 0x00, + // 1044 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xef, 0x6e, 0xdb, 0x36, + 0x10, 0xf7, 0xff, 0xd8, 0xe7, 0xd8, 0x69, 0xd8, 0xa5, 0x55, 0xdc, 0x76, 0x6d, 0x35, 0x74, 0xc8, + 0x87, 0xc2, 0x1b, 0x32, 0x04, 0x4b, 0xd3, 0x62, 0x83, 0xd1, 0x04, 0x99, 0x81, 0xac, 0x0b, 0x94, + 0xf4, 0xb3, 0xa1, 0x48, 0x6c, 0xc6, 0xc5, 0x22, 0x59, 0x91, 0x0a, 0xa0, 0x8f, 0xdb, 0x2b, 0xf4, + 0x85, 0xf6, 0x04, 0xc3, 0x1e, 0x69, 0xe0, 0x1f, 0xc9, 0x92, 0xad, 0xa2, 0xf3, 0x36, 0x60, 0xdf, + 0xa8, 0xdf, 0xdd, 0xef, 0x8e, 0x77, 0xa7, 0xbb, 0x23, 0x38, 0x3e, 0xe7, 0xb3, 0x38, 0xa1, 0x92, + 0x44, 0x78, 0x26, 0x70, 0x7c, 0x8b, 0xe3, 0x31, 0x8f, 0x99, 0x64, 0xa8, 0xc1, 0xaf, 0xdc, 0x0d, + 0x68, 0x9f, 0x44, 0x5c, 0xa6, 0xee, 0x57, 0x30, 0xbc, 0xc0, 0xf1, 0x2d, 0x09, 0xb0, 0x87, 0xdf, + 0x27, 0x58, 0x48, 0xf4, 0x08, 0x40, 0x18, 0x64, 0x46, 0x42, 0xa7, 0xfe, 0xa4, 0xbe, 0xd7, 0xf3, + 0x7a, 0x16, 0x99, 0x86, 0xee, 0x3e, 0x6c, 0x59, 0x82, 0xc8, 0x18, 0x8f, 0xa1, 0xbf, 0x60, 0x08, + 0x4b, 0x81, 0x9c, 0x22, 0xdc, 0xe7, 0x30, 0xb8, 0xc4, 0xd4, 0xa7, 0x32, 0x63, 0x3c, 0x80, 0x9e, + 0xd4, 0xc0, 0xc2, 0x45, 0xd7, 0x00, 0xd3, 0xd0, 0xfd, 0xb5, 0x0e, 0x83, 0x0b, 0xe9, 0xcb, 0x44, + 0xfc, 0x88, 0x85, 0xf0, 0xaf, 0x31, 0x3a, 0x80, 0x8e, 0xd0, 0x80, 0x53, 0x7f, 0xd2, 0xdc, 0xeb, + 0xef, 0x3f, 0x1a, 0xf3, 0xab, 0x71, 0x49, 0xc5, 0x7e, 0x9d, 0x50, 0x19, 0xa7, 0x9e, 0x55, 0x1e, + 0xbd, 0x80, 0x7e, 0x01, 0x46, 0x77, 0xa0, 0x79, 0x83, 0x53, 0xeb, 0x4e, 0x1d, 0xd1, 0x67, 0xd0, + 0xbe, 0xf5, 0xe7, 0x09, 0x76, 0x1a, 0x1a, 0x33, 0x1f, 0x47, 0x8d, 0xc3, 0xba, 0x9b, 0x42, 0xff, + 0x98, 0x88, 0x9b, 0xec, 0x02, 0x5f, 0x43, 0x3b, 0x24, 0xe2, 0x26, 0xf3, 0x3f, 0x52, 0xfe, 0x0b, + 0x72, 0x7d, 0xb6, 0xce, 0x8d, 0xe2, 0xe8, 0x10, 0x60, 0x01, 0x7e, 0xca, 0x75, 0xbd, 0xe8, 0xfa, + 0x08, 0xb6, 0x6d, 0x82, 0x27, 0x9c, 0x9f, 0xb3, 0xf0, 0x8c, 0x08, 0x89, 0x9e, 0x41, 0x8b, 0xb3, + 0x30, 0xf3, 0xbf, 0xad, 0xe3, 0x2f, 0x2a, 0x79, 0x5a, 0xec, 0xfe, 0xd1, 0x80, 0x41, 0x09, 0xff, + 0x44, 0x35, 0x55, 0x21, 0x42, 0xcc, 0xe7, 0x2c, 0x55, 0x52, 0x93, 0x85, 0xae, 0x01, 0xa6, 0xa1, + 0xaa, 0xab, 0x15, 0xca, 0x94, 0x63, 0xa7, 0x69, 0xea, 0x6a, 0xa0, 0xcb, 0x94, 0x63, 0xb4, 0x0b, + 0x5d, 0xce, 0xc2, 0x19, 0xf5, 0x23, 0xec, 0xb4, 0xb4, 0x74, 0x83, 0xb3, 0xf0, 0x8d, 0x1f, 0x61, + 0xb4, 0x03, 0x1d, 0x25, 0x22, 0xdc, 0x69, 0x9b, 0xdc, 0x72, 0x16, 0x4e, 0xb9, 0xba, 0x8e, 0x82, + 0x6d, 0x35, 0x3b, 0xe6, 0x3a, 0x9c, 0x85, 0xa6, 0x4e, 0x68, 0x02, 0x10, 0x30, 0x2a, 0x7d, 0x42, + 0x71, 0x2c, 0x9c, 0x0d, 0x1d, 0xec, 0xd3, 0x95, 0x60, 0xc7, 0xaf, 0x73, 0x1d, 0x93, 0xf3, 0x02, + 0x69, 0x74, 0x06, 0x5b, 0x4b, 0xe2, 0x8a, 0xec, 0x7f, 0x51, 0xcc, 0x7e, 0x7f, 0x7f, 0xa0, 0x5c, + 0xe4, 0xac, 0x62, 0x31, 0xde, 0x42, 0x2f, 0xc7, 0xd1, 0x33, 0x18, 0xe6, 0x8e, 0x4c, 0xd0, 0xc6, + 0xe4, 0x20, 0x47, 0x75, 0xe8, 0x4f, 0x61, 0x33, 0xc2, 0x11, 0x8b, 0xd3, 0xd9, 0x9c, 0x44, 0x44, + 0x6a, 0x1f, 0x4d, 0xaf, 0x6f, 0xb0, 0x33, 0x05, 0xb9, 0x7f, 0x76, 0x00, 0x8e, 0x4d, 0x9a, 0xe9, + 0x3b, 0x86, 0x1e, 0x42, 0x4f, 0x99, 0x13, 0xdc, 0x0f, 0x32, 0x9b, 0x0b, 0x00, 0xb9, 0xb0, 0xa9, + 0xf2, 0x85, 0xdf, 0x25, 0x73, 0x2c, 0xb0, 0xb4, 0x65, 0x2a, 0x61, 0xe8, 0x73, 0xb0, 0x75, 0x89, + 0x30, 0x95, 0xe5, 0x4a, 0x29, 0x04, 0x3d, 0xb7, 0xff, 0x4f, 0x4b, 0xa7, 0xd4, 0xd1, 0xff, 0x6f, + 0xee, 0x7f, 0x7c, 0xce, 0x42, 0x9b, 0x49, 0xad, 0x85, 0x0e, 0xa1, 0x6b, 0x7f, 0x11, 0xe1, 0xb4, + 0x35, 0xe3, 0xe1, 0x12, 0x23, 0x1b, 0x01, 0x86, 0x95, 0x6b, 0xa3, 0x97, 0xd0, 0xc3, 0x34, 0xe4, + 0x8c, 0x50, 0xa9, 0xca, 0x9b, 0x37, 0x6b, 0x81, 0x7a, 0x92, 0xc9, 0x0d, 0x77, 0xa1, 0x8f, 0x0e, + 0x60, 0x43, 0xe0, 0x20, 0xc6, 0x32, 0x2b, 0xfd, 0x83, 0x15, 0xaf, 0x5a, 0x6a, 0x88, 0x99, 0xae, + 0xf2, 0x49, 0xe8, 0x75, 0x8c, 0x85, 0xc0, 0xc2, 0xe9, 0x56, 0xfa, 0x9c, 0x66, 0x72, 0xeb, 0x33, + 0xd7, 0x47, 0x13, 0xe8, 0xc7, 0x98, 0xcf, 0x49, 0xe0, 0x4b, 0x95, 0xdb, 0x9e, 0xa6, 0x3f, 0x5e, + 0xa2, 0x7b, 0x0b, 0x0d, 0x63, 0xa0, 0xc8, 0x41, 0xf7, 0xf2, 0xe9, 0x04, 0x3a, 0xef, 0xd9, 0xf8, + 0xf9, 0x16, 0x7a, 0x79, 0x62, 0xd7, 0x19, 0x3e, 0xa3, 0x97, 0x79, 0x13, 0xff, 0x03, 0xf2, 0x2b, + 0x18, 0x96, 0x33, 0xbc, 0x16, 0xfb, 0x08, 0x36, 0x8b, 0x49, 0x5e, 0xd7, 0x73, 0x39, 0xcf, 0x6b, + 0xb1, 0xbf, 0x83, 0x3b, 0xcb, 0x69, 0x5e, 0x6b, 0x62, 0xff, 0x5e, 0x87, 0x61, 0xb6, 0x64, 0x04, + 0x4b, 0xe2, 0x00, 0xab, 0xf9, 0x15, 0xf0, 0x64, 0x16, 0x9b, 0xa5, 0xa3, 0xcd, 0x34, 0x3d, 0x08, + 0x78, 0x52, 0x58, 0x43, 0x4a, 0xa1, 0xd8, 0xa6, 0xdd, 0x80, 0x27, 0xba, 0x47, 0x55, 0xb7, 0xdb, + 0x36, 0xce, 0x0c, 0x34, 0xb5, 0xc6, 0xc0, 0xa0, 0x99, 0x8d, 0xe5, 0x6e, 0x6f, 0xad, 0x74, 0x3b, + 0xfa, 0x12, 0xb6, 0xe2, 0x84, 0x52, 0x42, 0xaf, 0x67, 0x6a, 0x29, 0xd3, 0x24, 0xd2, 0x43, 0xb1, + 0xe9, 0x0d, 0x2c, 0x3c, 0xe1, 0xfc, 0x4d, 0x12, 0xb9, 0xbf, 0xd5, 0x61, 0x77, 0x12, 0x86, 0x97, + 0x3f, 0x93, 0x38, 0x3c, 0xf7, 0x63, 0x99, 0xe6, 0x85, 0xf4, 0xf0, 0x7b, 0x84, 0xa0, 0x95, 0x24, + 0xf9, 0x0c, 0xd7, 0x67, 0x95, 0x20, 0x91, 0x0f, 0x6e, 0x75, 0x44, 0x43, 0x68, 0x10, 0x6e, 0x07, + 0x40, 0x83, 0x70, 0xc5, 0xe2, 0x2c, 0x36, 0xd7, 0x6a, 0x7b, 0xfa, 0xac, 0xc2, 0x26, 0x62, 0xc6, + 0xe8, 0x9c, 0x50, 0xac, 0x6f, 0xd2, 0xf5, 0xba, 0x44, 0xfc, 0xa4, 0xbf, 0xf5, 0x25, 0xde, 0xf2, + 0xff, 0xf9, 0x12, 0x13, 0xd8, 0x3d, 0xc6, 0xf3, 0x7f, 0x73, 0x07, 0xf7, 0x43, 0x1d, 0xd0, 0xaa, + 0x81, 0xff, 0x30, 0x80, 0x45, 0xdb, 0xb7, 0x8b, 0x6d, 0x5f, 0x0e, 0xac, 0xb3, 0x14, 0xd8, 0xf7, + 0x70, 0xb7, 0x22, 0x2a, 0xb4, 0x07, 0x4d, 0x76, 0xf5, 0x8b, 0xdd, 0xee, 0xf7, 0xd4, 0xf4, 0x59, + 0xd5, 0xf2, 0x94, 0xca, 0xfe, 0x87, 0x16, 0x0c, 0x27, 0x9c, 0x7b, 0xe6, 0x61, 0x77, 0x91, 0xd2, + 0x00, 0x1d, 0xc2, 0xe6, 0x29, 0x96, 0x13, 0xce, 0xed, 0x12, 0xbd, 0x5b, 0x58, 0x98, 0xd9, 0x1b, + 0x6d, 0xb4, 0xbd, 0xf2, 0x64, 0x72, 0x6b, 0xe8, 0x05, 0x80, 0x61, 0xaa, 0x39, 0x85, 0x50, 0x81, + 0x97, 0xd1, 0x76, 0x56, 0x96, 0xaf, 0x7a, 0x8e, 0xb8, 0x35, 0x74, 0x00, 0x83, 0x53, 0x2c, 0x0b, + 0x3b, 0xac, 0x8a, 0x3d, 0x2c, 0xcf, 0x51, 0xb7, 0x86, 0x5e, 0xc1, 0xf6, 0x29, 0x96, 0x4b, 0x7d, + 0xaa, 0xef, 0x56, 0x7a, 0x20, 0x8e, 0x50, 0x11, 0x32, 0x6a, 0x6e, 0x0d, 0xfd, 0x00, 0xf7, 0x95, + 0xfb, 0xaa, 0x0c, 0x56, 0xb9, 0xbf, 0x5f, 0x9d, 0x48, 0xe1, 0xd6, 0xd0, 0x6b, 0xd8, 0xa9, 0xec, + 0x34, 0xa4, 0x37, 0xc7, 0x47, 0x9b, 0x70, 0xd4, 0x53, 0x62, 0xf3, 0x72, 0xd6, 0x46, 0x2a, 0x3b, + 0xc5, 0x18, 0xf9, 0x68, 0x13, 0xad, 0x18, 0xa9, 0xfc, 0xd5, 0x91, 0xdd, 0x61, 0xf3, 0xbf, 0x61, + 0xe4, 0xaa, 0xa3, 0x5f, 0xf6, 0xdf, 0xfc, 0x15, 0x00, 0x00, 0xff, 0xff, 0xa2, 0xcd, 0xa8, 0xa8, + 0xf5, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/worker/server/pb/app_runtime_server.proto b/worker/server/pb/app_runtime_server.proto index 676cef706..744351420 100644 --- a/worker/server/pb/app_runtime_server.proto +++ b/worker/server/pb/app_runtime_server.proto @@ -56,10 +56,11 @@ message DeployInfo { string deployment = 3; map pods = 4; map services = 5; - map secrets = 6; - map ingresses = 7; - map replicatset = 8; - string status = 9; + map endpoints = 6; + map secrets = 7; + map ingresses = 8; + map replicatset = 9; + string status = 10; } message TenantResource { diff --git a/worker/server/server.go b/worker/server/server.go index 30b118f15..d3a1502bf 100644 --- a/worker/server/server.go +++ b/worker/server/server.go @@ -21,9 +21,9 @@ package server import ( "context" "fmt" + "github.com/goodrain/rainbond/db/model" corev1 "k8s.io/api/core/v1" "net" - "strconv" "strings" "time" @@ -180,6 +180,14 @@ func (r *RuntimeServer) GetDeployInfo(ctx context.Context, re *pb.ServiceRequest } deployinfo.Services = service } + if endpoints := appService.GetEndpoints(); endpoints != nil && + appService.AppServiceBase.ServiceKind == model.ServiceKindThirdParty { + eps := make(map[string]string, len(endpoints)) + for _, s := range endpoints { + eps[s.Name] = s.Name + } + deployinfo.Endpoints = eps + } if secrets := appService.GetSecrets(); secrets != nil { secretsinfo := make(map[string]string, len(secrets)) for _, s := range secrets { @@ -242,36 +250,49 @@ func (r *RuntimeServer) ListThirdPartyEndpoints(ctx context.Context, re *pb.Serv return new(pb.ThirdPartyEndpoints), nil } var pbeps []*pb.ThirdPartyEndpoint + // The same IP may correspond to two endpoints, which are internal and external endpoints. + // So it is need to filter the same IP. exists := make(map[string]bool) for _, ep := range as.GetEndpoints() { - if exists[ep.GetLabels()["uuid"]] { + if ep.Subsets == nil || len(ep.Subsets) == 0 { + logrus.Debugf("Key: %s; empty subsets", fmt.Sprintf("%s/%s", ep.Namespace, ep.Name)) continue } - exists[ep.GetLabels()["uuid"]] = true - pbep := &pb.ThirdPartyEndpoint{ - Uuid: ep.GetLabels()["uuid"], - Sid: ep.GetLabels()["service_id"], - Ip: ep.GetLabels()["ip"], - Port: func(item *corev1.Endpoints) int32 { - realport, _ := strconv.ParseBool(item.GetLabels()["realport"]) - if realport { - portstr := item.GetLabels()["port"] - port, _ := strconv.Atoi(portstr) - return int32(port) + for idx, subset := range ep.Subsets { + if exists[subset.Ports[0].Name] { + continue + } + ip := func(subset corev1.EndpointSubset) string { + if subset.Addresses != nil && len(subset.Addresses) > 0 { + return subset.Addresses[0].IP } - return 0 - }(ep), - Status: func(item *corev1.Endpoints) string { - if item.Subsets == nil || len(item.Subsets) == 0 { + if subset.NotReadyAddresses != nil && len(subset.NotReadyAddresses) > 0 { + return subset.NotReadyAddresses[0].IP + } + return "" + }(subset) + if strings.TrimSpace(ip) == "" { + logrus.Debugf("Key: %s; Index: %d; IP not found", fmt.Sprintf("%s/%s", ep.Namespace, ep.Name), idx) + continue + } + exists[subset.Ports[0].Name] = true + pbep := &pb.ThirdPartyEndpoint{ + Uuid: subset.Ports[0].Name, + Sid: ep.GetLabels()["service_id"], + Ip: ip, + Port: subset.Ports[0].Port, + Status: func(item *corev1.Endpoints) string { + if subset.Addresses != nil && len(subset.Addresses) > 0 { + return "healthy" + } + if subset.NotReadyAddresses != nil && len(subset.NotReadyAddresses) > 0 { + return "unhealthy" + } return "unknown" - } - if item.Subsets[0].Addresses == nil || len(item.Subsets[0].Addresses) == 0 { - return "unhealthy" - } - return "healthy" - }(ep), + }(ep), + } + pbeps = append(pbeps, pbep) } - pbeps = append(pbeps, pbep) } return &pb.ThirdPartyEndpoints{ Obj: pbeps, @@ -310,9 +331,16 @@ func (r *RuntimeServer) UpdThirdPartyEndpoint(ctx context.Context, re *pb.UpdThi Port: int(re.Port), IsOnline: re.IsOnline, } - r.updateCh.In() <- discovery.Event{ - Type: discovery.UpdateEvent, - Obj: rbdep, + if re.IsOnline == false { + r.updateCh.In() <- discovery.Event{ + Type: discovery.DeleteEvent, + Obj: rbdep, + } + } else { + r.updateCh.In() <- discovery.Event{ + Type: discovery.UpdateEvent, + Obj: rbdep, + } } return new(pb.Empty), nil }