diff --git a/db/dao/dao.go b/db/dao/dao.go index 7c2d143e7..654b4cc7a 100644 --- a/db/dao/dao.go +++ b/db/dao/dao.go @@ -221,7 +221,7 @@ type TenantServiceVolumeDao interface { type TenantServiceConfigFileDao interface { Dao - ListByVolumeID(volumeName string) ([]*model.TenantServiceConfigFile, error) + GetByVolumeName(volumeName string) (*model.TenantServiceConfigFile, error) DelByVolumeID(volumeName string) error } diff --git a/db/mysql/dao/tenants.go b/db/mysql/dao/tenants.go index e833bc6e7..d3b44eeed 100644 --- a/db/mysql/dao/tenants.go +++ b/db/mysql/dao/tenants.go @@ -969,14 +969,14 @@ func (t *TenantServiceConfigFileDaoImpl) UpdateModel(mo model.Interface) error { Update(configFile).Error } -// ListByVolumeID lists configFiles by volumeID -func (t *TenantServiceConfigFileDaoImpl) ListByVolumeID(volumeName string) ([]*model.TenantServiceConfigFile, error) { - var res []*model.TenantServiceConfigFile +// GetByVolumeName get config file by volume name +func (t *TenantServiceConfigFileDaoImpl) GetByVolumeName(volumeName string) (*model.TenantServiceConfigFile, error) { + var res model.TenantServiceConfigFile if err := t.DB.Where("volume_name = ?", volumeName).Find(&res).Error; err != nil { return nil, err } - return res, nil + return &res, nil } // DelByVolumeID deletes config files according to volume id diff --git a/db/volume_db_test.go b/db/volume_db_test.go index 758270c96..48d1e36cc 100644 --- a/db/volume_db_test.go +++ b/db/volume_db_test.go @@ -19,6 +19,7 @@ package db import ( + "github.com/jinzhu/gorm" dbconfig "github.com/goodrain/rainbond/db/config" "github.com/goodrain/rainbond/db/model" "github.com/goodrain/rainbond/util" @@ -35,32 +36,31 @@ func TestManager_TenantServiceConfigFileDaoImpl_UpdateModel(t *testing.T) { tx.Delete(model.TenantServiceConfigFile{}) tx.Commit() - vid := util.NewUUID() + vname := util.NewUUID() cf := &model.TenantServiceConfigFile{ UUID: util.NewUUID(), - VolumeName: vid, - Filename: "dummy_filename", + VolumeName: vname, FileContent: "dummy file content", } if err := GetManager().TenantServiceConfigFileDao().AddModel(cf); err != nil { t.Fatal(err) } - cfs, err := GetManager().TenantServiceConfigFileDao().ListByVolumeID(vid) + cf, err := GetManager().TenantServiceConfigFileDao().GetByVolumeName(vname) if err != nil { t.Fatal(err) } - if cfs == nil || len(cfs) != 1 { - t.Errorf("Expected one config file, but returned %v", cfs) + if cf == nil { + t.Errorf("Expected one config file, but returned %v", cf) } - if err := GetManager().TenantServiceConfigFileDao().DelByVolumeID(vid); err != nil { + if err := GetManager().TenantServiceConfigFileDao().DelByVolumeID(vname); err != nil { t.Fatal(err) } - cfs, err = GetManager().TenantServiceConfigFileDao().ListByVolumeID(vid) - if err != nil { + cf, err = GetManager().TenantServiceConfigFileDao().GetByVolumeName(vname) + if err != nil && err != gorm.ErrRecordNotFound { t.Fatal(err) } - if len(cfs) != 0 { - t.Errorf("Expected nothing for cfs, but returned %v", cfs) + if cf != nil { + t.Errorf("Expected nothing for cfs, but returned %v", cf) } } diff --git a/worker/appm/conversion/version.go b/worker/appm/conversion/version.go index 097df7826..b90e4e716 100644 --- a/worker/appm/conversion/version.go +++ b/worker/appm/conversion/version.go @@ -22,7 +22,6 @@ import ( "fmt" "os" "path" - "path/filepath" "strconv" "strings" @@ -324,7 +323,18 @@ func createVolumes(as *v1.AppService, version *dbmodel.VersionInfo, dbmanager db if err != nil { return nil, err } - cmmap := make(map[string]*corev1.ConfigMap) + + // environment variables + configs := make(map[string]string) + envs, err := createEnv(as, dbmanager) + if err != nil { + logrus.Warningf("error creating environment variables: %v", err) + } else { + for _, env := range *envs { + configs[env.Name] = env.Value + } + } + if vs != nil && len(vs) > 0 { for i := range vs { v := vs[i] @@ -336,60 +346,40 @@ func createVolumes(as *v1.AppService, version *dbmodel.VersionInfo, dbmanager db os.Chmod(v.HostPath, 0777) } // create a configMap which will be mounted as a volume - name := fmt.Sprintf("manual%d", v.ID) - mountPath := v.VolumePath + var cmap *corev1.ConfigMap if v.VolumeType == dbmodel.ConfigFileVolumeType.String() { - cfs, err := dbmanager.TenantServiceConfigFileDao().ListByVolumeID(v.VolumeName) + cf, err := dbmanager.TenantServiceConfigFileDao().GetByVolumeName(v.VolumeName) if err != nil { - logrus.Errorf("error listing config files by volume name(%s): %v", v.VolumeName, err) - return nil, fmt.Errorf("error listing config files by volume name(%s): %v", v.VolumeName, err) + logrus.Errorf("error getting config file by volume name(%s): %v", v.VolumeName, err) + return nil, fmt.Errorf("error getting config file by volume name(%s): %v", v.VolumeName, err) } - if cfs == nil || len(cfs) == 0 { - logrus.Errorf("there is no config files according to volume name(%s)", v.VolumeName) - return nil, fmt.Errorf("there is no config files according to volume name(%s)", v.VolumeName) - } - configs := make(map[string]string) - envs, err := createEnv(as, dbmanager) - if err != nil { - logrus.Warningf("error creating environment variables: %v", err) - } else { - for _, env := range *envs { - configs[env.Name] = env.Value - } - } - for _, cf := range cfs { - mountPath = path.Dir(v.VolumePath) - name = fmt.Sprintf("manual%s%s", as.ServiceID, mountPath) - name = strings.Replace(name, "/", "slash", -1) - cmap, ok := cmmap[name] - if !ok { - cmap = &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: as.TenantID, - Labels: as.GetCommonLabels(), - }, - Data: make(map[string]string), - } - cmmap[name] = cmap - } - cmap.Data[filepath.Base(v.VolumePath)] = util.ParseVariable(cf.FileContent, configs) + name := fmt.Sprintf("manual%s%s", as.ServiceID, v.VolumePath) + name = strings.Replace(name, "/", "slash", -1) + name = strings.Replace(name, ".", "dot", -1) + cmap = &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: as.TenantID, + Labels: as.GetCommonLabels(), + }, + Data: make(map[string]string), } + cmap.Data[path.Base(v.VolumePath)] = util.ParseVariable(cf.FileContent, configs) + as.SetConfigMap(cmap) + vd.SetVolumeCMap(cmap, path.Base(v.VolumePath), v.VolumePath, v.IsReadOnly) + continue // pass codes below } if as.GetStatefulSet() != nil { - vd.SetPV(dbmodel.VolumeType(v.VolumeType), name, mountPath, v.IsReadOnly) + vd.SetPV(dbmodel.VolumeType(v.VolumeType), fmt.Sprintf("manual%d", v.ID), v.VolumePath, v.IsReadOnly) } else { hostPath := v.HostPath if as.IsWindowsService { hostPath = RewriteHostPathInWindows(hostPath) } - vd.SetVolume(dbmodel.VolumeType(v.VolumeType), name, mountPath, hostPath, corev1.HostPathDirectoryOrCreate, v.IsReadOnly) + vd.SetVolume(dbmodel.VolumeType(v.VolumeType), fmt.Sprintf("manual%d", v.ID), v.VolumePath, hostPath, corev1.HostPathDirectoryOrCreate, v.IsReadOnly) } } } - for _, cmap := range cmmap { - as.SetConfigMap(cmap) - } //handle Shared storage logrus.Infof("begin handling Shared storage") tsmr, err := dbmanager.TenantServiceMountRelationDao().GetTenantServiceMountRelationsByService(version.ServiceID) @@ -413,16 +403,29 @@ func createVolumes(as *v1.AppService, version *dbmodel.VersionInfo, dbmanager db case dbmodel.ConfigFileVolumeType.String(): tsv, err := dbmanager.TenantServiceVolumeDao().GetVolumeByServiceIDAndName(t.DependServiceID, t.VolumeName) if err != nil { - return nil, fmt.Errorf("error getting TenantServiceVolume according to serviceID(%s) and volumeName(%s): %v", - t.DependServiceID, t.VolumeName, err) + return nil, fmt.Errorf("error getting TenantServiceVolume according to serviceID(%s) and volumeName(%s): %v", + t.DependServiceID, t.VolumeName, err) } - name := fmt.Sprintf("manual%s%s", t.DependServiceID, path.Dir(tsv.VolumePath)) + cf, err := dbmanager.TenantServiceConfigFileDao().GetByVolumeName(t.VolumeName) + if err != nil { + return nil, fmt.Errorf("error getting TenantServiceConfigFileDao according to volumeName(%s): %v", t.VolumeName, err) + } + + name := fmt.Sprintf("manual%s%s", as.ServiceID, t.VolumePath) name = strings.Replace(name, "/", "slash", -1) - if as.GetStatefulSet() != nil { - vd.SetPV(dbmodel.ConfigFileVolumeType, name, t.VolumePath, tsv.IsReadOnly) - } else { - vd.SetVolume(dbmodel.ConfigFileVolumeType, name, t.VolumePath, "", corev1.HostPathDirectoryOrCreate, tsv.IsReadOnly) + name = strings.Replace(name, ".", "dot", -1) + cmap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: as.TenantID, + Labels: as.GetCommonLabels(), + }, + Data: make(map[string]string), } + cmap.Data[path.Base(t.VolumePath)] = util.ParseVariable(cf.FileContent, configs) + as.SetConfigMap(cmap) + + vd.SetVolumeCMap(cmap, path.Base(t.VolumePath), t.VolumePath, tsv.IsReadOnly) } } } @@ -470,9 +473,11 @@ type volumeDefine struct { func (v *volumeDefine) GetVolumes() []corev1.Volume { return v.volumes } + func (v *volumeDefine) GetVolumeMounts() []corev1.VolumeMount { return v.volumeMounts } + func (v *volumeDefine) SetPV(VolumeType dbmodel.VolumeType, name, mountPath string, readOnly bool) { logrus.Info("Set persistence volume for statefuleset.") switch VolumeType { @@ -547,28 +552,9 @@ func (v *volumeDefine) SetPV(VolumeType dbmodel.VolumeType, name, mountPath stri ReadOnly: readOnly, }) } - case dbmodel.ConfigFileVolumeType: - logrus.Infof("VolumeType is config-file") - if statefulset := v.as.GetStatefulSet(); statefulset != nil { - cv := corev1.Volume{ - Name: name, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: name, - }, - }, - }, - } - v.volumes = append(v.volumes, cv) - v.volumeMounts = append(v.volumeMounts, corev1.VolumeMount{ - Name: name, - MountPath: mountPath, - ReadOnly: readOnly, - }) - } } } + func (v *volumeDefine) SetVolume(VolumeType dbmodel.VolumeType, name, mountPath, hostPath string, hostPathType corev1.HostPathType, readOnly bool) { logrus.Info("Set volume for deployment.") for _, m := range v.volumeMounts { @@ -617,27 +603,38 @@ func (v *volumeDefine) SetVolume(VolumeType dbmodel.VolumeType, name, mountPath, case dbmodel.LocalVolumeType: //no support return - case dbmodel.ConfigFileVolumeType: - logrus.Infof("VolumeType is config-file") - vo := corev1.Volume{ - Name: name, - } - vo.ConfigMap = &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: name, - }, - } - v.volumes = append(v.volumes, vo) - vm := corev1.VolumeMount{ - MountPath: mountPath, - Name: name, - ReadOnly: readOnly, - SubPath: "", - } - v.volumeMounts = append(v.volumeMounts, vm) } } +// SetVolumeCMap sets volumes and volumeMounts. The type of volumes is configMap. +func (v *volumeDefine) SetVolumeCMap(cmap *corev1.ConfigMap, k, p string, isReadOnly bool) { + vm := corev1.VolumeMount{ + MountPath: p, + Name: cmap.Name, + ReadOnly: isReadOnly, + SubPath: path.Base(p), + } + v.volumeMounts = append(v.volumeMounts, vm) + + vo := corev1.Volume{ + Name: cmap.Name, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: cmap.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: k, + Path: path.Base(p), // subpath + }, + }, + }, + }, + } + v.volumes = append(v.volumes, vo) +} + func createResources(as *v1.AppService) corev1.ResourceRequirements { var cpuRequest, cpuLimit int64 memory := as.ContainerMemory