Files
cloudpods/pkg/cloudcommon/db/standalone.go
2020-03-27 01:20:29 +08:00

595 lines
22 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 db
import (
"context"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/regutils"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type UUIDGenerator func() string
var (
DefaultUUIDGenerator = stringutils.UUID4
)
type SStandaloneResourceBase struct {
SResourceBase
// 资源UUID
Id string `width:"128" charset:"ascii" primary:"true" list:"user" json:"id"`
// 资源名称
Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user" update:"user" create:"required" json:"name"`
// 资源描述信息
Description string `width:"256" charset:"utf8" get:"user" list:"user" update:"user" create:"optional" json:"description"`
// 是否是模拟资源, 部分从公有云上同步的资源并不真实存在, 例如宿主机
// list 接口默认不会返回这类资源,除非显示指定 is_emulate=true 过滤参数
IsEmulated bool `nullable:"false" default:"false" list:"admin" create:"admin_optional" json:"is_emulated"`
}
func (model *SStandaloneResourceBase) BeforeInsert() {
if len(model.Id) == 0 {
model.Id = DefaultUUIDGenerator()
}
}
type SStandaloneResourceBaseManager struct {
SResourceBaseManager
NameRequireAscii bool
NameLength int
}
func NewStandaloneResourceBaseManager(
dt interface{},
tableName string,
keyword string,
keywordPlural string,
) SStandaloneResourceBaseManager {
return SStandaloneResourceBaseManager{
SResourceBaseManager: NewResourceBaseManager(dt, tableName, keyword, keywordPlural),
}
}
func (manager *SStandaloneResourceBaseManager) IsStandaloneManager() bool {
return true
}
func (self *SStandaloneResourceBaseManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return IsAdminAllowList(userCred, self)
}
func (self *SStandaloneResourceBaseManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAdminAllowCreate(userCred, self)
}
func (self *SStandaloneResourceBase) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return IsAdminAllowGet(userCred, self)
}
func (self *SStandaloneResourceBase) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return IsAdminAllowUpdate(userCred, self)
}
func (self *SStandaloneResourceBase) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAdminAllowDelete(userCred, self)
}
func (manager *SStandaloneResourceBaseManager) GetIStandaloneModelManager() IStandaloneModelManager {
return manager.GetVirtualObject().(IStandaloneModelManager)
}
func (manager *SStandaloneResourceBaseManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
return q.Equals("id", idStr)
}
func (manager *SStandaloneResourceBaseManager) FilterByNotId(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
return q.NotEquals("id", idStr)
}
func (manager *SStandaloneResourceBaseManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlchemy.SQuery {
return q.Equals("name", name)
}
func (manager *SStandaloneResourceBaseManager) FilterByHiddenSystemAttributes(q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
q = manager.SResourceBaseManager.FilterByHiddenSystemAttributes(q, userCred, query, scope)
showEmulated := jsonutils.QueryBoolean(query, "show_emulated", false)
if showEmulated {
var isAllow bool
if consts.IsRbacEnabled() {
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList, "show_emulated")
if !scope.HigherThan(allowScope) {
isAllow = true
}
} else {
if userCred.HasSystemAdminPrivilege() {
isAllow = true
}
}
if !isAllow {
showEmulated = false
}
}
if !showEmulated {
q = q.IsFalse("is_emulated")
}
return q
}
func (manager *SStandaloneResourceBaseManager) ValidateName(name string) error {
if manager.NameRequireAscii && !regutils.MatchName(name) {
return httperrors.NewInputParameterError("name starts with letter, and contains letter, number and ._@- only")
}
if manager.NameLength > 0 && len(name) > manager.NameLength {
return httperrors.NewInputParameterError("name longer than %d", manager.NameLength)
}
return nil
}
func (manager *SStandaloneResourceBaseManager) FetchById(idStr string) (IModel, error) {
return FetchById(manager.GetIStandaloneModelManager(), idStr)
}
func (manager *SStandaloneResourceBaseManager) FetchByName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByName(manager.GetIStandaloneModelManager(), userCred, idStr)
}
func (manager *SStandaloneResourceBaseManager) FetchByIdOrName(userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
return FetchByIdOrName(manager.GetIStandaloneModelManager(), userCred, idStr)
}
func (manager *SStandaloneResourceBaseManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
input apis.StandaloneResourceListInput,
) (*sqlchemy.SQuery, error) {
q, err := manager.SResourceBaseManager.ListItemFilter(ctx, q, userCred, input.ResourceBaseListInput)
if err != nil {
return q, errors.Wrap(err, "SResourceBaseManager.ListItemFilte")
}
// show_emulated is handled by FilterByHiddenSystemAttributes
if len(input.Names) > 0 {
q = q.In("name", input.Names)
}
if len(input.Ids) > 0 {
q = q.In("id", input.Ids)
}
tags := map[string][]string{}
for _, tag := range input.Tags {
if _, ok := tags[tag.Key]; !ok {
tags[tag.Key] = []string{}
}
if len(tag.Value) > 0 && !utils.IsInStringArray(tag.Value, tags[tag.Key]) {
tags[tag.Key] = append(tags[tag.Key], tag.Value)
}
}
if len(tags) > 0 {
metadataResQ := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
metadataView := metadataResQ.Query()
idx := 0
for key, values := range tags {
if idx == 0 {
metadataView = metadataView.Equals("key", key)
if len(values) > 0 {
metadataView = metadataView.In("value", values)
}
} else {
subMetataView := metadataResQ.Query().Equals("key", key)
if len(values) > 0 {
subMetataView = subMetataView.In("value", values)
}
sq := subMetataView.SubQuery()
metadataView.Join(sq, sqlchemy.Equals(metadataView.Field("id"), sq.Field("id")))
}
idx++
}
metadatas := metadataView.SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Distinct().SubQuery()
q = q.Filter(sqlchemy.In(q.Field("id"), sq))
}
if input.WithoutUserMeta {
metadatas := Metadata.Query().Equals("obj_type", manager.Keyword()).SubQuery()
sq := metadatas.Query(metadatas.Field("obj_id")).Startswith("key", USER_TAG_PREFIX).Distinct().SubQuery()
q.Filter(sqlchemy.NotIn(q.Field("id"), sq))
}
return q, nil
}
func (manager *SStandaloneResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
if strings.HasPrefix(field, "tag:") {
tagKey := field[4:]
metaQ := Metadata.Query("obj_id", "value").Equals("obj_type", manager.Keyword()).Equals("key", tagKey).SubQuery()
q = q.AppendField(metaQ.Field("value", field)).Distinct()
q = q.LeftJoin(metaQ, sqlchemy.Equals(q.Field("id"), metaQ.Field("obj_id")))
q = q.Asc(metaQ.Field("value"))
return q, nil
}
q, err := manager.SResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (manager *SStandaloneResourceBaseManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
input apis.StandaloneResourceListInput,
) (*sqlchemy.SQuery, error) {
q, err := manager.SResourceBaseManager.OrderByExtraFields(ctx, q, userCred, input.ResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SResourceBaseManager.OrderByExtraFields")
}
if len(input.OrderByTag) > 0 {
order := sqlchemy.SQL_ORDER_ASC
tagKey := input.OrderByTag
if stringutils2.HasSuffixIgnoreCase(input.OrderByTag, string(sqlchemy.SQL_ORDER_ASC)) {
tagKey = tagKey[0 : len(tagKey)-len(sqlchemy.SQL_ORDER_ASC)-1]
} else if stringutils2.HasSuffixIgnoreCase(input.OrderByTag, string(sqlchemy.SQL_ORDER_DESC)) {
tagKey = tagKey[0 : len(tagKey)-len(sqlchemy.SQL_ORDER_DESC)-1]
order = sqlchemy.SQL_ORDER_DESC
}
metaQ := Metadata.Query("obj_id", "value").Equals("obj_type", manager.Keyword()).Equals("key", tagKey).SubQuery()
q = q.LeftJoin(metaQ, sqlchemy.Equals(q.Field("id"), metaQ.Field("obj_id")))
if order == sqlchemy.SQL_ORDER_ASC {
q = q.Asc(metaQ.Field("value"))
} else {
q = q.Desc(metaQ.Field("value"))
}
}
return q, nil
}
func (model *SStandaloneResourceBase) StandaloneModelManager() IStandaloneModelManager {
return model.GetModelManager().(IStandaloneModelManager)
}
func (model *SStandaloneResourceBase) GetId() string {
return model.Id
}
func (model *SStandaloneResourceBase) GetName() string {
return model.Name
}
func (model *SStandaloneResourceBase) GetIStandaloneModel() IStandaloneModel {
return model.GetVirtualObject().(IStandaloneModel)
}
func (model *SStandaloneResourceBase) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
desc := model.SResourceBase.GetShortDesc(ctx)
desc.Add(jsonutils.NewString(model.GetName()), "name")
desc.Add(jsonutils.NewString(model.GetId()), "id")
/*if len(model.ExternalId) > 0 {
desc.Add(jsonutils.NewString(model.ExternalId), "external_id")
}*/
return desc
}
func (model *SStandaloneResourceBase) GetShortDescV2(ctx context.Context) *apis.StandaloneResourceShortDescDetail {
desc := &apis.StandaloneResourceShortDescDetail{}
desc.ModelBaseShortDescDetail = *model.SResourceBase.GetShortDescV2(ctx)
desc.Name = model.GetName()
desc.Id = model.GetId()
return desc
}
/*
* userCred: optional
*/
func (model *SStandaloneResourceBase) GetMetadata(key string, userCred mcclient.TokenCredential) string {
return Metadata.GetStringValue(model, key, userCred)
}
func (model *SStandaloneResourceBase) GetMetadataJson(key string, userCred mcclient.TokenCredential) jsonutils.JSONObject {
return Metadata.GetJsonValue(model, key, userCred)
}
func (model *SStandaloneResourceBase) SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValue(ctx, model, key, value, userCred)
}
func (model *SStandaloneResourceBase) SetAllMetadata(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
}
func (model *SStandaloneResourceBase) SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
}
func (model *SStandaloneResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
}
func (model *SStandaloneResourceBase) SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
}
func (model *SStandaloneResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
return Metadata.SetValue(ctx, model, key, "", userCred)
}
func (model *SStandaloneResourceBase) RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error {
return Metadata.RemoveAll(ctx, model, userCred)
}
func (model *SStandaloneResourceBase) GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error) {
return Metadata.GetAll(model, nil, userCred)
}
func (model *SStandaloneResourceBase) AllowGetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return IsAllowGetSpec(rbacutils.ScopeSystem, userCred, model, "metadata")
}
func (model *SStandaloneResourceBase) GetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
fields := jsonutils.GetQueryStringArray(query, "field")
val, err := Metadata.GetAll(model, fields, userCred)
if err != nil {
return nil, err
}
return jsonutils.Marshal(val), nil
}
func (model *SStandaloneResourceBase) AllowPerformMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "metadata")
}
func (model *SStandaloneResourceBase) PerformMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
dict, ok := data.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("input data not key value dict")
}
dictMap, err := dict.GetMap()
if err != nil {
return nil, err
}
dictStore := make(map[string]interface{})
for k, v := range dictMap {
// 已双下滑线开头的metadata是系统内置普通用户不可添加只能查看
if strings.HasPrefix(k, SYS_TAG_PREFIX) && (userCred == nil || !IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "metadata")) {
return nil, httperrors.NewForbiddenError("not allow to set system key, please remove the underscore at the beginning")
}
dictStore[k], _ = v.GetString()
}
err = model.SetAllMetadata(ctx, dictStore, userCred)
return nil, err
}
func (model *SStandaloneResourceBase) AllowPerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "user-metadata")
}
func (model *SStandaloneResourceBase) PerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
dict, ok := data.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("input data not key value dict")
}
dictMap, err := dict.GetMap()
if err != nil {
return nil, err
}
dictStore := make(map[string]interface{})
for k, v := range dictMap {
dictStore[USER_TAG_PREFIX+k], _ = v.GetString()
}
err = model.SetUserMetadataValues(ctx, dictStore, userCred)
return nil, err
}
func (model *SStandaloneResourceBase) AllowPerformSetUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "set-user-metadata")
}
func (model *SStandaloneResourceBase) PerformSetUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
dict, ok := data.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("input data not key value dict")
}
dictMap, err := dict.GetMap()
if err != nil {
return nil, err
}
dictStore := make(map[string]interface{})
for k, v := range dictMap {
dictStore[USER_TAG_PREFIX+k], _ = v.GetString()
}
err = model.SetUserMetadataAll(ctx, dictStore, userCred)
return nil, err
}
func (model *SStandaloneResourceBase) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
model.SResourceBase.PostUpdate(ctx, userCred, query, data)
jsonMeta, _ := data.Get("__meta__")
if jsonMeta != nil {
model.PerformMetadata(ctx, userCred, nil, jsonMeta)
}
}
func (model *SStandaloneResourceBase) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
model.SResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
jsonMeta, _ := data.Get("__meta__")
if jsonMeta != nil {
model.PerformMetadata(ctx, userCred, nil, jsonMeta)
}
}
func (model *SStandaloneResourceBase) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
if model.Deleted {
model.RemoveAllMetadata(ctx, userCred)
}
model.SResourceBase.PostDelete(ctx, userCred)
}
// func (model *SStandaloneResourceBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
// return DeleteModel(ctx, userCred, model)
// }
func (model *SStandaloneResourceBase) ClearSchedDescCache() error {
return nil
}
func (model *SStandaloneResourceBase) AppendDescription(userCred mcclient.TokenCredential, msg string) error {
_, err := Update(model.GetIStandaloneModel(), func() error {
if len(model.Description) > 0 {
model.Description += ";"
}
model.Description += msg
return nil
})
if err != nil {
return errors.Wrap(err, "db.Update")
}
OpsLog.LogEvent(model, "append_desc", msg, userCred)
return nil
}
func (manager *SStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StandaloneResourceCreateInput) (apis.StandaloneResourceCreateInput, error) {
var err error
input.ResourceBaseCreateInput, err = manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.ResourceBaseCreateInput)
if err != nil {
return input, errors.Wrap(err, "SResourceBaseManager.ValidateCreateData")
}
return input, nil
}
func (model *SStandaloneResourceBase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (apis.StandaloneResourceDetails, error) {
return apis.StandaloneResourceDetails{}, nil
}
func (manager *SStandaloneResourceBaseManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []apis.StandaloneResourceDetails {
ret := make([]apis.StandaloneResourceDetails, len(objs))
resIds := make([]string, len(objs))
upperRet := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
for i := range objs {
ret[i] = apis.StandaloneResourceDetails{
ResourceBaseDetails: upperRet[i],
}
resIds[i] = GetObjectIdstr(objs[i].(IModel))
}
if fields == nil || fields.Contains("__meta__") {
q := Metadata.Query("id", "key", "value")
metaKeyValues := make(map[string][]SMetadata)
err := FetchQueryObjectsByIds(q, "id", resIds, &metaKeyValues)
if err != nil {
log.Errorf("FetchQueryObjectsByIds metadata fail %s", err)
return ret
}
for i := range objs {
if metaList, ok := metaKeyValues[resIds[i]]; ok {
ret[i].Metadata = metaList2Map(manager.GetIStandaloneModelManager(), userCred, metaList)
}
}
}
return ret
}
func (manager *SStandaloneResourceBaseManager) GetMetadataHiddenKeys() []string {
return nil
}
const (
TAG_EXPORT_KEY_PREFIX = "tag:"
)
func (manager *SStandaloneResourceBaseManager) GetExportExtraKeys(ctx context.Context, keys stringutils2.SSortedStrings, rowMap map[string]string) *jsonutils.JSONDict {
res := manager.SResourceBaseManager.GetExportExtraKeys(ctx, keys, rowMap)
for _, key := range keys {
if strings.HasPrefix(key, TAG_EXPORT_KEY_PREFIX) {
res.Add(jsonutils.NewString(rowMap[key]), key)
}
}
return res
}
func (manager *SStandaloneResourceBaseManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
var err error
q, err = manager.SResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
if err != nil {
return nil, errors.Wrap(err, "SResourceBaseManager.ListItemExportKeys")
}
for _, key := range keys {
if strings.HasPrefix(key, TAG_EXPORT_KEY_PREFIX) {
tagKey := key[len(TAG_EXPORT_KEY_PREFIX):]
metaQ := Metadata.Query("obj_id", "value").Equals("obj_type", manager.Keyword()).Equals("key", tagKey).SubQuery()
q = q.LeftJoin(metaQ, sqlchemy.Equals(q.Field("id"), metaQ.Field("obj_id")))
q = q.AppendField(metaQ.Field("value", key))
}
}
return q, nil
}
func (model *SStandaloneResourceBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.StandaloneResourceBaseUpdateInput) (apis.StandaloneResourceBaseUpdateInput, error) {
var err error
input.ResourceBaseUpdateInput, err = model.SResourceBase.ValidateUpdateData(ctx, userCred, query, input.ResourceBaseUpdateInput)
if err != nil {
return input, errors.Wrap(err, "SModelBase.ValidateUpdateData")
}
if len(input.Name) > 0 {
err = alterNameValidator(model.GetIStandaloneModel(), input.Name)
if err != nil {
return input, errors.Wrap(err, "alterNameValidator")
}
}
return input, nil
}
func (model *SStandaloneResourceBase) IsShared() bool {
return false
}