From f5910133580a88b758ab20fa4eba7cea14f173af Mon Sep 17 00:00:00 2001 From: rainzm Date: Mon, 12 Jul 2021 19:36:16 +0800 Subject: [PATCH] feat(notify): Gets the available notification types for the receiver --- pkg/apis/notify/config.go | 10 +++-- pkg/mcclient/modules/mod_notify.go | 2 +- pkg/mcclient/options/notify/receiver.go | 3 +- pkg/notify/models/config.go | 12 ++++- pkg/notify/models/receiver.go | 58 +++++++++++++++++++++---- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/pkg/apis/notify/config.go b/pkg/apis/notify/config.go index 258c6abd2c..9c84c98545 100644 --- a/pkg/apis/notify/config.go +++ b/pkg/apis/notify/config.go @@ -80,9 +80,13 @@ type ConfigValidateOutput struct { } type ConfigManagerGetTypesInput struct { - // description: domain where in config - // example: default - Domain string `json:"domain"` + // description: View the available notification channels for the domains with these DomainIds + // required: true + DomainIds []string `json:"domain_ids"` + // description: Operation of reduce + // required: false + // enum: union,merge + Operation string `json:"operation"` } type ConfigManagerGetTypesOutput struct { diff --git a/pkg/mcclient/modules/mod_notify.go b/pkg/mcclient/modules/mod_notify.go index 4da4f1eb44..63248073ca 100644 --- a/pkg/mcclient/modules/mod_notify.go +++ b/pkg/mcclient/modules/mod_notify.go @@ -35,7 +35,7 @@ func init() { NotifyReceiver = NewNotifyv2Manager( "receiver", "receivers", - []string{"ID", "Name", "Email", "International_Mobile", "Enabled_Contact_Types", "Verified_Infos"}, + []string{"ID", "Name", "Domain_Id", "Project_Domain", "Email", "International_Mobile", "Enabled_Contact_Types", "Verified_Infos"}, []string{}, ) register(&NotifyReceiver) diff --git a/pkg/mcclient/options/notify/receiver.go b/pkg/mcclient/options/notify/receiver.go index d4916ceb81..18c1a93b25 100644 --- a/pkg/mcclient/options/notify/receiver.go +++ b/pkg/mcclient/options/notify/receiver.go @@ -125,7 +125,8 @@ func (ri *ReceiverIntellijGetOptions) Params() (jsonutils.JSONObject, error) { } type ReceiverGetTypeOptions struct { - Domain string `help:"Domain under where available contact methods"` + DomainIds []string `help:"View the available notification channels for the domains with these DomainIds"` + Operation string `help:"Operation of reduce" choices:"merge|union"` } func (rg *ReceiverGetTypeOptions) Params() (jsonutils.JSONObject, error) { diff --git a/pkg/notify/models/config.go b/pkg/notify/models/config.go index 2ecd50334b..50157c49a8 100644 --- a/pkg/notify/models/config.go +++ b/pkg/notify/models/config.go @@ -63,7 +63,7 @@ type SConfig struct { db.SStandaloneResourceBase db.SDomainizedResourceBase - Type string `width:"15" nullable:"false" create:"required" get:"domain" list:"domain"` + Type string `width:"15" nullable:"false" create:"required" get:"domain" list:"domain" index:"true"` Content jsonutils.JSONObject `nullable:"false" create:"required" update:"domain" get:"domain" list:"domain"` Attribution string `width:"8" nullable:"false" default:"system" get:"domain" list:"domain" create:"optional"` } @@ -234,6 +234,16 @@ func sortContactType(ctypes []string) []string { return ret } +func (cm *SConfigManager) contactTypesQuery(domainId string) *sqlchemy.SQuery { + q := cm.Query("type").Distinct() + if domainId == "" { + q = q.Equals("attribution", api.CONFIG_ATTRIBUTION_SYSTEM) + } else { + q = q.Filter(sqlchemy.OR(sqlchemy.AND(sqlchemy.Equals(q.Field("attribution"), api.CONFIG_ATTRIBUTION_DOMAIN), sqlchemy.Equals(q.Field("domain_id"), domainId)), sqlchemy.Equals(q.Field("attribution"), api.CONFIG_ATTRIBUTION_SYSTEM))) + } + return q +} + func (cm *SConfigManager) availableContactTypes(domainId string) ([]string, error) { q := cm.Query("type") q = q.Filter(sqlchemy.OR(sqlchemy.AND(sqlchemy.Equals(q.Field("attribution"), api.CONFIG_ATTRIBUTION_DOMAIN), sqlchemy.Equals(q.Field("domain_id"), domainId)), sqlchemy.Equals(q.Field("attribution"), api.CONFIG_ATTRIBUTION_SYSTEM))) diff --git a/pkg/notify/models/receiver.go b/pkg/notify/models/receiver.go index 487584df0b..c4dc01b5cb 100644 --- a/pkg/notify/models/receiver.go +++ b/pkg/notify/models/receiver.go @@ -695,16 +695,58 @@ func (r *SReceiverManager) AllowPerformGetTypes(ctx context.Context, userCred mc func (rm *SReceiverManager) PerformGetTypes(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ConfigManagerGetTypesInput) (api.ConfigManagerGetTypesOutput, error) { output := api.ConfigManagerGetTypesOutput{} - t, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, input.Domain) - if err != nil { - return output, errors.Wrap(err, "unable to FetchDomainByIdOrName") + var reduce func([]*sqlchemy.SQuery) *sqlchemy.SQuery + var err error + switch input.Operation { + case "", "merge": + reduce = func(qs []*sqlchemy.SQuery) *sqlchemy.SQuery { + q := qs[0] + for i := 1; i < len(qs); i++ { + q = q.In("type", qs[i]) + } + return q + } + case "union": + reduce = func(qs []*sqlchemy.SQuery) *sqlchemy.SQuery { + if len(qs) == 1 { + return qs[0] + } + iqs := make([]sqlchemy.IQuery, 0, len(qs)) + for i := range qs { + iqs = append(iqs, qs[i]) + } + union, _ := sqlchemy.UnionWithError(iqs...) + if err != nil { + } + return union.Query() + } + default: + return output, httperrors.NewInputParameterError("unkown operation %q", input.Operation) } - ret, err := ConfigManager.availableContactTypes(t.Id) - if err != nil { - return output, errors.Wrap(err, "unable to get available contact types") + domainIds := sets.NewString(input.DomainIds...).UnsortedList() + qs := make([]*sqlchemy.SQuery, 0, len(domainIds)) + if len(domainIds) == 0 { + qs = append(qs, ConfigManager.contactTypesQuery("")) + } else { + for i := range domainIds { + ctypeQ := ConfigManager.contactTypesQuery(domainIds[i]) + qs = append(qs, ctypeQ) + } } - - output.Types = sortContactType(ret) + q := reduce(qs) + q.DebugQuery() + allTypes := make([]struct { + Type string + }, 0, 3) + err = q.All(&allTypes) + if err != nil { + return output, err + } + ret := make([]string, len(allTypes)) + for i := range ret { + ret[i] = allTypes[i].Type + } + output.Types = ret return output, nil }