mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-29 18:27:58 +08:00
feat: Plugins add storage
This commit is contained in:
parent
8ec269f393
commit
a09edcba31
@ -93,6 +93,14 @@ type ResourceSpec struct {
|
||||
BaseNormal BaseEnv `json:"base_normal"`
|
||||
}
|
||||
|
||||
//PluginStorage 插件存储结构体
|
||||
type PluginStorage struct {
|
||||
VolumeName string `json:"volume_name"`
|
||||
VolumePath string `json:"volume_path"`
|
||||
FileContent string `json:"file_content"`
|
||||
AttrType string `json:"attr_type"`
|
||||
}
|
||||
|
||||
//BasePort base of current app ports
|
||||
type BasePort struct {
|
||||
ServiceAlias string `json:"service_alias"`
|
||||
|
@ -440,6 +440,9 @@ var ShareFileVolumeType VolumeType = "share-file"
|
||||
//LocalVolumeType 本地文件存储
|
||||
var LocalVolumeType VolumeType = "local"
|
||||
|
||||
//PluginStorageType 插件存储
|
||||
var PluginStorageType VolumeType = "plugin-storage"
|
||||
|
||||
//MemoryFSVolumeType 内存文件存储
|
||||
var MemoryFSVolumeType VolumeType = "memoryfs"
|
||||
|
||||
|
@ -32,7 +32,7 @@ var translationMetadata = map[string]string{
|
||||
"save image to hub error": "保存镜像到仓库失败",
|
||||
"Please try again or contact customer service": "后端服务开小差,请重试或联系客服",
|
||||
"unzip metadata file error": "解压数据失败",
|
||||
"start service error": "启动服务失败,请检查集服务信息或查看日志",
|
||||
"start service error": "启动服务失败,请检查集群服务信息或查看日志",
|
||||
"start service timeout": "启动服务超时,建议观察服务实例运行状态",
|
||||
"stop service error": "停止服务失败,建议观察服务实例运行状态",
|
||||
"stop service timeout": "停止服务超时,建议观察服务实例运行状态",
|
||||
|
@ -21,6 +21,7 @@ package conversion
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/goodrain/rainbond/worker/appm/volume"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -181,6 +182,31 @@ func conversionServicePlugin(as *typesv1.AppService, dbmanager db.Manager) ([]v1
|
||||
}
|
||||
//create plugin config to configmap
|
||||
for i := range appPlugins {
|
||||
config, err := dbmanager.TenantPluginVersionConfigDao().GetPluginConfig(appPlugins[i].ServiceID,
|
||||
appPlugins[i].PluginID)
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logrus.Errorf("get service plugin config from db failure %s", err.Error())
|
||||
}
|
||||
if config != nil {
|
||||
configStr := config.ConfigStr
|
||||
var oldConfig api_model.ResourceSpec
|
||||
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
|
||||
for key, plugin := range oldConfig.BaseNormal.Options {
|
||||
var pluginStorage api_model.PluginStorage
|
||||
jsonValue, ok := plugin.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if err := json.Unmarshal([]byte(jsonValue), &pluginStorage); err != nil {
|
||||
continue
|
||||
}
|
||||
if pluginStorage.VolumeName != "" || pluginStorage.VolumePath != "" {
|
||||
IsContainMount(&mainContainer.VolumeMounts, as, pluginStorage, config.PluginID)
|
||||
delete(oldConfig.BaseNormal.Options, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ApplyPluginConfig(as, appPlugins[i], dbmanager, inboundPluginConfig)
|
||||
}
|
||||
//if need proxy but not install net plugin
|
||||
@ -199,6 +225,11 @@ func conversionServicePlugin(as *typesv1.AppService, dbmanager db.Manager) ([]v1
|
||||
initContainers = append(initContainers, bootSequence)
|
||||
}
|
||||
as.BootSeqContainer = &bootSequence
|
||||
if len(as.GetPodTemplate().Spec.Containers) != 0 {
|
||||
pluginMountVolume(initContainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
|
||||
pluginMountVolume(precontainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
|
||||
pluginMountVolume(postcontainers, as.GetPodTemplate().Spec.Containers[0].VolumeMounts)
|
||||
}
|
||||
return initContainers, precontainers, postcontainers, nil
|
||||
}
|
||||
|
||||
@ -280,7 +311,6 @@ func ApplyPluginConfig(as *typesv1.AppService, servicePluginRelation *model.Tena
|
||||
}
|
||||
if config != nil {
|
||||
configStr := config.ConfigStr
|
||||
//if have inbound plugin,will Propagate its listner port to other plug-ins
|
||||
if inboundPluginConfig != nil {
|
||||
var oldConfig api_model.ResourceSpec
|
||||
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
|
||||
@ -470,3 +500,34 @@ func xdsHostIPEnv(xdsHost string) corev1.EnvVar {
|
||||
}
|
||||
return v1.EnvVar{Name: "XDS_HOST_IP", Value: xdsHost}
|
||||
}
|
||||
|
||||
//IsContainMount 判断存储路径是否冲突,以及进一步实现创建存储或配置文件
|
||||
func IsContainMount(volumeMounts *[]v1.VolumeMount, as *typesv1.AppService, plugin api_model.PluginStorage, pluginID string) bool {
|
||||
|
||||
for _, mountValue := range *volumeMounts {
|
||||
if mountValue.MountPath == plugin.VolumePath {
|
||||
return false
|
||||
}
|
||||
}
|
||||
volumeMount := v1.VolumeMount{Name: plugin.VolumeName, MountPath: plugin.VolumePath}
|
||||
*volumeMounts = append(*volumeMounts, volumeMount)
|
||||
var define = &volume.Define{}
|
||||
v := new(volume.PluginStorageVolume)
|
||||
v.Plugin = plugin
|
||||
v.AS = as
|
||||
v.PluginID = pluginID
|
||||
if err := v.CreateVolume(define); err != nil {
|
||||
return false
|
||||
}
|
||||
as.GetPodTemplate().Spec.Volumes = append(as.GetPodTemplate().Spec.Volumes, define.GetVolumes()...)
|
||||
if len(as.GetPodTemplate().Spec.Containers) != 0 {
|
||||
as.GetPodTemplate().Spec.Containers[0].VolumeMounts = append(as.GetPodTemplate().Spec.Containers[0].VolumeMounts, define.GetVolumeMounts()...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func pluginMountVolume(containers []v1.Container, volumeMount []v1.VolumeMount) {
|
||||
for i := range containers {
|
||||
containers[i].VolumeMounts = volumeMount
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +172,6 @@ func getMainContainer(as *v1.AppService, version *dbmodel.VersionInfo, dv *volum
|
||||
logrus.Infof("service id: %s; enable privileged.", as.ServiceID)
|
||||
c.SecurityContext = &corev1.SecurityContext{Privileged: util.Bool(true)}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
65
worker/appm/volume/plugin-storage.go
Normal file
65
worker/appm/volume/plugin-storage.go
Normal file
@ -0,0 +1,65 @@
|
||||
package volume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
api_model "github.com/goodrain/rainbond/api/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"
|
||||
"path"
|
||||
)
|
||||
|
||||
//PluginStorageVolume 插件新增存储
|
||||
type PluginStorageVolume struct {
|
||||
Plugin api_model.PluginStorage
|
||||
Base
|
||||
PluginID string
|
||||
AS *v1.AppService
|
||||
}
|
||||
|
||||
//CreateVolume 创建插件存储或配置文件
|
||||
func (v *PluginStorageVolume) CreateVolume(define *Define) error {
|
||||
v.as = v.AS
|
||||
if v.Plugin.AttrType == "config-file" {
|
||||
cmap := &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: util.NewUUID(),
|
||||
Namespace: v.as.GetNamespace(),
|
||||
Labels: v.as.GetCommonLabels(),
|
||||
},
|
||||
Data: make(map[string]string),
|
||||
}
|
||||
cmap.Data[path.Base(v.Plugin.VolumePath)] = util.ParseVariable(v.Plugin.FileContent, map[string]string{})
|
||||
v.as.SetConfigMap(cmap)
|
||||
mode := int32(777)
|
||||
define.SetVolumeCMap(cmap, path.Base(v.Plugin.VolumePath), v.Plugin.VolumePath, false, &mode)
|
||||
return nil
|
||||
} else if v.Plugin.AttrType == "storage" {
|
||||
volumeMountName := fmt.Sprintf("plugin-%v-%v", v.PluginID, v.Plugin.VolumeName)
|
||||
volumeMountPath := v.Plugin.VolumePath
|
||||
volumeReadOnly := false
|
||||
var vm *corev1.VolumeMount
|
||||
annotations := map[string]string{"volume_name": v.Plugin.VolumeName}
|
||||
labels := v.as.GetCommonLabels(map[string]string{"volume_name": volumeMountName, "VolumeName": v.Plugin.VolumeName, "pluginID": v.PluginID})
|
||||
claim := newVolumeClaim(volumeMountName, volumeMountPath, "RWX", v1.RainbondStatefuleShareStorageClass, 0, labels, annotations)
|
||||
v.as.SetClaim(claim)
|
||||
v.as.SetClaimManually(claim)
|
||||
vo := corev1.Volume{Name: volumeMountName}
|
||||
vo.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: claim.GetName(), ReadOnly: volumeReadOnly}
|
||||
define.volumes = append(define.volumes, vo)
|
||||
vm = &corev1.VolumeMount{
|
||||
Name: volumeMountName,
|
||||
MountPath: volumeMountPath,
|
||||
ReadOnly: volumeReadOnly,
|
||||
}
|
||||
define.volumeMounts = append(define.volumeMounts, *vm)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateDependVolume create depend volume
|
||||
func (v *PluginStorageVolume) CreateDependVolume(define *Define) error {
|
||||
return nil
|
||||
}
|
@ -71,7 +71,6 @@ func (v *ShareFileVolume) CreateVolume(define *Define) error {
|
||||
claim := newVolumeClaim(volumeMountName, volumeMountPath, v.svm.AccessMode, v1.RainbondStatefuleShareStorageClass, v.svm.VolumeCapacity, labels, annotations)
|
||||
v.as.SetClaim(claim)
|
||||
v.as.SetClaimManually(claim)
|
||||
|
||||
vo := corev1.Volume{Name: volumeMountName}
|
||||
vo.PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ClaimName: claim.GetName(), ReadOnly: volumeReadOnly}
|
||||
define.volumes = append(define.volumes, vo)
|
||||
|
@ -72,6 +72,8 @@ func NewVolumeManager(as *v1.AppService,
|
||||
v = new(MemoryFSVolume)
|
||||
case dbmodel.LocalVolumeType.String():
|
||||
v = new(LocalVolume)
|
||||
case dbmodel.PluginStorageType.String():
|
||||
v = new(PluginStorageVolume)
|
||||
default:
|
||||
logrus.Warnf("other volume type[%s]", volumeType)
|
||||
v = new(OtherVolume)
|
||||
|
@ -19,7 +19,10 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
"github.com/jinzhu/gorm"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
@ -68,7 +71,7 @@ func (p *rainbondssscProvisioner) Provision(options controller.VolumeOptions) (*
|
||||
_, stateless := options.PVC.Labels["stateless"]
|
||||
// v5.0.4 Previous versions
|
||||
hostpath := path.Join(p.pvDir, "tenant", tenantID, "service", serviceID, options.PVC.Name)
|
||||
|
||||
pluginID, ok := options.PVC.Labels["pluginID"]
|
||||
// after v5.0.4,change host path
|
||||
// Directory path has nothing to do with volume ID
|
||||
// Directory path bound to volume mount path
|
||||
@ -85,6 +88,30 @@ func (p *rainbondssscProvisioner) Provision(options controller.VolumeOptions) (*
|
||||
if !stateless {
|
||||
hostpath = path.Join(volume.HostPath, podName)
|
||||
}
|
||||
} else if ok {
|
||||
config, err := db.GetManager().TenantPluginVersionConfigDao().GetPluginConfig(serviceID, pluginID)
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
logrus.Errorf("get service plugin config from db failure %s", err.Error())
|
||||
}
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("can not parse volume id")
|
||||
}
|
||||
configStr := config.ConfigStr
|
||||
var oldConfig api_model.ResourceSpec
|
||||
if err := json.Unmarshal([]byte(configStr), &oldConfig); err == nil {
|
||||
for _, plugin := range oldConfig.BaseNormal.Options {
|
||||
var pluginStorage api_model.PluginStorage
|
||||
jsonValue, ok := plugin.(string)
|
||||
if ok {
|
||||
if err := json.Unmarshal([]byte(jsonValue), &pluginStorage); err == nil {
|
||||
if pluginStorage.VolumeName == options.PVC.Labels["VolumeName"] {
|
||||
hostpath = path.Join("/grdata/tenant/", tenantID, "service", serviceID, pluginStorage.VolumePath, podName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("can not parse volume id")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user