Files
cloudpods/pkg/notify/models/mod_config.go
2020-03-18 20:51:20 +08:00

253 lines
7.3 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"fmt"
"strconv"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
_interface "yunion.io/x/onecloud/pkg/notify/interface"
"yunion.io/x/onecloud/pkg/notify/options"
)
type SConfigManager struct {
SStatusStandaloneResourceBaseManager
}
var ConfigManager *SConfigManager
func init() {
ConfigManager = &SConfigManager{
SStatusStandaloneResourceBaseManager: NewStatusStandaloneResourceBaseManager(
SConfig{},
"notify_t_config",
"config",
"configs",
),
}
ConfigManager.SetVirtualObject(ConfigManager)
}
// SConfig is a table which storage (k,v) and its type.
// The three important concepts are key, value and type.
// Key and type uniquely identify a value.
type SConfig struct {
SStatusStandaloneResourceBase
Type string `width:"15" nullable:"false" create:"required" list:"user"`
KeyText string `width:"30" nullable:"false" create:"required" list:"user"`
ValueText string `width:"256" nullable:"false" create:"required" list:"user"`
}
// ListItemFilter is a hook function belong to IModelManager interface when Listing.
// This will Called in yunion.io/x/onecloud/pkg/cloudcommon/db.List function.
func (self *SConfigManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
if !query.Contains("type") {
return q, nil
}
contactType, _ := query.GetString("type")
q.Filter(sqlchemy.Equals(q.Field("type"), contactType))
return q, nil
}
// GetValue fetch the SConfig struct corresponding to key and type.
func (self *SConfigManager) GetValue(key, contactType string) (*SConfig, error) {
q := self.Query()
q.Filter(sqlchemy.AND(sqlchemy.Equals(q.Field("type"), contactType), sqlchemy.Equals(q.Field("key_text"), key)))
configs := make([]SConfig, 0, 1)
err := db.FetchModelObjects(self, q, &configs)
if err != nil {
return nil, errors.Wrap(err, "Fetch SConfig by key and type failed")
}
if len(configs) == 0 {
return nil, errors.Error("There is no SConfig whose key and type meet the requirement")
}
return &configs[0], nil
}
func (self *SConfigManager) InitializeData() error {
q := self.Query()
q = q.Filter(sqlchemy.OR(sqlchemy.IsNotNull(q.Field("updated_at")), sqlchemy.IsNotNull(q.Field("created_at")),
sqlchemy.IsNotNull(q.Field("deleted_at")), sqlchemy.IsTrue(q.Field("deleted")),
sqlchemy.IsNotNull(q.Field("update_by")), sqlchemy.IsNotNull(q.Field("delete_by"))))
n, err := q.CountWithError()
if err != nil {
return err
}
if n <= 0 {
log.Debugf("need to init data for %s", self.TableSpec().Name())
// need to update
sql := fmt.Sprintf("update %s set updated_at=gmt_modified, deleted=is_deleted, created_at=gmt_create, deleted_at=gmt_deleted, update_by=modified_by, delete_by=deleted_by", self.TableSpec().Name())
q := sqlchemy.NewRawQuery(sql, "")
q.Row()
sql = fmt.Sprintf("update %s set type='mobile' where type='sms_aliyun'", self.TableSpec().Name())
q = sqlchemy.NewRawQuery(sql, "")
q.Row()
}
// init webconsole's config
sql := fmt.Sprintf("update %s set deleted='1' where type='webconsole'", self.TableSpec().Name())
q = sqlchemy.NewRawQuery(sql)
q.Row()
configs := []SConfig{
{
Type: "webconsole",
KeyText: "auth_uri",
ValueText: options.Options.AuthURL,
},
{
Type: "webconsole",
KeyText: "admin_user",
ValueText: options.Options.AdminUser,
},
{
Type: "webconsole",
KeyText: "admin_password",
ValueText: options.Options.AdminPassword,
},
{
Type: "webconsole",
KeyText: "admin_tenant_name",
ValueText: options.Options.AdminProject,
},
}
for _, config := range configs {
err := self.TableSpec().Insert(&config)
if err != nil {
return err
}
}
return nil
}
// Fetch all SConfig struct which type is contactType.
func (self *SConfigManager) GetConfigByType(contactType string) ([]SConfig, error) {
q := self.Query()
q.Filter(sqlchemy.Equals(q.Field("type"), contactType))
configs := make([]SConfig, 0, 5)
err := db.FetchModelObjects(self, q, &configs)
if err != nil {
return nil, errors.Wrap(err, "Fetch SConfigs by type failed")
}
//if len(configs) == 0 {
// return nil, errors.Error("There is no SConfig whose type meet the requirement")
//}
return configs, nil
}
func (self *SConfigManager) GetConfig(contactType string) (_interface.SConfig, error) {
configs, err := self.GetConfigByType(contactType)
if err != nil {
return nil, err
}
ret := make(map[string]string)
for i := range configs {
ret[configs[i].KeyText] = configs[i].ValueText
}
return ret, nil
}
func (self *SConfigManager) SetConfig(contactType string, config _interface.SConfig) error {
return fmt.Errorf("SetConfig Not Implemented")
}
type SConvertFunc func(*jsonutils.JSONDict) *jsonutils.JSONDict
var (
// toDisplay store SConvertFunc which convert the data from client to the form required by database of contactType
toDisplay map[string]SConvertFunc
// fromDisplay store SConvertFunc which convert the data from database to the form required by client of contactType
fromDisplay map[string]SConvertFunc
)
func init() {
toDisplay = map[string]SConvertFunc{
EMAIL: emailToDisplay,
}
fromDisplay = map[string]SConvertFunc{
EMAIL: emailFromDisplay,
}
}
func emailFromDisplay(dict *jsonutils.JSONDict) *jsonutils.JSONDict {
keys := dict.SortedKeys()
newKey := ""
for _, key := range keys {
switch key {
case "username", "password":
newKey = "mail." + key
case "hostname", "hostport":
newKey = "mail.smtp." + key
case "ssl_global":
newKey = "mail.global.ssl"
}
v, _ := dict.Get(key)
dict.Add(v, newKey)
dict.Remove(key)
}
return dict
}
func emailToDisplay(dict *jsonutils.JSONDict) *jsonutils.JSONDict {
keys := dict.SortedKeys()
for _, key := range keys {
newKey := ""
value, _ := dict.Get(key)
switch key {
case "mail.username", "mail.password":
newKey = key[5:]
case "mail.smtp.hostname":
newKey = key[10:]
case "mail.smtp.hostport":
newKey = key[10:]
portStr, _ := value.GetString()
port, _ := strconv.Atoi(portStr)
value = jsonutils.NewInt(int64(port))
case "mail.global.ssl":
newKey = "ssl_global"
sslStr, _ := value.GetString()
ssl, _ := strconv.ParseBool(sslStr)
value = jsonutils.NewBool(ssl)
}
dict.Add(value, newKey)
dict.Remove(key)
}
return dict
}
func (self *SConfigManager) Display2Database(cType string, dict *jsonutils.JSONDict) *jsonutils.JSONDict {
cf, ok := fromDisplay[cType]
if ok {
return cf(dict)
}
return dict
}
func (self *SConfigManager) Database2Display(cType string, dict *jsonutils.JSONDict) *jsonutils.JSONDict {
cf, ok := toDisplay[cType]
if ok {
return cf(dict)
}
return dict
}