mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
db: add standalone_anon
This commit is contained in:
+19
-15
@@ -153,23 +153,9 @@ type StatusStandaloneResourceCreateInput struct {
|
||||
StatusBaseResourceCreateInput
|
||||
}
|
||||
|
||||
type StandaloneResourceCreateInput struct {
|
||||
type StandaloneAnonResourceCreateInput struct {
|
||||
ResourceBaseCreateInput
|
||||
|
||||
// 资源名称,如果generate_name为空,则为必填项
|
||||
// description: resource name, required if generated_name is not given
|
||||
// unique: true
|
||||
// required: true
|
||||
// example: test-network
|
||||
Name string `json:"name" help:"name of newly created resource" positional:"true" required:"true"`
|
||||
|
||||
// 生成资源名称的模板,如果name为空,则为必填项
|
||||
// description: generated resource name, given a pattern to generate name, required if name is not given
|
||||
// unique: false
|
||||
// required: false
|
||||
// example: test###
|
||||
GenerateName string `json:"generate_name" help:"pattern for generating name if no name is given"`
|
||||
|
||||
// 资源描述
|
||||
// required: false
|
||||
// example: test create network
|
||||
@@ -185,6 +171,24 @@ type StandaloneResourceCreateInput struct {
|
||||
Metadata map[string]string `json:"__meta__" token:"tag" help:"tags in the form of key=value"`
|
||||
}
|
||||
|
||||
type StandaloneResourceCreateInput struct {
|
||||
StandaloneAnonResourceCreateInput
|
||||
|
||||
// 资源名称,如果generate_name为空,则为必填项
|
||||
// description: resource name, required if generated_name is not given
|
||||
// unique: true
|
||||
// required: true
|
||||
// example: test-network
|
||||
Name string `json:"name" help:"name of newly created resource" positional:"true" required:"true"`
|
||||
|
||||
// 生成资源名称的模板,如果name为空,则为必填项
|
||||
// description: generated resource name, given a pattern to generate name, required if name is not given
|
||||
// unique: false
|
||||
// required: false
|
||||
// example: test###
|
||||
GenerateName string `json:"generate_name" help:"pattern for generating name if no name is given"`
|
||||
}
|
||||
|
||||
type JoinResourceBaseCreateInput struct {
|
||||
ResourceBaseCreateInput
|
||||
}
|
||||
|
||||
+8
-3
@@ -216,7 +216,7 @@ type MetadataResourceListInput struct {
|
||||
WithMeta *bool `json:"with_meta"`
|
||||
}
|
||||
|
||||
type StandaloneResourceListInput struct {
|
||||
type StandaloneAnonResourceListInput struct {
|
||||
ResourceBaseListInput
|
||||
|
||||
MetadataResourceListInput
|
||||
@@ -224,12 +224,17 @@ type StandaloneResourceListInput struct {
|
||||
// 显示所有的资源,包括模拟的资源
|
||||
ShowEmulated *bool `json:"show_emulated" help:"show emulated resources" negative:"do not show emulated resources"`
|
||||
|
||||
// 以资源名称过滤列表
|
||||
Names []string `json:"name" help:"filter by names"`
|
||||
// 以资源ID过滤列表
|
||||
Ids []string `json:"id" help:"filter by ids"`
|
||||
}
|
||||
|
||||
type StandaloneResourceListInput struct {
|
||||
StandaloneAnonResourceListInput
|
||||
|
||||
// 以资源名称过滤列表
|
||||
Names []string `json:"name" help:"filter by names"`
|
||||
}
|
||||
|
||||
type StatusResourceBaseListInput struct {
|
||||
// 以资源的状态过滤列表
|
||||
Status []string `json:"status"`
|
||||
|
||||
+12
-3
@@ -71,10 +71,15 @@ type AdminSharableVirtualResourceDetails struct {
|
||||
SharableVirtualResourceDetails
|
||||
}
|
||||
|
||||
type StandaloneResourceShortDescDetail struct {
|
||||
type StandaloneAnonResourceShortDescDetail struct {
|
||||
ModelBaseShortDescDetail
|
||||
|
||||
Id string `json:"id"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type StandaloneResourceShortDescDetail struct {
|
||||
StandaloneAnonResourceShortDescDetail
|
||||
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
@@ -137,12 +142,16 @@ type UserResourceDetails struct {
|
||||
OwnerName string `json:"owner_name"`
|
||||
}
|
||||
|
||||
type StandaloneResourceDetails struct {
|
||||
type StandaloneAnonResourceDetails struct {
|
||||
ResourceBaseDetails
|
||||
|
||||
MetadataResourceInfo
|
||||
}
|
||||
|
||||
type StandaloneResourceDetails struct {
|
||||
StandaloneAnonResourceDetails
|
||||
}
|
||||
|
||||
type DomainizedResourceInfo struct {
|
||||
// 资源归属项目的域名称
|
||||
ProjectDomain string `json:"project_domain"`
|
||||
|
||||
+8
-3
@@ -22,13 +22,18 @@ type ResourceBaseUpdateInput struct {
|
||||
ModelBaseUpdateInput
|
||||
}
|
||||
|
||||
type StandaloneResourceBaseUpdateInput struct {
|
||||
type StandaloneAnonResourceBaseUpdateInput struct {
|
||||
ResourceBaseUpdateInput
|
||||
|
||||
// 资源描述
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type StandaloneResourceBaseUpdateInput struct {
|
||||
StandaloneAnonResourceBaseUpdateInput
|
||||
|
||||
// 资源名称
|
||||
Name string `json:"name"`
|
||||
// 资源描述
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type StatusStandaloneResourceBaseUpdateInput struct {
|
||||
|
||||
@@ -21,49 +21,23 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"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
|
||||
SStandaloneAnonResourceBase
|
||||
|
||||
// 资源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
|
||||
SMetadataResourceBaseModelManager
|
||||
SStandaloneAnonResourceBaseManager
|
||||
|
||||
NameRequireAscii bool
|
||||
NameLength int
|
||||
@@ -76,75 +50,14 @@ func NewStandaloneResourceBaseManager(
|
||||
keywordPlural string,
|
||||
) SStandaloneResourceBaseManager {
|
||||
return SStandaloneResourceBaseManager{
|
||||
SResourceBaseManager: NewResourceBaseManager(dt, tableName, keyword, keywordPlural),
|
||||
SStandaloneAnonResourceBaseManager: NewStandaloneAnonResourceBaseManager(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")
|
||||
@@ -155,10 +68,6 @@ func (manager *SStandaloneResourceBaseManager) ValidateName(name string) error {
|
||||
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)
|
||||
}
|
||||
@@ -173,62 +82,30 @@ func (manager *SStandaloneResourceBaseManager) ListItemFilter(
|
||||
userCred mcclient.TokenCredential,
|
||||
input apis.StandaloneResourceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SResourceBaseManager.ListItemFilter(ctx, q, userCred, input.ResourceBaseListInput)
|
||||
q, err := manager.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneAnonResourceListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "SResourceBaseManager.ListItemFilte")
|
||||
return q, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.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)
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.ListItemFilter(manager.GetIModelManager(), q, input.MetadataResourceListInput)
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SStandaloneResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SMetadataResourceBaseModelManager.QueryDistinctExtraField(manager.GetIModelManager(), q, field)
|
||||
if err == nil {
|
||||
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)
|
||||
q, err := manager.SStandaloneAnonResourceBaseManager.OrderByExtraFields(ctx, q, userCred, input.StandaloneAnonResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.OrderByExtraFields(manager.GetIModelManager(), q, input.MetadataResourceListInput)
|
||||
|
||||
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
|
||||
}
|
||||
@@ -238,265 +115,23 @@ func (model *SStandaloneResourceBase) GetIStandaloneModel() IStandaloneModel {
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
desc := model.SResourceBase.GetShortDesc(ctx)
|
||||
desc := model.SStandaloneAnonResourceBase.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.StandaloneAnonResourceShortDescDetail = *model.SStandaloneAnonResourceBase.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 isUserMetadata(key string) bool {
|
||||
return strings.HasPrefix(key, USER_TAG_PREFIX)
|
||||
}
|
||||
|
||||
func containsUserMetadata(dict map[string]interface{}) bool {
|
||||
for k := range dict {
|
||||
if isUserMetadata(k) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValue(ctx, model, key, value, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValue")
|
||||
}
|
||||
if isUserMetadata(key) {
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetAllMetadata(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValuesWithLog")
|
||||
}
|
||||
if containsUserMetadata(dictstore) {
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValuesWithLog")
|
||||
}
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetAll")
|
||||
}
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetAll")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValue(ctx, model, key, "", userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValue")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.RemoveAll(ctx, model, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "RemoveAll")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error) {
|
||||
return Metadata.GetAll(model, nil, "", userCred)
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) GetAllUserMetadata() (map[string]string, error) {
|
||||
meta, err := Metadata.GetAll(model, nil, USER_TAG_PREFIX, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Metadata.GetAll")
|
||||
}
|
||||
ret := make(map[string]string)
|
||||
for k, v := range meta {
|
||||
ret[k[len(USER_TAG_PREFIX):]] = v
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
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, input apis.GetMetadataInput) (apis.GetMetadataOutput, error) {
|
||||
val, err := Metadata.GetAll(model, input.Field, input.Prefix, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Metadata.GetAll")
|
||||
}
|
||||
if len(input.Prefix) > 0 {
|
||||
// trim prefix from key
|
||||
ret := make(map[string]string)
|
||||
for k, v := range val {
|
||||
ret[k[len(input.Prefix):]] = v
|
||||
}
|
||||
val = ret
|
||||
}
|
||||
return 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")
|
||||
}
|
||||
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (model *SStandaloneResourceBase) PerformMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
// 已双下滑线开头的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
|
||||
}
|
||||
err := model.SetAllMetadata(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetAllMetadata")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 更新资源的用户标签
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (model *SStandaloneResourceBase) PerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformUserMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
dictStore[USER_TAG_PREFIX+k] = v
|
||||
}
|
||||
err := model.SetUserMetadataValues(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetUserMetadataValues")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
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, input apis.PerformSetUserMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
if len(k) > 64-len(USER_TAG_PREFIX) {
|
||||
return nil, httperrors.NewInputParameterError("input key too long > %d", 64-len(USER_TAG_PREFIX))
|
||||
}
|
||||
if len(v) > 65535 {
|
||||
return nil, httperrors.NewInputParameterError("input value too long > %d", 65535)
|
||||
}
|
||||
dictStore[USER_TAG_PREFIX+k] = v
|
||||
}
|
||||
err := model.SetUserMetadataAll(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetUserMetadataAll")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
model.SResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
meta := make(map[string]string)
|
||||
err := data.Unmarshal(&meta, "__meta__")
|
||||
if err == nil {
|
||||
model.PerformMetadata(ctx, userCred, nil, meta)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
meta := make(map[string]string)
|
||||
err := data.Unmarshal(&meta, "__meta__")
|
||||
if err == nil {
|
||||
model.PerformMetadata(ctx, userCred, nil, meta)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
input.StandaloneAnonResourceCreateInput, err = manager.SStandaloneAnonResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneAnonResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SResourceBaseManager.ValidateCreateData")
|
||||
return input, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
input.Name = strings.TrimSpace(input.Name)
|
||||
if strings.ContainsAny(input.Name, "\n\r\t") {
|
||||
@@ -518,47 +153,18 @@ func (manager *SStandaloneResourceBaseManager) FetchCustomizeColumns(
|
||||
isList bool,
|
||||
) []apis.StandaloneResourceDetails {
|
||||
ret := make([]apis.StandaloneResourceDetails, len(objs))
|
||||
upperRet := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
metaRet := manager.SMetadataResourceBaseModelManager.FetchCustomizeColumns(manager.GetIModelManager(), userCred, objs, fields)
|
||||
upperRet := manager.SStandaloneAnonResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range objs {
|
||||
ret[i] = apis.StandaloneResourceDetails{
|
||||
ResourceBaseDetails: upperRet[i],
|
||||
MetadataResourceInfo: metaRet[i],
|
||||
StandaloneAnonResourceDetails: upperRet[i],
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (manager *SStandaloneResourceBaseManager) GetMetadataHiddenKeys() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SStandaloneResourceBaseManager) GetExportExtraKeys(ctx context.Context, keys stringutils2.SSortedStrings, rowMap map[string]string) *jsonutils.JSONDict {
|
||||
res := manager.SResourceBaseManager.GetExportExtraKeys(ctx, keys, rowMap)
|
||||
|
||||
metaRes := manager.SMetadataResourceBaseModelManager.GetExportExtraKeys(keys, rowMap)
|
||||
if metaRes.Length() > 0 {
|
||||
res.Update(metaRes)
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.ListItemExportKeys(manager.GetIModelManager(), q, keys)
|
||||
|
||||
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)
|
||||
input.StandaloneAnonResourceBaseUpdateInput, err = model.SStandaloneAnonResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneAnonResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SModelBase.ValidateUpdateData")
|
||||
}
|
||||
@@ -575,11 +181,3 @@ func (model *SStandaloneResourceBase) ValidateUpdateData(ctx context.Context, us
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) IsShared() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
// 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/pkg/errors"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"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 SStandaloneAnonResourceBase struct {
|
||||
SResourceBase
|
||||
|
||||
// 资源UUID
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user" json:"id"`
|
||||
|
||||
// 资源描述信息
|
||||
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 *SStandaloneAnonResourceBase) BeforeInsert() {
|
||||
if len(model.Id) == 0 {
|
||||
model.Id = DefaultUUIDGenerator()
|
||||
}
|
||||
}
|
||||
|
||||
type SStandaloneAnonResourceBaseManager struct {
|
||||
SResourceBaseManager
|
||||
SMetadataResourceBaseModelManager
|
||||
}
|
||||
|
||||
func NewStandaloneAnonResourceBaseManager(
|
||||
dt interface{},
|
||||
tableName string,
|
||||
keyword string,
|
||||
keywordPlural string,
|
||||
) SStandaloneAnonResourceBaseManager {
|
||||
return SStandaloneAnonResourceBaseManager{
|
||||
SResourceBaseManager: NewResourceBaseManager(dt, tableName, keyword, keywordPlural),
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) IsStandaloneManager() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SStandaloneAnonResourceBaseManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowList(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SStandaloneAnonResourceBaseManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowCreate(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SStandaloneAnonResourceBase) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowGet(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SStandaloneAnonResourceBase) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
return IsAdminAllowUpdate(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SStandaloneAnonResourceBase) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowDelete(userCred, self)
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) GetIStandaloneModelManager() IStandaloneModelManager {
|
||||
return manager.GetVirtualObject().(IStandaloneModelManager)
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
|
||||
return q.Equals("id", idStr)
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) FilterByNotId(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
|
||||
return q.NotEquals("id", idStr)
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) 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 *SStandaloneAnonResourceBaseManager) FetchById(idStr string) (IModel, error) {
|
||||
return FetchById(manager.GetIStandaloneModelManager(), idStr)
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input apis.StandaloneAnonResourceListInput,
|
||||
) (*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.Ids) > 0 {
|
||||
q = q.In("id", input.Ids)
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.ListItemFilter(manager.GetIModelManager(), q, input.MetadataResourceListInput)
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SMetadataResourceBaseModelManager.QueryDistinctExtraField(manager.GetIModelManager(), q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
input apis.StandaloneAnonResourceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SResourceBaseManager.OrderByExtraFields(ctx, q, userCred, input.ResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.OrderByExtraFields(manager.GetIModelManager(), q, input.MetadataResourceListInput)
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) StandaloneModelManager() IStandaloneModelManager {
|
||||
return model.GetModelManager().(IStandaloneModelManager)
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetId() string {
|
||||
return model.Id
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetIStandaloneModel() IStandaloneModel {
|
||||
return model.GetVirtualObject().(IStandaloneModel)
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
desc := model.SResourceBase.GetShortDesc(ctx)
|
||||
desc.Add(jsonutils.NewString(model.GetId()), "id")
|
||||
/*if len(model.ExternalId) > 0 {
|
||||
desc.Add(jsonutils.NewString(model.ExternalId), "external_id")
|
||||
}*/
|
||||
return desc
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetShortDescV2(ctx context.Context) *apis.StandaloneAnonResourceShortDescDetail {
|
||||
desc := &apis.StandaloneAnonResourceShortDescDetail{}
|
||||
desc.ModelBaseShortDescDetail = *model.SResourceBase.GetShortDescV2(ctx)
|
||||
desc.Id = model.GetId()
|
||||
return desc
|
||||
}
|
||||
|
||||
/*
|
||||
* userCred: optional
|
||||
*/
|
||||
func (model *SStandaloneAnonResourceBase) GetMetadata(key string, userCred mcclient.TokenCredential) string {
|
||||
return Metadata.GetStringValue(model, key, userCred)
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetMetadataJson(key string, userCred mcclient.TokenCredential) jsonutils.JSONObject {
|
||||
return Metadata.GetJsonValue(model, key, userCred)
|
||||
}
|
||||
|
||||
func isUserMetadata(key string) bool {
|
||||
return strings.HasPrefix(key, USER_TAG_PREFIX)
|
||||
}
|
||||
|
||||
func containsUserMetadata(dict map[string]interface{}) bool {
|
||||
for k := range dict {
|
||||
if isUserMetadata(k) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValue(ctx, model, key, value, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValue")
|
||||
}
|
||||
if isUserMetadata(key) {
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetAllMetadata(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValuesWithLog")
|
||||
}
|
||||
if containsUserMetadata(dictstore) {
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValuesWithLog")
|
||||
}
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetAll")
|
||||
}
|
||||
model.GetIStandaloneModel().OnMetadataUpdated(ctx, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetAll")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.SetValue(ctx, model, key, "", userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "SetValue")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := Metadata.RemoveAll(ctx, model, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "RemoveAll")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error) {
|
||||
return Metadata.GetAll(model, nil, "", userCred)
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) GetAllUserMetadata() (map[string]string, error) {
|
||||
meta, err := Metadata.GetAll(model, nil, USER_TAG_PREFIX, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Metadata.GetAll")
|
||||
}
|
||||
ret := make(map[string]string)
|
||||
for k, v := range meta {
|
||||
ret[k[len(USER_TAG_PREFIX):]] = v
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) AllowGetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return IsAllowGetSpec(rbacutils.ScopeSystem, userCred, model, "metadata")
|
||||
}
|
||||
|
||||
// 获取资源标签(元数据)
|
||||
func (model *SStandaloneAnonResourceBase) GetDetailsMetadata(ctx context.Context, userCred mcclient.TokenCredential, input apis.GetMetadataInput) (apis.GetMetadataOutput, error) {
|
||||
val, err := Metadata.GetAll(model, input.Field, input.Prefix, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Metadata.GetAll")
|
||||
}
|
||||
if len(input.Prefix) > 0 {
|
||||
// trim prefix from key
|
||||
ret := make(map[string]string)
|
||||
for k, v := range val {
|
||||
ret[k[len(input.Prefix):]] = v
|
||||
}
|
||||
val = ret
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) AllowPerformMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "metadata")
|
||||
}
|
||||
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (model *SStandaloneAnonResourceBase) PerformMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
// 已双下滑线开头的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
|
||||
}
|
||||
err := model.SetAllMetadata(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetAllMetadata")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) AllowPerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "user-metadata")
|
||||
}
|
||||
|
||||
// 更新资源的用户标签
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (model *SStandaloneAnonResourceBase) PerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformUserMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
dictStore[USER_TAG_PREFIX+k] = v
|
||||
}
|
||||
err := model.SetUserMetadataValues(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetUserMetadataValues")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) 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 *SStandaloneAnonResourceBase) PerformSetUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformSetUserMetadataInput) (jsonutils.JSONObject, error) {
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range input {
|
||||
if len(k) > 64-len(USER_TAG_PREFIX) {
|
||||
return nil, httperrors.NewInputParameterError("input key too long > %d", 64-len(USER_TAG_PREFIX))
|
||||
}
|
||||
if len(v) > 65535 {
|
||||
return nil, httperrors.NewInputParameterError("input value too long > %d", 65535)
|
||||
}
|
||||
dictStore[USER_TAG_PREFIX+k] = v
|
||||
}
|
||||
err := model.SetUserMetadataAll(ctx, dictStore, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SetUserMetadataAll")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
model.SResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
meta := make(map[string]string)
|
||||
err := data.Unmarshal(&meta, "__meta__")
|
||||
if err == nil {
|
||||
model.PerformMetadata(ctx, userCred, nil, meta)
|
||||
}
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
model.SResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
meta := make(map[string]string)
|
||||
err := data.Unmarshal(&meta, "__meta__")
|
||||
if err == nil {
|
||||
model.PerformMetadata(ctx, userCred, nil, meta)
|
||||
}
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
if model.Deleted {
|
||||
model.RemoveAllMetadata(ctx, userCred)
|
||||
}
|
||||
model.SResourceBase.PostDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
// func (model *SStandaloneAnonResourceBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
// return DeleteModel(ctx, userCred, model)
|
||||
// }
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) ClearSchedDescCache() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) 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 *SStandaloneAnonResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StandaloneAnonResourceCreateInput) (apis.StandaloneAnonResourceCreateInput, 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 *SStandaloneAnonResourceBase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (apis.StandaloneAnonResourceDetails, error) {
|
||||
return apis.StandaloneAnonResourceDetails{}, nil
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.StandaloneAnonResourceDetails {
|
||||
ret := make([]apis.StandaloneAnonResourceDetails, len(objs))
|
||||
upperRet := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
metaRet := manager.SMetadataResourceBaseModelManager.FetchCustomizeColumns(manager.GetIModelManager(), userCred, objs, fields)
|
||||
for i := range objs {
|
||||
ret[i] = apis.StandaloneAnonResourceDetails{
|
||||
ResourceBaseDetails: upperRet[i],
|
||||
MetadataResourceInfo: metaRet[i],
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) GetMetadataHiddenKeys() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) GetExportExtraKeys(ctx context.Context, keys stringutils2.SSortedStrings, rowMap map[string]string) *jsonutils.JSONDict {
|
||||
res := manager.SResourceBaseManager.GetExportExtraKeys(ctx, keys, rowMap)
|
||||
|
||||
metaRes := manager.SMetadataResourceBaseModelManager.GetExportExtraKeys(keys, rowMap)
|
||||
if metaRes.Length() > 0 {
|
||||
res.Update(metaRes)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (manager *SStandaloneAnonResourceBaseManager) 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")
|
||||
}
|
||||
|
||||
q = manager.SMetadataResourceBaseModelManager.ListItemExportKeys(manager.GetIModelManager(), q, keys)
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.StandaloneAnonResourceBaseUpdateInput) (apis.StandaloneAnonResourceBaseUpdateInput, 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")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) IsShared() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (model *SStandaloneAnonResourceBase) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
// noop
|
||||
}
|
||||
@@ -211,7 +211,9 @@ func buildCloudregion(id, name, provider string) *models.SCloudregion {
|
||||
SEnabledStatusStandaloneResourceBase: db.SEnabledStatusStandaloneResourceBase{
|
||||
SStatusStandaloneResourceBase: db.SStatusStandaloneResourceBase{
|
||||
SStandaloneResourceBase: db.SStandaloneResourceBase{
|
||||
Id: id,
|
||||
SStandaloneAnonResourceBase: db.SStandaloneAnonResourceBase{
|
||||
Id: id,
|
||||
},
|
||||
Name: name,
|
||||
},
|
||||
SStatusResourceBase: db.SStatusResourceBase{
|
||||
|
||||
Reference in New Issue
Block a user