Merge branch 'master' of code.goodrain.com:goodrain/rainbond

This commit is contained in:
ysicing 2017-11-15 19:33:20 +08:00
commit f9fa664b52
9 changed files with 272 additions and 105 deletions

View File

@ -1678,6 +1678,30 @@
}
},
"/v2/tenants/{tenant_name}/plugin/{plugin_id}/default-env": {
"get": {
"description": "get plugin env",
"consumes": [
"application/json",
"application/x-protobuf"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"v2"
],
"summary": "获取插件默认设定的env",
"operationId": "getPluginDefaultEnv",
"responses": {
"default": {
"description": "统一返回格式",
"schema": {
"$ref": "#/responses/commandResponse"
}
}
}
},
"put": {
"description": "update default env",
"consumes": [
@ -1847,48 +1871,6 @@
}
}
},
"/v2/tenants/{tenant_name}/plugin/{plugin_id}/envs": {
"get": {
"description": "get plugin env",
"consumes": [
"application/json",
"application/x-protobuf"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"v2"
],
"summary": "获取插件设定的env",
"operationId": "getPluginEnv",
"parameters": [
{
"type": "string",
"x-go-name": "TenantName",
"name": "tenant_name",
"in": "path",
"required": true
},
{
"type": "string",
"x-go-name": "PluginID",
"name": "plugin_id",
"in": "path",
"required": true
}
],
"responses": {
"default": {
"description": "统一返回格式",
"schema": {
"$ref": "#/responses/commandResponse"
}
}
}
}
},
"/v2/tenants/{tenant_name}/resources": {
"get": {
"description": "get tenant resources",

View File

@ -21,6 +21,7 @@ package controller
import (
"net/http"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/pkg/api/handler"
"github.com/goodrain/rainbond/pkg/api/middleware"
@ -566,9 +567,9 @@ func (t *TenantStruct) DeletePluginRelation(w http.ResponseWriter, r *http.Reque
//GetPluginDefaultEnvs GetPluginDefaultEnvs
func (t *TenantStruct) GetPluginDefaultEnvs(w http.ResponseWriter, r *http.Request) {
// swagger:operation GET /v2/tenants/{tenant_name}/plugin/{plugin_id}/envs v2 getPluginEnv
// swagger:operation GET /v2/tenants/{tenant_name}/plugin/{plugin_id}/default-env v2 getPluginDefaultEnv
//
// 获取插件设定的env
// 获取插件默认设定的env
//
// get plugin env
//
@ -619,6 +620,7 @@ func (t *TenantStruct) GePluginEnvWhichCanBeSet(w http.ResponseWriter, r *http.R
// description: 统一返回格式
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
pluginID := chi.URLParam(r, "plugin_id")
logrus.Debugf("plugin_Id is %s", pluginID)
envs, err := handler.GetPluginManager().GetEnvsWhichCanBeSet(serviceID, pluginID)
if err != nil {
err.Handle(r, w)

View File

@ -97,6 +97,18 @@ func (p *PluginAction) CreatePluginAct(cps *api_model.CreatePluginStruct) *util.
return util.CreateAPIHandleErrorFromDBError(fmt.Sprintf("add default env %s", env.ENVName), err)
}
}
//添加默认plugin model env
vis := &dbmodel.TenantPluginDefaultENV{
PluginID: cps.Body.PluginID,
ENVName: "PLUGIN_MOEL",
ENVValue: cps.Body.PluginModel,
IsChange: false,
}
err = db.GetManager().TenantPluginDefaultENVDaoTransactions(tx).AddModel(vis)
if err != nil {
tx.Rollback()
return util.CreateAPIHandleErrorFromDBError("add default env PLUGIN_MOEL", err)
}
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return util.CreateAPIHandleErrorFromDBError("commit create plugin transactions", err)
@ -222,7 +234,7 @@ func (p *PluginAction) GetEnvsWhichCanBeSet(serviceID, pluginID string) (interfa
if len(envs) > 0 {
return envs, nil
}
envD, errD := db.GetManager().TenantPluginDefaultENVDao().GetDefaultENVSByPluginIDCantBeSet(pluginID)
envD, errD := db.GetManager().TenantPluginDefaultENVDao().GetDefaultEnvWhichCanBeSetByPluginID(pluginID)
if errD != nil {
return nil, util.CreateAPIHandleErrorFromDBError("get envs which can be set", errD)
}
@ -345,6 +357,7 @@ func (p *PluginAction) DockerfileBuildPlugin(b *api_model.BuildPluginStruct, plu
Kind: b.Body.Kind,
Repo: b.Body.RepoURL,
GitURL: b.Body.GitURL,
Info: b.Body.Info,
BuildTime: time.Now().Format(time.RFC3339),
Status: "building",
}

View File

@ -330,7 +330,7 @@ type DeletePluginSetStruct struct {
}
//GetPluginEnvStruct GetPluginEnvStruct
//swagger:parameters getPluginEnv
//swagger:parameters getPluginEnv, getPluginDefaultEnv
type GetPluginEnvStruct struct {
// in: path
// required: true

View File

@ -21,6 +21,7 @@ package controller
import (
"net/http"
"github.com/Sirupsen/logrus"
"github.com/go-chi/chi"
"github.com/goodrain/rainbond/pkg/api/util"
"github.com/pquerna/ffjson/ffjson"
@ -46,9 +47,9 @@ func ServiceDiscover(w http.ResponseWriter, r *http.Request) {
//ListenerDiscover ListenerDiscover
func ListenerDiscover(w http.ResponseWriter, r *http.Request) {
tenantName := chi.URLParam(r, "tenant_id")
tenantService := chi.URLParam(r, "tenant_service")
serviceNodes := chi.URLParam(r, "service_nodes")
lds, err := discoverService.DiscoverListeners(tenantName, serviceNodes)
lds, err := discoverService.DiscoverListeners(tenantService, serviceNodes)
if err != nil {
err.Handle(r, w)
return
@ -64,9 +65,9 @@ func ListenerDiscover(w http.ResponseWriter, r *http.Request) {
//ClusterDiscover ClusterDiscover
func ClusterDiscover(w http.ResponseWriter, r *http.Request) {
tenantName := chi.URLParam(r, "tenant_id")
tenantService := chi.URLParam(r, "tenant_service")
serviceNodes := chi.URLParam(r, "service_nodes")
cds, err := discoverService.DiscoverClusters(tenantName, serviceNodes)
cds, err := discoverService.DiscoverClusters(tenantService, serviceNodes)
if err != nil {
err.Handle(r, w)
return
@ -79,3 +80,12 @@ func ClusterDiscover(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte(cdsJ))
}
//RoutesDiscover RoutesDiscover
func RoutesDiscover(w http.ResponseWriter, r *http.Request) {
namespace := chi.URLParam(r, "tenant_id")
serviceNodes := chi.URLParam(r, "service_nodes")
routeConfig := chi.URLParam(r, "route_config")
logrus.Debugf("route_config is %s, namespace %s, serviceNodes %s", routeConfig, namespace, serviceNodes)
w.WriteHeader(200)
}

View File

@ -43,14 +43,25 @@ type CDS struct {
//PieceCDS struct
type PieceCDS struct {
Name string `json:"name"`
Type string `json:"type"`
ConnectTimeoutMS int `json:"connect_timeout_ms"`
LBType string `json:"lb_type"`
ServiceName string `json:"service_name"`
Name string `json:"name"`
Type string `json:"type"`
ConnectTimeoutMS int `json:"connect_timeout_ms"`
LBType string `json:"lb_type"`
ServiceName string `json:"service_name"`
CircuitBreakers *CircuitBreakers `json:"circuit_breakers"`
//HealthCheck cdsHealthCheckt `json:"health_check"`
}
//MaxConnections circuit
type MaxConnections struct {
MaxConnections int `json:"max_connections"`
}
//CircuitBreakers circuit
type CircuitBreakers struct {
Default *MaxConnections `json:"default"`
}
type cdsHealthCheckt struct {
Type string `json:"type"`
TimeoutMS int `json:"timeout_ms"`
@ -118,9 +129,16 @@ type PieceHTTPVirtualHost struct {
//PieceHTTPRoutes PieceHTTPRoutes
type PieceHTTPRoutes struct {
TimeoutMS int `json:"timeout_ms"`
Prefix string `json:"prefix"`
Cluster string `json:"cluster"`
TimeoutMS int `json:"timeout_ms"`
Prefix string `json:"prefix"`
Cluster string `json:"cluster"`
Headers []*PieceHeader `json:"headers"`
}
//PieceHeader PieceHeader
type PieceHeader struct {
Name string `json:"name"`
Value string `json:"value"`
}
//HTTPSingleFileter HttpSingleFileter
@ -129,3 +147,14 @@ type HTTPSingleFileter struct {
Name string `json:"name"`
Config map[string]string `json:"config"`
}
const (
//PREFIX PREFIX
PREFIX string = "PREFIX"
//HEADERS HEADERS
HEADERS string = "HEADERS"
//DOMAINS DOMAINS
DOMAINS string = "DOMAINS"
//LIMITS LIMITS
LIMITS string = "LIMITS"
)

View File

@ -31,6 +31,7 @@ func DisconverRoutes() chi.Router {
r.Mount("/listeners", ListenersRoutes())
r.Mount("/clusters", ClustersRoutes())
r.Mount("/registration", RegistrationRoutes())
r.Mount("/routes", RoutesRouters())
return r
}
@ -39,7 +40,7 @@ func DisconverRoutes() chi.Router {
func ListenersRoutes() chi.Router {
r := chi.NewRouter()
r.Get("/ping", controller.Ping)
r.Get("/{tenant_id}/{service_nodes}", controller.ListenerDiscover)
r.Get("/{tenant_service}/{service_nodes}", controller.ListenerDiscover)
return r
}
@ -48,7 +49,7 @@ func ListenersRoutes() chi.Router {
func ClustersRoutes() chi.Router {
r := chi.NewRouter()
r.Get("/ping", controller.Ping)
r.Get("/{tenant_id}/{service_nodes}", controller.ClusterDiscover)
r.Get("/{tenant_service}/{service_nodes}", controller.ClusterDiscover)
return r
}
@ -60,3 +61,12 @@ func RegistrationRoutes() chi.Router {
r.Get("/{service_name}", controller.ServiceDiscover)
return r
}
//RoutesRouters rds
//GET /v1/routes/(string: route_config_name)/(string: service_cluster)/(string: service_node)
func RoutesRouters() chi.Router {
r := chi.NewRouter()
r.Get("/ping", controller.Ping)
r.Get("/{route_config}/{tenant_service}/{service_nodes}", controller.RoutesDiscover)
return r
}

View File

@ -20,8 +20,10 @@ package service
import (
"fmt"
"strconv"
"strings"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/cmd/node/option"
"github.com/goodrain/rainbond/pkg/api/util"
node_model "github.com/goodrain/rainbond/pkg/node/api/model"
@ -91,7 +93,18 @@ func (d *DiscoverAction) DiscoverService(serviceInfo string) (*node_model.SDS, *
}
//DiscoverListeners DiscoverListeners
func (d *DiscoverAction) DiscoverListeners(namespace, serviceCluster string) (*node_model.LDS, *util.APIHandleError) {
func (d *DiscoverAction) DiscoverListeners(tenantService, serviceCluster string) (*node_model.LDS, *util.APIHandleError) {
nn := strings.Split(tenantService, "_")
if len(nn) != 2 {
return nil, util.CreateAPIHandleError(400,
fmt.Errorf("namesapces and service_alias not in good format"))
}
namespace := nn[0]
serviceAlias := nn[1]
envs, err := d.ToolsGetMainPodEnvs(namespace, serviceAlias)
if err != nil {
return nil, err
}
mm := strings.Split(serviceCluster, "_")
if len(mm) == 0 {
return nil, util.CreateAPIHandleError(400, fmt.Errorf("service_name is not in good format"))
@ -111,32 +124,25 @@ func (d *DiscoverAction) DiscoverListeners(namespace, serviceCluster string) (*n
continue
}
for _, service := range services.Items {
//protocol, ok := service.Labels["protocol"]
// if ok && protocol == "http" {
// //TODO: HTTP inner的protocol添加资源时需要label
// hsf := &node_model.HTTPSingleFileter{
// Type: "decoder",
// Name: "router",
// }
// prs := &node_model.PieceHTTPRoutes{
// TimeoutMS: 0,
// Prefix: "/",
// Cluster: "",
// }
// continue
// }
//TODO: TCP
for _, port := range service.Spec.Ports {
switch port.Protocol {
case "TCP":
//TODO: HTTP inner的protocol添加资源时需要label
inner, ok := service.Labels["service_type"]
if !ok || inner != "inner" {
continue
}
port := service.Spec.Ports[0].Port
portProtocol, ok := service.Labels["port_protocol"]
if ok {
logrus.Debugf("port protocol is %s", portProtocol)
switch portProtocol {
case "stream":
ptr := &node_model.PieceTCPRoute{
Cluster: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Cluster: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
}
lrs := &node_model.LDSTCPRoutes{
Routes: []*node_model.PieceTCPRoute{ptr},
}
lcg := &node_model.LDSTCPConfig{
StatPrefix: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
StatPrefix: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
RouteConfig: lrs,
}
lfs := &node_model.LDSFilters{
@ -144,29 +150,42 @@ func (d *DiscoverAction) DiscoverListeners(namespace, serviceCluster string) (*n
Config: lcg,
}
plds := &node_model.PieceLDS{
Name: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Address: fmt.Sprintf("tcp://0.0.0.0:%v", port.Port),
Name: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
Address: fmt.Sprintf("tcp://0.0.0.0:%d", port),
Filters: []*node_model.LDSFilters{lfs},
}
ldsL = append(ldsL, plds)
continue
case "HTTP":
case "http":
hsf := &node_model.HTTPSingleFileter{
Type: "decoder",
Name: "router",
}
prs := &node_model.PieceHTTPRoutes{
TimeoutMS: 0,
Prefix: "/",
Cluster: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Prefix: d.ToolsGetRouterItem(serviceAlias, node_model.PREFIX, envs),
Cluster: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
}
domain, ok := service.Labels["domain"]
if !ok {
domain = "*"
envHeaders := d.ToolsGetRouterItem(serviceAlias, node_model.HEADERS, envs)
var headers []*node_model.PieceHeader
if envHeaders != "" {
mm := strings.Split(envHeaders, ",")
for _, h := range mm {
nn := strings.Split(h, ":")
header := &node_model.PieceHeader{
Name: nn[0],
Value: nn[1],
}
headers = append(headers, header)
}
}
if len(headers) != 0 {
prs.Headers = headers
}
pvh := &node_model.PieceHTTPVirtualHost{
Name: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Domains: []string{domain},
//TODO: 目前支持自定义一个domain
Name: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
Domains: []string{d.ToolsGetRouterItem(serviceAlias, node_model.DOMAINS, envs)},
Routes: []*node_model.PieceHTTPRoutes{prs},
}
rcg := &node_model.RouteConfig{
@ -183,8 +202,8 @@ func (d *DiscoverAction) DiscoverListeners(namespace, serviceCluster string) (*n
Config: lhc,
}
plds := &node_model.PieceLDS{
Name: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Address: fmt.Sprintf("tcp://0.0.0.0:%v", port.TargetPort),
Name: fmt.Sprintf("%s_%s_%d", namespace, serviceAlias, port),
Address: fmt.Sprintf("tcp://0.0.0.0:%d", port),
Filters: []*node_model.LDSFilters{lfs},
}
ldsL = append(ldsL, plds)
@ -200,7 +219,17 @@ func (d *DiscoverAction) DiscoverListeners(namespace, serviceCluster string) (*n
}
//DiscoverClusters DiscoverClusters
func (d *DiscoverAction) DiscoverClusters(namespace, serviceCluster string) (*node_model.CDS, *util.APIHandleError) {
func (d *DiscoverAction) DiscoverClusters(tenantService, serviceCluster string) (*node_model.CDS, *util.APIHandleError) {
nn := strings.Split(tenantService, "_")
if len(nn) != 2 {
return nil, util.CreateAPIHandleError(400, fmt.Errorf("namesapces and service_alias not in good format"))
}
namespace := nn[0]
serviceAlias := nn[1]
envs, err := d.ToolsGetMainPodEnvs(namespace, serviceAlias)
if err != nil {
return nil, err
}
mm := strings.Split(serviceCluster, "_")
if len(mm) == 0 {
return nil, util.CreateAPIHandleError(400, fmt.Errorf("service_name is not in good format"))
@ -213,17 +242,31 @@ func (d *DiscoverAction) DiscoverClusters(namespace, serviceCluster string) (*no
return nil, util.CreateAPIHandleError(500, err)
}
for _, service := range services.Items {
for _, port := range service.Spec.Ports {
pcds := &node_model.PieceCDS{
Name: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Type: "sds",
ConnectTimeoutMS: 250,
LBType: "round_robin",
ServiceName: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
}
cdsL = append(cdsL, pcds)
inner, ok := service.Labels["service_type"]
if !ok || inner != "inner" {
continue
}
circuits, errC := strconv.Atoi(d.ToolsGetRouterItem(serviceAlias, node_model.LIMITS, envs))
if errC != nil {
circuits = 1024
logrus.Warnf("strconv circuit error, ignore this error and set circuits to 1024")
}
cb := &node_model.CircuitBreakers{
Default: &node_model.MaxConnections{
MaxConnections: circuits,
},
}
port := service.Spec.Ports[0]
pcds := &node_model.PieceCDS{
Name: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
Type: "sds",
ConnectTimeoutMS: 250,
LBType: "round_robin",
ServiceName: fmt.Sprintf("%s_%s_%v", namespace, serviceAlias, port.Port),
CircuitBreakers: cb,
}
cdsL = append(cdsL, pcds)
continue
}
}
cds := &node_model.CDS{
@ -240,3 +283,80 @@ func (d *DiscoverAction) ToolsGetK8SServiceList(uuid string) (*v1.ServiceList, e
}
return serviceList, nil
}
//ToolsGetMainPodEnvs ToolsGetMainPodEnvs
func (d *DiscoverAction) ToolsGetMainPodEnvs(namespace, serviceAlias string) (*[]v1.EnvVar, *util.APIHandleError) {
labelname := fmt.Sprintf("name=%s", serviceAlias)
pods, err := k8s.K8S.Core().Pods(namespace).List(metav1.ListOptions{LabelSelector: labelname})
logrus.Debugf("service_alias %s pod is %v", serviceAlias, pods)
if err != nil {
return nil, util.CreateAPIHandleError(500, err)
}
if len(pods.Items) == 0 {
return nil,
util.CreateAPIHandleError(404, fmt.Errorf("have no pod for discover"))
}
if len(pods.Items[0].Spec.Containers) < 2 {
return nil,
util.CreateAPIHandleError(404, fmt.Errorf("have no net plugins for discover"))
}
for _, c := range pods.Items[0].Spec.Containers {
for _, e := range c.Env {
if e.Name == "PLUGIN_MOEL" && strings.Contains(e.Value, "net-plugin") {
return &c.Env, nil
}
}
}
return nil, util.CreateAPIHandleError(404, fmt.Errorf("have no envs for plugin"))
}
//ToolsBuildPieceLDS ToolsBuildPieceLDS
func (d *DiscoverAction) ToolsBuildPieceLDS() {}
//ToolsGetRouterItem ToolsGetRouterItem
func (d *DiscoverAction) ToolsGetRouterItem(destAlias, kind string, envs *[]v1.EnvVar) string {
switch kind {
case node_model.PREFIX:
ename := fmt.Sprintf("PREFIX_%s", destAlias)
for _, e := range *envs {
if e.Name == ename {
return e.Value
}
}
return "/"
case node_model.LIMITS:
ename := fmt.Sprintf("LIMIT_%s", destAlias)
for _, e := range *envs {
if e.Name == ename {
return e.Value
}
}
return "1024"
case node_model.HEADERS:
ename := fmt.Sprintf("HEADER_%s", destAlias)
for _, e := range *envs {
if e.Name == ename {
return e.Value
}
}
return ""
case node_model.DOMAINS:
ename := fmt.Sprintf("DOMAIN_%s", destAlias)
for _, e := range *envs {
if e.Name == ename {
return e.Value
}
}
return "*"
}
return ""
}
func getEnvValue(ename string, envs *[]v1.EnvVar) string {
for _, e := range *envs {
if e.Name == ename {
return e.Value
}
}
return ""
}

View File

@ -116,8 +116,9 @@ func (k *K8sServiceBuild) createInnerService(port *model.TenantServicesPort) *v1
var service v1.Service
service.Name = fmt.Sprintf("service-%d-%d", port.ID, port.ContainerPort)
service.Labels = map[string]string{
"service_type": "inner",
"name": k.service.ServiceAlias + "Service",
"service_type": "inner",
"name": k.service.ServiceAlias + "Service",
"port_protocol": port.Protocol,
}
var servicePort v1.ServicePort
if port.Protocol == "udp" {