mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-29 18:27:58 +08:00
[ADD] add new app runtime conversion code
This commit is contained in:
parent
2935ee9191
commit
f178a0e213
@ -397,3 +397,9 @@ type AppBackupDao interface {
|
||||
GetDeleteAppBackup(backupID string) (*model.AppBackup, error)
|
||||
GetDeleteAppBackups() ([]*model.AppBackup, error)
|
||||
}
|
||||
|
||||
//ServiceSourceDao service source dao
|
||||
type ServiceSourceDao interface {
|
||||
Dao
|
||||
GetServiceSource(serviceID string) ([]*model.ServiceSourceConfig, error)
|
||||
}
|
||||
|
5
db/db.go
5
db/db.go
@ -20,6 +20,7 @@ package db
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/goodrain/rainbond/db/config"
|
||||
"github.com/goodrain/rainbond/db/dao"
|
||||
@ -102,6 +103,7 @@ type Manager interface {
|
||||
|
||||
NotificationEventDao() dao.NotificationEventDao
|
||||
AppBackupDao() dao.AppBackupDao
|
||||
ServiceSourceDao() dao.ServiceSourceDao
|
||||
}
|
||||
|
||||
var defaultManager Manager
|
||||
@ -110,11 +112,12 @@ var defaultManager Manager
|
||||
func CreateManager(config config.Config) (err error) {
|
||||
if config.DBType == "mysql" || config.DBType == "cockroachdb" {
|
||||
defaultManager, err = mysql.CreateManager(config)
|
||||
return err
|
||||
} else {
|
||||
//TODO:etcd 插件实现
|
||||
//defaultManager, err = etcd.CreateManager(config)
|
||||
}
|
||||
return
|
||||
return fmt.Errorf("Db drivers not supported")
|
||||
}
|
||||
|
||||
//CloseManager 关闭
|
||||
|
@ -117,3 +117,17 @@ type LocalScheduler struct {
|
||||
func (t *LocalScheduler) TableName() string {
|
||||
return "local_scheduler"
|
||||
}
|
||||
|
||||
//ServiceSourceConfig service source config info
|
||||
//such as deployment、statefulset、configmap
|
||||
type ServiceSourceConfig struct {
|
||||
Model
|
||||
ServiceID string `gorm:"column:service_id;size:32"`
|
||||
SourceType string `gorm:"column:source_type;size:32"`
|
||||
SourceBody string `gorm:"column:source_body;size:2000"`
|
||||
}
|
||||
|
||||
//TableName 表名
|
||||
func (t *ServiceSourceConfig) TableName() string {
|
||||
return "tenant_service_source"
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ type Interface interface {
|
||||
//Tenants 租户信息
|
||||
type Tenants struct {
|
||||
Model
|
||||
Name string `gorm:"column:name;size:40;unique_index"`
|
||||
UUID string `gorm:"column:uuid;size:33;unique_index"`
|
||||
EID string `gorm:"column:eid"`
|
||||
Name string `gorm:"column:name;size:40;unique_index"`
|
||||
UUID string `gorm:"column:uuid;size:33;unique_index"`
|
||||
EID string `gorm:"column:eid"`
|
||||
LimitMemory int `gorm:"column:limit_memory"`
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ func (t *Tenants) TableName() string {
|
||||
return "tenants"
|
||||
}
|
||||
|
||||
//TenantServices 租户应用
|
||||
//TenantServices app service base info
|
||||
type TenantServices struct {
|
||||
Model
|
||||
TenantID string `gorm:"column:tenant_id;size:32" json:"tenant_id"`
|
||||
@ -68,25 +68,27 @@ type TenantServices struct {
|
||||
ServiceKey string `gorm:"column:service_key;size:32" json:"service_key"`
|
||||
// 服务别名
|
||||
ServiceAlias string `gorm:"column:service_alias;size:30" json:"service_alias"`
|
||||
// service regist endpoint name(host name), used of statefulset
|
||||
ServiceName string `gorm:"column:service_name;size:100" json:"service_name"`
|
||||
// 服务描述
|
||||
Comment string `gorm:"column:comment" json:"comment"`
|
||||
// 服务版本
|
||||
// 服务版本(deprecated)
|
||||
ServiceVersion string `gorm:"column:service_version;size:32" json:"service_version"`
|
||||
// 镜像名称
|
||||
// 镜像名称(deprecated)
|
||||
ImageName string `gorm:"column:image_name;size:100" json:"image_name"`
|
||||
// 容器CPU权重
|
||||
ContainerCPU int `gorm:"column:container_cpu;default:500" json:"container_cpu"`
|
||||
// 容器最大内存
|
||||
ContainerMemory int `gorm:"column:container_memory;default:128" json:"container_memory"`
|
||||
// 容器启动命令
|
||||
// 容器启动命令(deprecated)
|
||||
ContainerCMD string `gorm:"column:container_cmd;size:2048" json:"container_cmd"`
|
||||
// 容器环境变量
|
||||
// 容器环境变量(deprecated)
|
||||
ContainerEnv string `gorm:"column:container_env;size:255" json:"container_env"`
|
||||
// 卷名字
|
||||
// 卷名字 (deprecated)
|
||||
VolumePath string `gorm:"column:volume_path" json:"volume_path"`
|
||||
// 容器挂载目录
|
||||
// 容器挂载目录 (deprecated)
|
||||
VolumeMountPath string `gorm:"column:volume_mount_path" json:"volume_mount_path"`
|
||||
// 宿主机目录
|
||||
// 宿主机目录 (deprecated)
|
||||
HostPath string `gorm:"column:host_path" json:"host_path"`
|
||||
// 扩容方式;0:无状态;1:有状态;2:分区
|
||||
ExtendMethod string `gorm:"column:extend_method;default:'stateless';" json:"extend_method"`
|
||||
@ -96,27 +98,27 @@ type TenantServices struct {
|
||||
DeployVersion string `gorm:"column:deploy_version" json:"deploy_version"`
|
||||
// 服务分类:application,cache,store
|
||||
Category string `gorm:"column:category" json:"category"`
|
||||
// 服务当前状态:undeploy,running,closed,unusual,starting,checking,stoping
|
||||
// 服务当前状态:undeploy,running,closed,unusual,starting,checking,stoping(deprecated)
|
||||
CurStatus string `gorm:"column:cur_status;default:'undeploy'" json:"cur_status"`
|
||||
// 计费状态 为1 计费,为0不计费
|
||||
// 计费状态 为1 计费,为0不计费 (deprecated)
|
||||
Status int `gorm:"column:status;default:0" json:"status"`
|
||||
// 最新操作ID
|
||||
EventID string `gorm:"column:event_id" json:"event_id"`
|
||||
// 服务类型
|
||||
// 服务类型 (deprecated)
|
||||
ServiceType string `gorm:"column:service_type" json:"service_type"`
|
||||
// 镜像来源
|
||||
// 租户ID
|
||||
Namespace string `gorm:"column:namespace" json:"namespace"`
|
||||
// 共享类型shared、exclusive
|
||||
// 共享类型shared、exclusive(deprecated)
|
||||
VolumeType string `gorm:"column:volume_type;default:'shared'" json:"volume_type"`
|
||||
// 端口类型,one_outer;dif_protocol;multi_outer
|
||||
// 端口类型,one_outer;dif_protocol;multi_outer (deprecated)
|
||||
PortType string `gorm:"column:port_type;default:'multi_outer'" json:"port_type"`
|
||||
// 更新时间
|
||||
UpdateTime time.Time `gorm:"column:update_time" json:"update_time"`
|
||||
// 服务创建类型cloud云市服务,assistant云帮服务
|
||||
ServiceOrigin string `gorm:"column:service_origin;default:'assistant'" json:"service_origin"`
|
||||
// 代码来源:gitlab,github
|
||||
// 代码来源:gitlab,github (deprecated)
|
||||
CodeFrom string `gorm:"column:code_from" json:"code_from"`
|
||||
|
||||
//(deprecated)
|
||||
Domain string `gorm:"column:domain" json:"domain"`
|
||||
}
|
||||
|
||||
@ -204,6 +206,8 @@ type TenantServicesDelete struct {
|
||||
ServiceKey string `gorm:"column:service_key;size:32" json:"service_key"`
|
||||
// 服务别名
|
||||
ServiceAlias string `gorm:"column:service_alias;size:30" json:"service_alias"`
|
||||
// service regist endpoint name(host name), used of statefulset
|
||||
ServiceName string `gorm:"column:service_name;size:100" json:"service_name"`
|
||||
// 服务描述
|
||||
Comment string `gorm:"column:comment" json:"comment"`
|
||||
// 服务版本
|
||||
|
@ -35,7 +35,8 @@ type VersionInfo struct {
|
||||
//slug: this is a source code tar file
|
||||
DeliveredType string `gorm:"column:delivered_type;size:40"` //kind
|
||||
DeliveredPath string `gorm:"column:delivered_path;size:250"` //交付物path
|
||||
ImageName string `gorm:"column:image_name;size:250"` //交付物path
|
||||
ImageName string `gorm:"column:image_name;size:250"` //运行镜像名称
|
||||
Cmd string `gorm:"column:cmd;size:200"` //启动命令
|
||||
RepoURL string `gorm:"column:repo_url;size:100"`
|
||||
CodeVersion string `gorm:"column:code_version;size:40"`
|
||||
CommitMsg string `gorm:"column:code_commit_msg;size:200"`
|
||||
|
@ -469,3 +469,44 @@ func (t *LocalSchedulerDaoImpl) GetLocalScheduler(serviceID string) ([]*model.Lo
|
||||
}
|
||||
return ls, nil
|
||||
}
|
||||
|
||||
//ServiceSourceImpl service source
|
||||
type ServiceSourceImpl struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
//AddModel add service source
|
||||
func (t *ServiceSourceImpl) AddModel(mo model.Interface) error {
|
||||
ls := mo.(*model.ServiceSourceConfig)
|
||||
var oldLs model.ServiceSourceConfig
|
||||
if ok := t.DB.Where("service_id=? and source_type=?", ls.ServiceID, ls.SourceType).Find(&oldLs).RecordNotFound(); ok {
|
||||
if err := t.DB.Create(ls).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
oldLs.SourceBody = ls.SourceBody
|
||||
t.DB.Save(oldLs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//UpdateModel update service source
|
||||
func (t *ServiceSourceImpl) UpdateModel(mo model.Interface) error {
|
||||
ls := mo.(*model.LocalScheduler)
|
||||
if ls.ID == 0 {
|
||||
return fmt.Errorf("ServiceSourceImpl id can not be empty when update ")
|
||||
}
|
||||
if err := t.DB.Save(ls).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//GetServiceSource get services source
|
||||
func (t *ServiceSourceImpl) GetServiceSource(serviceID string) ([]*model.ServiceSourceConfig, error) {
|
||||
var serviceSources []*model.ServiceSourceConfig
|
||||
if err := t.DB.Where("service_id=?", serviceID).Find(&serviceSources).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return serviceSources, nil
|
||||
}
|
||||
|
@ -458,3 +458,10 @@ func (m *Manager) AppBackupDao() dao.AppBackupDao {
|
||||
DB: m.db,
|
||||
}
|
||||
}
|
||||
|
||||
//ServiceSourceDao service source db impl
|
||||
func (m *Manager) ServiceSourceDao() dao.ServiceSourceDao {
|
||||
return &mysqldao.ServiceSourceImpl{
|
||||
DB: m.db,
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ func (m *Manager) RegisterTableModel() {
|
||||
m.models = append(m.models, &model.NotificationEvent{})
|
||||
m.models = append(m.models, &model.AppStatus{})
|
||||
m.models = append(m.models, &model.AppBackup{})
|
||||
m.models = append(m.models, &model.ServiceSourceConfig{})
|
||||
}
|
||||
|
||||
//CheckTable check and create tables
|
||||
|
@ -0,0 +1,64 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/db"
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
//first conv service source
|
||||
RegistConversion(ServiceSource)
|
||||
//step2 conv service base
|
||||
RegistConversion(TenantServiceBase)
|
||||
//step3 conv service pod base info
|
||||
RegistConversion(TenantServiceVersion)
|
||||
//step4 conv service plugin
|
||||
RegistConversion(TenantServicePlugin)
|
||||
//step5 conv service inner and outer regist
|
||||
RegistConversion(TenantServiceRegist)
|
||||
}
|
||||
|
||||
//Conversion conversion function
|
||||
//Any application attribute implementation is similarly injected
|
||||
type Conversion func(*v1.AppService, db.Manager) error
|
||||
|
||||
//conversionList conversion function list
|
||||
var conversionList []Conversion
|
||||
|
||||
//RegistConversion regist conversion function list
|
||||
func RegistConversion(fun Conversion) {
|
||||
conversionList = append(conversionList, fun)
|
||||
}
|
||||
|
||||
//InitAppService init a app service
|
||||
func InitAppService(dbmanager db.Manager, serviceID string) (*v1.AppService, error) {
|
||||
appService := &v1.AppService{
|
||||
AppServiceBase: v1.AppServiceBase{
|
||||
ServiceID: serviceID,
|
||||
},
|
||||
}
|
||||
for _, c := range conversionList {
|
||||
if err := c(appService, dbmanager); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return appService, nil
|
||||
}
|
42
worker/appm/conversion/conversion_test.go
Normal file
42
worker/appm/conversion/conversion_test.go
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goodrain/rainbond/db/config"
|
||||
|
||||
"github.com/goodrain/rainbond/db"
|
||||
)
|
||||
|
||||
func TestInitAppService(t *testing.T) {
|
||||
err := db.CreateManager(config.Config{
|
||||
MysqlConnectionInfo: "root:ASDASDASDASDASD@tcp(ali-sh-s1.goodrain.net:21194)/region",
|
||||
DBType: "mysql",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
as, err := InitAppService(db.GetManager(), "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(as)
|
||||
}
|
49
worker/appm/conversion/gateway.go
Normal file
49
worker/appm/conversion/gateway.go
Normal file
@ -0,0 +1,49 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/goodrain/rainbond/db"
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
)
|
||||
|
||||
//createDefaultDomain create default domain
|
||||
func createDefaultDomain(tenantName, serviceAlias string, servicePort int) string {
|
||||
exDomain := os.Getenv("EX_DOMAIN")
|
||||
if exDomain == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.Contains(exDomain, ":") {
|
||||
exDomain = strings.Split(exDomain, ":")[0]
|
||||
}
|
||||
if exDomain[0] == '.' {
|
||||
exDomain = exDomain[1:]
|
||||
}
|
||||
exDomain = strings.TrimSpace(exDomain)
|
||||
return fmt.Sprintf("%d.%s.%s.%s", servicePort, serviceAlias, tenantName, exDomain)
|
||||
}
|
||||
|
||||
//TenantServiceRegist conv inner and outer service regist
|
||||
func TenantServiceRegist(as *v1.AppService, dbmanager db.Manager) error {
|
||||
return nil
|
||||
}
|
30
worker/appm/conversion/labels.go
Normal file
30
worker/appm/conversion/labels.go
Normal file
@ -0,0 +1,30 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
func getCommonLable(labels ...map[string]string) map[string]string {
|
||||
var resultLabel = make(map[string]string)
|
||||
for _, l := range labels {
|
||||
for k, v := range l {
|
||||
resultLabel[k] = v
|
||||
}
|
||||
}
|
||||
resultLabel["creater"] = "Rainbond"
|
||||
return resultLabel
|
||||
}
|
29
worker/appm/conversion/plugin.go
Normal file
29
worker/appm/conversion/plugin.go
Normal file
@ -0,0 +1,29 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/db"
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
)
|
||||
|
||||
//TenantServicePlugin conv service all plugin
|
||||
func TenantServicePlugin(as *v1.AppService, dbmanager db.Manager) error {
|
||||
return nil
|
||||
}
|
158
worker/appm/conversion/service.go
Normal file
158
worker/appm/conversion/service.go
Normal file
@ -0,0 +1,158 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/goodrain/rainbond/db"
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
"github.com/jinzhu/gorm"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
//ServiceSource conv ServiceSource
|
||||
func ServiceSource(as *v1.AppService, dbmanager db.Manager) error {
|
||||
sscs, err := dbmanager.ServiceSourceDao().GetServiceSource(as.ServiceID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("conv service source failure %s", err.Error())
|
||||
}
|
||||
for _, ssc := range sscs {
|
||||
switch ssc.SourceType {
|
||||
case "deployment":
|
||||
var dm appsv1.Deployment
|
||||
if err := decoding(ssc.SourceBody, &dm); err != nil {
|
||||
return decodeError(err)
|
||||
}
|
||||
as.SetDeployment(&dm)
|
||||
case "statefulset":
|
||||
var ss appsv1.StatefulSet
|
||||
if err := decoding(ssc.SourceBody, &ss); err != nil {
|
||||
return decodeError(err)
|
||||
}
|
||||
as.SetStatefulSet(&ss)
|
||||
case "configmap":
|
||||
var cm corev1.ConfigMap
|
||||
if err := decoding(ssc.SourceBody, &cm); err != nil {
|
||||
return decodeError(err)
|
||||
}
|
||||
as.SetConfigMap(&cm)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func decodeError(err error) error {
|
||||
return fmt.Errorf("decode service source failure %s", err.Error())
|
||||
}
|
||||
func decoding(source string, target interface{}) error {
|
||||
return yaml.Unmarshal([]byte(source), target)
|
||||
}
|
||||
func int32Ptr(i int) *int32 {
|
||||
j := int32(i)
|
||||
return &j
|
||||
}
|
||||
|
||||
//TenantServiceBase conv tenant service base info
|
||||
func TenantServiceBase(as *v1.AppService, dbmanager db.Manager) error {
|
||||
tenantService, err := dbmanager.TenantServiceDao().GetServiceByID(as.ServiceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get service base info failure %s", err.Error())
|
||||
}
|
||||
tenant, err := dbmanager.TenantDao().GetTenantByUUID(tenantService.TenantID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get tenant info failure %s", err.Error())
|
||||
}
|
||||
serviceType, err := dbmanager.TenantServiceLabelDao().GetTenantServiceTypeLabel(as.ServiceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get service type info failure %s", err.Error())
|
||||
}
|
||||
as.TenantID = tenantService.TenantID
|
||||
as.DeployVersion = tenantService.DeployVersion
|
||||
as.ContainerCPU = tenantService.ContainerCPU
|
||||
as.ContainerMemory = tenantService.ContainerMemory
|
||||
as.Replicas = tenantService.Replicas
|
||||
as.ServiceAlias = tenantService.ServiceAlias
|
||||
as.CreaterID = util.NewUUID()
|
||||
as.TenantName = tenant.Name
|
||||
if serviceType.LabelValue == util.StatefulServiceType {
|
||||
as.ServiceType = v1.TypeStatefulSet
|
||||
statefulset := as.GetStatefulSet()
|
||||
if statefulset == nil {
|
||||
statefulset = &appsv1.StatefulSet{}
|
||||
}
|
||||
initBaseStatefulSet(tenantService, statefulset)
|
||||
as.SetStatefulSet(statefulset)
|
||||
}
|
||||
if serviceType.LabelValue == util.StatelessServiceType {
|
||||
as.ServiceType = v1.TypeDeployment
|
||||
deployment := as.GetDeployment()
|
||||
if deployment == nil {
|
||||
deployment = &appsv1.Deployment{}
|
||||
}
|
||||
initBaseDeployment(tenantService, deployment)
|
||||
as.SetDeployment(deployment)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initSelector(selector *metav1.LabelSelector, service *dbmodel.TenantServices) {
|
||||
selector.MatchLabels["name"] = service.ServiceAlias
|
||||
selector.MatchLabels["version"] = service.DeployVersion
|
||||
}
|
||||
func initBaseStatefulSet(service *dbmodel.TenantServices, stateful *appsv1.StatefulSet) {
|
||||
stateful.Spec.Replicas = int32Ptr(service.Replicas)
|
||||
if stateful.Spec.Selector == nil {
|
||||
stateful.Spec.Selector = &metav1.LabelSelector{}
|
||||
}
|
||||
initSelector(stateful.Spec.Selector, service)
|
||||
stateful.Spec.ServiceName = service.ServiceName
|
||||
stateful.Namespace = service.TenantID
|
||||
stateful.Name = service.ServiceAlias
|
||||
stateful.GenerateName = service.ServiceAlias
|
||||
stateful.Labels = getCommonLable(stateful.Labels, map[string]string{
|
||||
"name": service.ServiceAlias,
|
||||
"version": service.DeployVersion,
|
||||
"service_id": service.ServiceID,
|
||||
})
|
||||
}
|
||||
|
||||
func initBaseDeployment(service *dbmodel.TenantServices, deploymemnt *appsv1.Deployment) {
|
||||
deploymemnt.Spec.Replicas = int32Ptr(service.Replicas)
|
||||
if deploymemnt.Spec.Selector == nil {
|
||||
deploymemnt.Spec.Selector = &metav1.LabelSelector{}
|
||||
}
|
||||
initSelector(deploymemnt.Spec.Selector, service)
|
||||
deploymemnt.Namespace = service.TenantID
|
||||
deploymemnt.Name = util.NewUUID()
|
||||
deploymemnt.GenerateName = strings.Replace(service.ServiceAlias, "_", "-", -1)
|
||||
deploymemnt.Labels = getCommonLable(deploymemnt.Labels, map[string]string{
|
||||
"name": service.ServiceAlias,
|
||||
"version": service.DeployVersion,
|
||||
"service_id": service.ServiceID,
|
||||
})
|
||||
}
|
601
worker/appm/conversion/version.go
Normal file
601
worker/appm/conversion/version.go
Normal file
@ -0,0 +1,601 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
"github.com/goodrain/rainbond/db"
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
//TenantServiceVersion service deploy version conv. define pod spec
|
||||
func TenantServiceVersion(as *v1.AppService, dbmanager db.Manager) error {
|
||||
version, err := dbmanager.VersionInfoDao().GetVersionByDeployVersion(as.DeployVersion, as.ServiceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get service deploy version failure %s", err.Error())
|
||||
}
|
||||
dv, err := createVolumes(as, version, dbmanager)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create volume in pod template error :%s", err.Error())
|
||||
}
|
||||
container, err := getMainContainer(as, version, dv, dbmanager)
|
||||
if err != nil {
|
||||
return fmt.Errorf("conv service envs failure %s", err.Error())
|
||||
}
|
||||
podtmpSpec := corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
Volumes: dv.GetVolumes(),
|
||||
Containers: []corev1.Container{*container},
|
||||
NodeSelector: createNodeSelector(as, dbmanager),
|
||||
Affinity: createAffinity(as, dbmanager),
|
||||
},
|
||||
}
|
||||
//set annotations feature by env
|
||||
setFeature(&podtmpSpec)
|
||||
//set to deployment or statefulset
|
||||
as.SetPodTemplate(podtmpSpec)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMainContainer(as *v1.AppService, version *dbmodel.VersionInfo, dv *volumeDefine, dbmanager db.Manager) (*corev1.Container, error) {
|
||||
envs, err := createEnv(as, dbmanager)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("conv service envs failure %s", err.Error())
|
||||
}
|
||||
args := createArgs(version, *envs)
|
||||
resources := createResources(as)
|
||||
ports := createPorts(as, dbmanager)
|
||||
return &corev1.Container{
|
||||
Name: as.ServiceID,
|
||||
Image: version.ImageName,
|
||||
Args: args,
|
||||
Ports: ports,
|
||||
Env: *envs,
|
||||
VolumeMounts: dv.GetVolumeMounts(),
|
||||
LivenessProbe: createProbe(as, dbmanager, "liveness"),
|
||||
ReadinessProbe: createProbe(as, dbmanager, "readiness"),
|
||||
Resources: resources,
|
||||
}, nil
|
||||
}
|
||||
|
||||
//GetConfigKey 获取配置key
|
||||
func GetConfigKey(rk string) string {
|
||||
if len(rk) < 4 {
|
||||
return ""
|
||||
}
|
||||
left := strings.Index(rk, "{")
|
||||
right := strings.Index(rk, "}")
|
||||
return rk[left+1 : right]
|
||||
}
|
||||
|
||||
func getenv(key string, envs []corev1.EnvVar) string {
|
||||
for _, env := range envs {
|
||||
if env.Name == key {
|
||||
return env.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func createArgs(version *dbmodel.VersionInfo, envs []corev1.EnvVar) (args []string) {
|
||||
if version.Cmd == "" {
|
||||
return
|
||||
}
|
||||
cmd := version.Cmd
|
||||
var reg = regexp.MustCompile(`(?U)\$\{.*\}`)
|
||||
resultKey := reg.FindAllString(cmd, -1)
|
||||
for _, rk := range resultKey {
|
||||
value := getenv(GetConfigKey(rk), envs)
|
||||
cmd = strings.Replace(cmd, rk, value, -1)
|
||||
}
|
||||
args = strings.Split(cmd, " ")
|
||||
args = util.RemoveSpaces(args)
|
||||
return args
|
||||
}
|
||||
|
||||
//createEnv create service container env
|
||||
func createEnv(as *v1.AppService, dbmanager db.Manager) (*[]corev1.EnvVar, error) {
|
||||
var envs []corev1.EnvVar
|
||||
var envsAll []*dbmodel.TenantServiceEnvVar
|
||||
//set relation app outer env
|
||||
relations, err := dbmanager.TenantServiceRelationDao().GetTenantServiceRelations(as.ServiceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if relations != nil && len(relations) > 0 {
|
||||
var relationIDs []string
|
||||
for _, r := range relations {
|
||||
relationIDs = append(relationIDs, r.DependServiceID)
|
||||
}
|
||||
if len(relationIDs) > 0 {
|
||||
es, err := dbmanager.TenantServiceEnvVarDao().GetDependServiceEnvs(relationIDs, []string{"outer", "both"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if es != nil {
|
||||
envsAll = append(envsAll, es...)
|
||||
}
|
||||
serviceAliass, err := dbmanager.TenantServiceDao().GetServiceAliasByIDs(relationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var Depend string
|
||||
for _, sa := range serviceAliass {
|
||||
if Depend != "" {
|
||||
Depend += ","
|
||||
}
|
||||
Depend += fmt.Sprintf("%s:%s", sa.ServiceAlias, sa.ServiceID)
|
||||
}
|
||||
envs = append(envs, corev1.EnvVar{Name: "DEPEND_SERVICE", Value: Depend})
|
||||
as.NeedProxy = true
|
||||
}
|
||||
}
|
||||
//set app relation env
|
||||
relations, err = dbmanager.TenantServiceRelationDao().GetTenantServiceRelationsByDependServiceID(as.ServiceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if relations != nil && len(relations) > 0 {
|
||||
var relationIDs []string
|
||||
for _, r := range relations {
|
||||
relationIDs = append(relationIDs, r.ServiceID)
|
||||
}
|
||||
if len(relationIDs) > 0 {
|
||||
serviceAliass, err := dbmanager.TenantServiceDao().GetServiceAliasByIDs(relationIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var Depend string
|
||||
for _, sa := range serviceAliass {
|
||||
if Depend != "" {
|
||||
Depend += ","
|
||||
}
|
||||
Depend += fmt.Sprintf("%s:%s", sa.ServiceAlias, sa.ServiceID)
|
||||
}
|
||||
envs = append(envs, corev1.EnvVar{Name: "REVERSE_DEPEND_SERVICE", Value: Depend})
|
||||
}
|
||||
}
|
||||
//set app port and net env
|
||||
ports, err := dbmanager.TenantServicesPortDao().GetPortsByServiceID(as.ServiceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ports != nil && len(ports) > 0 {
|
||||
var portStr string
|
||||
for i, port := range ports {
|
||||
if i == 0 {
|
||||
envs = append(envs, corev1.EnvVar{Name: "PORT", Value: strconv.Itoa(ports[0].ContainerPort)})
|
||||
envs = append(envs, corev1.EnvVar{Name: "PROTOCOL", Value: ports[0].Protocol})
|
||||
}
|
||||
if portStr != "" {
|
||||
portStr += ":"
|
||||
}
|
||||
portStr += fmt.Sprintf("%d", port.ContainerPort)
|
||||
if port.IsOuterService && (port.Protocol == "http" || port.Protocol == "https") {
|
||||
envs = append(envs, corev1.EnvVar{Name: fmt.Sprintf("DEFAULT_DOMAIN_%d", port.ContainerPort), Value: createDefaultDomain(as.TenantName, as.ServiceAlias, port.ContainerPort)})
|
||||
}
|
||||
}
|
||||
envs = append(envs, corev1.EnvVar{Name: "MONITOR_PORT", Value: portStr})
|
||||
}
|
||||
//set net mode env by get from system
|
||||
envs = append(envs, corev1.EnvVar{Name: "CUR_NET", Value: os.Getenv("CUR_NET")})
|
||||
//set app custom envs
|
||||
es, err := dbmanager.TenantServiceEnvVarDao().GetServiceEnvs(as.ServiceID, []string{"inner", "both", "outer"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(es) > 0 {
|
||||
envsAll = append(envsAll, es...)
|
||||
}
|
||||
for _, e := range envsAll {
|
||||
envs = append(envs, corev1.EnvVar{Name: e.AttrName, Value: e.AttrValue})
|
||||
}
|
||||
//set default env
|
||||
envs = append(envs, corev1.EnvVar{Name: "TENANT_ID", Value: as.TenantID})
|
||||
envs = append(envs, corev1.EnvVar{Name: "SERVICE_ID", Value: as.ServiceID})
|
||||
envs = append(envs, corev1.EnvVar{Name: "MEMORY_SIZE", Value: getMemoryType(as.ContainerMemory)})
|
||||
envs = append(envs, corev1.EnvVar{Name: "SERVICE_NAME", Value: as.ServiceAlias})
|
||||
envs = append(envs, corev1.EnvVar{Name: "SERVICE_POD_NUM", Value: strconv.Itoa(as.Replicas)})
|
||||
envs = append(envs, corev1.EnvVar{Name: "HOST_IP", ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
FieldPath: "status.hostIP",
|
||||
},
|
||||
}})
|
||||
envs = append(envs, corev1.EnvVar{Name: "POD_IP", ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
FieldPath: "status.podIP",
|
||||
},
|
||||
}})
|
||||
return &envs, nil
|
||||
}
|
||||
|
||||
func getMemoryType(memorySize int) string {
|
||||
memoryType := "small"
|
||||
if v, ok := memoryLabels[memorySize]; ok {
|
||||
memoryType = v
|
||||
}
|
||||
return memoryType
|
||||
}
|
||||
|
||||
var memoryLabels = map[int]string{
|
||||
128: "micro",
|
||||
256: "small",
|
||||
512: "medium",
|
||||
1024: "large",
|
||||
2048: "2xlarge",
|
||||
4096: "4xlarge",
|
||||
8192: "8xlarge",
|
||||
16384: "16xlarge",
|
||||
32768: "32xlarge",
|
||||
65536: "64xlarge",
|
||||
}
|
||||
|
||||
func createVolumes(as *v1.AppService, version *dbmodel.VersionInfo, dbmanager db.Manager) (*volumeDefine, error) {
|
||||
var vd = &volumeDefine{}
|
||||
vs, err := dbmanager.TenantServiceVolumeDao().GetTenantServiceVolumesByServiceID(version.ServiceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if vs != nil && len(vs) > 0 {
|
||||
for i := range vs {
|
||||
v := vs[i]
|
||||
if v.VolumeType == dbmodel.ShareFileVolumeType.String() {
|
||||
err := util.CheckAndCreateDir(v.HostPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create host path %s error,%s", v.HostPath, err.Error())
|
||||
}
|
||||
os.Chmod(v.HostPath, 0777)
|
||||
}
|
||||
vd.SetVolume(dbmodel.VolumeType(v.VolumeType), fmt.Sprintf("manual%d", v.ID), v.VolumePath, v.HostPath, v.IsReadOnly)
|
||||
}
|
||||
}
|
||||
//handle Shared storage
|
||||
tsmr, err := dbmanager.TenantServiceMountRelationDao().GetTenantServiceMountRelationsByService(version.ServiceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if vs != nil && len(tsmr) > 0 {
|
||||
for i := range tsmr {
|
||||
t := tsmr[i]
|
||||
err := util.CheckAndCreateDir(t.HostPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create host path %s error,%s", t.HostPath, err.Error())
|
||||
}
|
||||
vd.SetVolume(dbmodel.ShareFileVolumeType, fmt.Sprintf("mnt%d", t.ID), t.VolumePath, t.HostPath, false)
|
||||
}
|
||||
}
|
||||
//handle slug file volume
|
||||
if version.DeliveredType == "slug" {
|
||||
slugPath := version.DeliveredPath
|
||||
vd.SetVolume(dbmodel.ShareFileVolumeType, "slug", "/tmp/slug/slug.tgz", slugPath, true)
|
||||
}
|
||||
//need service mesh sidecar, volume kubeconfig
|
||||
if as.NeedProxy {
|
||||
vd.SetVolume(dbmodel.ShareFileVolumeType, "kube-config", "/etc/kubernetes", "/grdata/kubernetes", true)
|
||||
}
|
||||
return vd, nil
|
||||
}
|
||||
|
||||
type volumeDefine struct {
|
||||
volumeMounts []corev1.VolumeMount
|
||||
volumes []corev1.Volume
|
||||
persistentVolumes []corev1.PersistentVolume
|
||||
}
|
||||
|
||||
func (v *volumeDefine) GetVolumes() []corev1.Volume {
|
||||
return v.volumes
|
||||
}
|
||||
func (v *volumeDefine) GetVolumeMounts() []corev1.VolumeMount {
|
||||
return v.volumeMounts
|
||||
}
|
||||
func (v *volumeDefine) SetVolume(VolumeType dbmodel.VolumeType, name, mountPath, hostPath string, readOnly bool) {
|
||||
for _, m := range v.volumeMounts {
|
||||
if m.MountPath == mountPath {
|
||||
return
|
||||
}
|
||||
}
|
||||
if hostPath != "" {
|
||||
switch VolumeType {
|
||||
case dbmodel.MemoryFSVolumeType:
|
||||
vo := corev1.Volume{Name: name}
|
||||
vo.EmptyDir = &corev1.EmptyDirVolumeSource{
|
||||
Medium: corev1.StorageMediumMemory,
|
||||
}
|
||||
v.volumes = append(v.volumes, vo)
|
||||
if mountPath != "" {
|
||||
vm := corev1.VolumeMount{
|
||||
MountPath: mountPath,
|
||||
Name: name,
|
||||
ReadOnly: readOnly,
|
||||
SubPath: "",
|
||||
}
|
||||
v.volumeMounts = append(v.volumeMounts, vm)
|
||||
}
|
||||
case dbmodel.ShareFileVolumeType:
|
||||
vo := corev1.Volume{
|
||||
Name: name,
|
||||
}
|
||||
vo.HostPath = &corev1.HostPathVolumeSource{
|
||||
Path: hostPath,
|
||||
}
|
||||
v.volumes = append(v.volumes, vo)
|
||||
if mountPath != "" {
|
||||
vm := corev1.VolumeMount{
|
||||
MountPath: mountPath,
|
||||
Name: name,
|
||||
ReadOnly: readOnly,
|
||||
SubPath: "",
|
||||
}
|
||||
v.volumeMounts = append(v.volumeMounts, vm)
|
||||
}
|
||||
case dbmodel.LocalVolumeType:
|
||||
fulesystem := corev1.PersistentVolumeFilesystem
|
||||
localPV := corev1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name + "pv",
|
||||
},
|
||||
Spec: corev1.PersistentVolumeSpec{
|
||||
VolumeMode: &fulesystem,
|
||||
AccessModes: []corev1.PersistentVolumeAccessMode{
|
||||
corev1.ReadWriteOnce,
|
||||
},
|
||||
//do not auto reclaim
|
||||
PersistentVolumeReclaimPolicy: corev1.PersistentVolumeReclaimRetain,
|
||||
StorageClassName: "local-storage",
|
||||
PersistentVolumeSource: corev1.PersistentVolumeSource{
|
||||
Local: &corev1.LocalVolumeSource{
|
||||
Path: hostPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
v.persistentVolumes = append(v.persistentVolumes, localPV)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func createResources(as *v1.AppService) corev1.ResourceRequirements {
|
||||
var cpuRequest, cpuLimit int64
|
||||
memory := as.ContainerMemory
|
||||
if memory < 512 {
|
||||
cpuRequest, cpuLimit = int64(memory)/128*30, int64(memory)/128*80
|
||||
} else if memory <= 1024 {
|
||||
cpuRequest, cpuLimit = int64(memory)/128*30, int64(memory)/128*160
|
||||
} else {
|
||||
cpuRequest, cpuLimit = int64(memory)/128*30, ((int64(memory)-1024)/1024*500 + 1280)
|
||||
}
|
||||
limits := corev1.ResourceList{}
|
||||
limits[corev1.ResourceCPU] = *resource.NewMilliQuantity(
|
||||
cpuLimit,
|
||||
resource.DecimalSI)
|
||||
limits[corev1.ResourceMemory] = *resource.NewQuantity(
|
||||
int64(as.ContainerMemory*1024*1024),
|
||||
resource.BinarySI)
|
||||
request := corev1.ResourceList{}
|
||||
request[corev1.ResourceCPU] = *resource.NewMilliQuantity(
|
||||
cpuRequest,
|
||||
resource.DecimalSI)
|
||||
request[corev1.ResourceMemory] = *resource.NewQuantity(
|
||||
int64(as.ContainerMemory*1024*1024),
|
||||
resource.BinarySI)
|
||||
return corev1.ResourceRequirements{
|
||||
Limits: limits,
|
||||
Requests: request,
|
||||
}
|
||||
}
|
||||
|
||||
func checkUpstreamPluginRelation(serviceID string, dbmanager db.Manager) (bool, error) {
|
||||
return dbmanager.TenantServicePluginRelationDao().CheckSomeModelPluginByServiceID(
|
||||
serviceID,
|
||||
dbmodel.UpNetPlugin)
|
||||
}
|
||||
func createUpstreamPluginMappingPort(
|
||||
ports []*dbmodel.TenantServicesPort,
|
||||
pluginPorts []*dbmodel.TenantServicesStreamPluginPort,
|
||||
) (
|
||||
[]*dbmodel.TenantServicesPort,
|
||||
error) {
|
||||
//start from 65301
|
||||
for i := range ports {
|
||||
port := ports[i]
|
||||
for _, pport := range pluginPorts {
|
||||
if pport.ContainerPort == port.ContainerPort {
|
||||
port.ContainerPort = pport.PluginPort
|
||||
port.MappingPort = pport.PluginPort
|
||||
}
|
||||
}
|
||||
}
|
||||
return ports, nil
|
||||
}
|
||||
func createPorts(as *v1.AppService, dbmanager db.Manager) (ports []corev1.ContainerPort) {
|
||||
ps, err := dbmanager.TenantServicesPortDao().GetPortsByServiceID(as.ServiceID)
|
||||
if err == nil && ps != nil && len(ps) > 0 {
|
||||
crt, err := checkUpstreamPluginRelation(as.ServiceID, dbmanager)
|
||||
if err != nil {
|
||||
//return nil, fmt.Errorf("get service upstream plugin relation error, %s", err.Error())
|
||||
return
|
||||
}
|
||||
if crt {
|
||||
pluginPorts, err := dbmanager.TenantServicesStreamPluginPortDao().GetPluginMappingPorts(
|
||||
as.ServiceID,
|
||||
dbmodel.UpNetPlugin,
|
||||
)
|
||||
if err != nil {
|
||||
//return nil, fmt.Errorf("find upstream plugin mapping port error, %s", err.Error())
|
||||
return
|
||||
}
|
||||
ps, err = createUpstreamPluginMappingPort(ps, pluginPorts)
|
||||
}
|
||||
for i := range ps {
|
||||
p := ps[i]
|
||||
var hostPort int32
|
||||
if p.IsOuterService && os.Getenv("CUR_NET") == "midonet" {
|
||||
hostPort = 1
|
||||
}
|
||||
ports = append(ports, corev1.ContainerPort{
|
||||
HostPort: hostPort,
|
||||
ContainerPort: int32(p.ContainerPort),
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createProbe(as *v1.AppService, dbmanager db.Manager, mode string) *corev1.Probe {
|
||||
probe, err := dbmanager.ServiceProbeDao().GetServiceUsedProbe(as.ServiceID, mode)
|
||||
if err == nil && probe != nil {
|
||||
if mode == "liveness" && probe.SuccessThreshold < 1 {
|
||||
probe.SuccessThreshold = 1
|
||||
}
|
||||
if mode == "readiness" && probe.FailureThreshold < 1 {
|
||||
probe.FailureThreshold = 3
|
||||
}
|
||||
p := &corev1.Probe{
|
||||
FailureThreshold: int32(probe.FailureThreshold),
|
||||
SuccessThreshold: int32(probe.SuccessThreshold),
|
||||
InitialDelaySeconds: int32(probe.InitialDelaySecond),
|
||||
TimeoutSeconds: int32(probe.TimeoutSecond),
|
||||
PeriodSeconds: int32(probe.PeriodSecond),
|
||||
}
|
||||
if probe.Scheme == "tcp" {
|
||||
tcp := &corev1.TCPSocketAction{
|
||||
Port: intstr.FromInt(probe.Port),
|
||||
}
|
||||
p.TCPSocket = tcp
|
||||
return p
|
||||
} else if probe.Scheme == "http" {
|
||||
action := corev1.HTTPGetAction{Path: probe.Path, Port: intstr.FromInt(probe.Port)}
|
||||
if probe.HTTPHeader != "" {
|
||||
hds := strings.Split(probe.HTTPHeader, ",")
|
||||
var headers []corev1.HTTPHeader
|
||||
for _, hd := range hds {
|
||||
kv := strings.Split(hd, "=")
|
||||
if len(kv) == 1 {
|
||||
header := corev1.HTTPHeader{
|
||||
Name: kv[0],
|
||||
Value: "",
|
||||
}
|
||||
headers = append(headers, header)
|
||||
} else if len(kv) == 2 {
|
||||
header := corev1.HTTPHeader{
|
||||
Name: kv[0],
|
||||
Value: kv[1],
|
||||
}
|
||||
headers = append(headers, header)
|
||||
}
|
||||
}
|
||||
action.HTTPHeaders = headers
|
||||
}
|
||||
p.HTTPGet = &action
|
||||
return p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Error("query probe error:", err.Error())
|
||||
}
|
||||
//TODO:create default probe
|
||||
return nil
|
||||
}
|
||||
|
||||
func createNodeSelector(as *v1.AppService, dbmanager db.Manager) map[string]string {
|
||||
selector := make(map[string]string)
|
||||
labels, err := dbmanager.TenantServiceLabelDao().GetTenantServiceNodeSelectorLabel(as.ServiceID)
|
||||
if err == nil && labels != nil && len(labels) > 0 {
|
||||
for _, l := range labels {
|
||||
selector[l.LabelValue] = dbmodel.LabelKeyNodeSelector
|
||||
}
|
||||
}
|
||||
return selector
|
||||
}
|
||||
func createAffinity(as *v1.AppService, dbmanager db.Manager) *corev1.Affinity {
|
||||
var affinity corev1.Affinity
|
||||
labels, err := dbmanager.TenantServiceLabelDao().GetTenantServiceAffinityLabel(as.ServiceID)
|
||||
if err == nil && labels != nil && len(labels) > 0 {
|
||||
nsr := make([]corev1.NodeSelectorRequirement, 0)
|
||||
podAffinity := make([]corev1.PodAffinityTerm, 0)
|
||||
podAntAffinity := make([]corev1.PodAffinityTerm, 0)
|
||||
for _, l := range labels {
|
||||
if l.LabelKey == dbmodel.LabelKeyNodeAffinity {
|
||||
nsr = append(nsr, corev1.NodeSelectorRequirement{
|
||||
Key: l.LabelKey,
|
||||
Operator: corev1.NodeSelectorOpIn,
|
||||
Values: []string{l.LabelValue},
|
||||
})
|
||||
}
|
||||
if l.LabelKey == dbmodel.LabelKeyServiceAffinity {
|
||||
podAffinity = append(podAffinity, corev1.PodAffinityTerm{
|
||||
LabelSelector: metav1.SetAsLabelSelector(map[string]string{
|
||||
"name": l.LabelValue,
|
||||
}),
|
||||
})
|
||||
}
|
||||
if l.LabelKey == dbmodel.LabelKeyServiceAntyAffinity {
|
||||
podAntAffinity = append(
|
||||
podAntAffinity, corev1.PodAffinityTerm{
|
||||
LabelSelector: metav1.SetAsLabelSelector(map[string]string{
|
||||
"name": l.LabelValue,
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
affinity.NodeAffinity = &corev1.NodeAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{
|
||||
NodeSelectorTerms: []corev1.NodeSelectorTerm{
|
||||
corev1.NodeSelectorTerm{MatchExpressions: nsr},
|
||||
},
|
||||
},
|
||||
}
|
||||
affinity.PodAffinity = &corev1.PodAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: podAffinity,
|
||||
}
|
||||
affinity.PodAntiAffinity = &corev1.PodAntiAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: podAntAffinity,
|
||||
}
|
||||
}
|
||||
return &affinity
|
||||
}
|
||||
|
||||
func setFeature(podt *corev1.PodTemplateSpec) {
|
||||
for _, env := range podt.Spec.Containers[0].Env {
|
||||
switch strings.ToLower(env.Name) {
|
||||
case "annotations_hostname":
|
||||
podt.Spec.Hostname = env.Value
|
||||
case "annotations_shcedulername":
|
||||
podt.Spec.SchedulerName = env.Value
|
||||
case "annotations_nodename":
|
||||
podt.Spec.NodeName = env.Value
|
||||
}
|
||||
}
|
||||
}
|
30
worker/appm/conversion/version_test.go
Normal file
30
worker/appm/conversion/version_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
v1 "github.com/goodrain/rainbond/worker/appm/types/v1"
|
||||
)
|
||||
|
||||
func TestTenantServiceVersion(t *testing.T) {
|
||||
var as v1.AppService
|
||||
TenantServiceVersion(&as, nil)
|
||||
}
|
28
worker/appm/storageclass/storeage_class.go
Normal file
28
worker/appm/storageclass/storeage_class.go
Normal file
@ -0,0 +1,28 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package storageclass
|
||||
|
||||
//TODO:
|
||||
|
||||
// kind: StorageClass
|
||||
// apiVersion: storage.k8s.io/v1
|
||||
// metadata:
|
||||
// name: local-storage
|
||||
// provisioner: kubernetes.io/no-provisioner
|
||||
// volumeBindingMode: WaitForFirstConsumer
|
35
worker/appm/store/informer.go
Normal file
35
worker/appm/store/informer.go
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
//Informer kube-api client cache
|
||||
type Informer struct {
|
||||
Ingress cache.SharedIndexInformer
|
||||
Service cache.SharedIndexInformer
|
||||
Endpoint cache.SharedIndexInformer
|
||||
Secret cache.SharedIndexInformer
|
||||
StatefulSet cache.SharedIndexInformer
|
||||
Deployment cache.SharedIndexInformer
|
||||
Pod cache.SharedIndexInformer
|
||||
ConfigMap cache.SharedIndexInformer
|
||||
}
|
37
worker/appm/store/lister.go
Normal file
37
worker/appm/store/lister.go
Normal file
@ -0,0 +1,37 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
appsv1 "k8s.io/client-go/listers/apps/v1"
|
||||
corev1 "k8s.io/client-go/listers/core/v1"
|
||||
v1beta1 "k8s.io/client-go/listers/extensions/v1beta1"
|
||||
)
|
||||
|
||||
//Lister kube-api client cache
|
||||
type Lister struct {
|
||||
Ingress v1beta1.IngressLister
|
||||
Service corev1.ServiceLister
|
||||
Endpoint corev1.EndpointsLister
|
||||
Secret corev1.SecretLister
|
||||
StatefulSet appsv1.StatefulSetLister
|
||||
Deployment appsv1.DeploymentLister
|
||||
Pod corev1.PodLister
|
||||
ConfigMap corev1.ConfigMapLister
|
||||
}
|
94
worker/appm/store/store.go
Normal file
94
worker/appm/store/store.go
Normal file
@ -0,0 +1,94 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
//Storer app runtime store interface
|
||||
type Storer interface {
|
||||
}
|
||||
|
||||
//appRuntimeStore app runtime store
|
||||
//cache all kubernetes object and appservice
|
||||
type appRuntimeStore struct {
|
||||
informers *Informer
|
||||
listers *Lister
|
||||
}
|
||||
|
||||
//NewStore new app runtime store
|
||||
func NewStore(client kubernetes.Interface) Storer {
|
||||
store := &appRuntimeStore{
|
||||
informers: &Informer{},
|
||||
}
|
||||
// create informers factory, enable and assign required informers
|
||||
infFactory := informers.NewFilteredSharedInformerFactory(client, time.Second, corev1.NamespaceAll,
|
||||
func(options *metav1.ListOptions) {
|
||||
options.LabelSelector = "creater=Rainbond"
|
||||
})
|
||||
store.informers.Deployment = infFactory.Apps().V1().Deployments().Informer()
|
||||
store.listers.Deployment = infFactory.Apps().V1().Deployments().Lister()
|
||||
|
||||
store.informers.StatefulSet = infFactory.Apps().V1().StatefulSets().Informer()
|
||||
store.listers.StatefulSet = infFactory.Apps().V1().StatefulSets().Lister()
|
||||
|
||||
store.informers.Service = infFactory.Core().V1().Services().Informer()
|
||||
store.listers.Service = infFactory.Core().V1().Services().Lister()
|
||||
|
||||
store.informers.Endpoint = infFactory.Core().V1().Endpoints().Informer()
|
||||
store.listers.Endpoint = infFactory.Core().V1().Endpoints().Lister()
|
||||
|
||||
store.informers.Pod = infFactory.Core().V1().Pods().Informer()
|
||||
store.listers.Pod = infFactory.Core().V1().Pods().Lister()
|
||||
|
||||
store.informers.Secret = infFactory.Core().V1().Secrets().Informer()
|
||||
store.listers.Secret = infFactory.Core().V1().Secrets().Lister()
|
||||
|
||||
store.informers.ConfigMap = infFactory.Core().V1().ConfigMaps().Informer()
|
||||
store.listers.ConfigMap = infFactory.Core().V1().ConfigMaps().Lister()
|
||||
|
||||
store.informers.Ingress = infFactory.Extensions().V1beta1().Ingresses().Informer()
|
||||
store.listers.Ingress = infFactory.Extensions().V1beta1().Ingresses().Lister()
|
||||
|
||||
store.informers.Deployment.AddEventHandler(store)
|
||||
store.informers.StatefulSet.AddEventHandler(store)
|
||||
store.informers.Pod.AddEventHandler(store)
|
||||
store.informers.Secret.AddEventHandler(store)
|
||||
store.informers.Service.AddEventHandler(store)
|
||||
store.informers.Endpoint.AddEventHandler(store)
|
||||
store.informers.Ingress.AddEventHandler(store)
|
||||
store.informers.ConfigMap.AddEventHandler(store)
|
||||
return store
|
||||
}
|
||||
|
||||
func (a *appRuntimeStore) OnAdd(obj interface{}) {
|
||||
|
||||
}
|
||||
func (a *appRuntimeStore) OnUpdate(oldObj, newObj interface{}) {
|
||||
|
||||
}
|
||||
func (a *appRuntimeStore) OnDelete(obj interface{}) {
|
||||
|
||||
}
|
@ -27,10 +27,31 @@ import (
|
||||
//AppServiceStatus the status of service, calculate in real time from kubernetes
|
||||
type AppServiceStatus string
|
||||
|
||||
//AppServiceType the deploy type of service.
|
||||
type AppServiceType string
|
||||
|
||||
//TypeStatefulSet statefulset
|
||||
var TypeStatefulSet AppServiceType = "statefulset"
|
||||
|
||||
//TypeDeployment deployment
|
||||
var TypeDeployment AppServiceType = "deployment"
|
||||
|
||||
//TypeReplicationController rc
|
||||
var TypeReplicationController AppServiceType = "replicationcontroller"
|
||||
|
||||
//AppServiceBase app service base info
|
||||
type AppServiceBase struct {
|
||||
TenantID string
|
||||
ServiceID string
|
||||
TenantID string
|
||||
TenantName string
|
||||
ServiceID string
|
||||
ServiceAlias string
|
||||
ServiceType AppServiceType
|
||||
DeployVersion string
|
||||
ContainerCPU int
|
||||
ContainerMemory int
|
||||
Replicas int
|
||||
NeedProxy bool
|
||||
CreaterID string
|
||||
}
|
||||
|
||||
//AppService a service of rainbond app state in kubernetes
|
||||
@ -49,3 +70,91 @@ type AppService struct {
|
||||
func (a *AppService) GetDeployment() *v1.Deployment {
|
||||
return a.deployment
|
||||
}
|
||||
|
||||
//SetDeployment set kubernetes deployment model
|
||||
func (a *AppService) SetDeployment(d *v1.Deployment) {
|
||||
a.deployment = d
|
||||
}
|
||||
|
||||
//GetStatefulSet get kubernetes statefulset model
|
||||
func (a *AppService) GetStatefulSet() *v1.StatefulSet {
|
||||
return a.statefulset
|
||||
}
|
||||
|
||||
//SetStatefulSet set kubernetes statefulset model
|
||||
func (a *AppService) SetStatefulSet(d *v1.StatefulSet) {
|
||||
a.statefulset = d
|
||||
}
|
||||
|
||||
//SetConfigMap set kubernetes configmap model
|
||||
func (a *AppService) SetConfigMap(d *corev1.ConfigMap) {
|
||||
if len(a.configMaps) > 0 {
|
||||
for i, configMap := range a.configMaps {
|
||||
if configMap.GetName() == d.GetName() {
|
||||
a.configMaps[i] = d
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
a.configMaps = append(a.configMaps, d)
|
||||
}
|
||||
|
||||
//SetService set kubernetes service model
|
||||
func (a *AppService) SetService(d *corev1.Service) {
|
||||
if len(a.services) > 0 {
|
||||
for i, service := range a.services {
|
||||
if service.GetName() == d.GetName() {
|
||||
a.services[i] = d
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
a.services = append(a.services, d)
|
||||
}
|
||||
|
||||
//SetIngress set kubernetes ingress model
|
||||
func (a *AppService) SetIngress(d *extensions.Ingress) {
|
||||
if len(a.ingresses) > 0 {
|
||||
for i, ingress := range a.ingresses {
|
||||
if ingress.GetName() == d.GetName() {
|
||||
a.ingresses[i] = d
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
a.ingresses = append(a.ingresses, d)
|
||||
}
|
||||
|
||||
//SetEndpoint set kubernetes endpoint model
|
||||
func (a *AppService) SetEndpoint(d *corev1.Endpoints) {
|
||||
if len(a.endpoints) > 0 {
|
||||
for i, endpoint := range a.endpoints {
|
||||
if endpoint.GetName() == d.GetName() {
|
||||
a.endpoints[i] = d
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
a.endpoints = append(a.endpoints, d)
|
||||
}
|
||||
|
||||
//SetPodTemplate set pod template spec
|
||||
func (a *AppService) SetPodTemplate(d corev1.PodTemplateSpec) {
|
||||
if a.statefulset != nil {
|
||||
a.statefulset.Spec.Template = d
|
||||
}
|
||||
if a.deployment != nil {
|
||||
a.deployment.Spec.Template = d
|
||||
}
|
||||
}
|
||||
|
||||
//GetPodTemplate get pod template
|
||||
func (a *AppService) GetPodTemplate() *corev1.PodTemplateSpec {
|
||||
if a.statefulset != nil {
|
||||
return &a.statefulset.Spec.Template
|
||||
}
|
||||
if a.deployment != nil {
|
||||
return &a.deployment.Spec.Template
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user