dispatcher.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package handler
  15. import (
  16. "context"
  17. "fmt"
  18. "net/http"
  19. "reflect"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/gotypes"
  23. "yunion.io/x/pkg/util/printutils"
  24. "yunion.io/x/pkg/utils"
  25. "yunion.io/x/onecloud/pkg/appsrv"
  26. "yunion.io/x/onecloud/pkg/appsrv/dispatcher"
  27. "yunion.io/x/onecloud/pkg/cloudcommon/etcd"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/etcd/models/base"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/policy"
  30. "yunion.io/x/onecloud/pkg/httperrors"
  31. "yunion.io/x/onecloud/pkg/mcclient/auth"
  32. )
  33. func NewEtcdModelHandler(manger base.IEtcdModelManager) *SEtcdModelHandler {
  34. return &SEtcdModelHandler{
  35. manager: manger,
  36. }
  37. }
  38. type SEtcdModelHandler struct {
  39. manager base.IEtcdModelManager
  40. }
  41. func (disp *SEtcdModelHandler) Filter(f appsrv.FilterHandler) appsrv.FilterHandler {
  42. return auth.Authenticate(f)
  43. }
  44. func (disp *SEtcdModelHandler) Keyword() string {
  45. return disp.manager.Keyword()
  46. }
  47. func (disp *SEtcdModelHandler) KeywordPlural() string {
  48. return disp.manager.KeywordPlural()
  49. }
  50. func (disp *SEtcdModelHandler) ContextKeywordPlurals() [][]string {
  51. return nil
  52. }
  53. func (disp *SEtcdModelHandler) CustomizeHandlerInfo(handler *appsrv.SHandlerInfo) {
  54. disp.manager.CustomizeHandlerInfo(handler)
  55. }
  56. func (disp *SEtcdModelHandler) FetchCreateHeaderData(ctx context.Context, header http.Header) (jsonutils.JSONObject, error) {
  57. return disp.manager.FetchCreateHeaderData(ctx, header)
  58. }
  59. func (disp *SEtcdModelHandler) FetchUpdateHeaderData(ctx context.Context, header http.Header) (jsonutils.JSONObject, error) {
  60. return disp.manager.FetchUpdateHeaderData(ctx, header)
  61. }
  62. func (disp *SEtcdModelHandler) List(ctx context.Context, query jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (*printutils.ListResult, error) {
  63. objs, err := disp.manager.AllJson(ctx)
  64. if err != nil {
  65. return nil, httperrors.NewGeneralError(err)
  66. }
  67. return &printutils.ListResult{
  68. Data: objs,
  69. Total: len(objs),
  70. Limit: 0,
  71. Offset: 0,
  72. }, nil
  73. }
  74. func (disp *SEtcdModelHandler) Get(ctx context.Context, idstr string, query jsonutils.JSONObject, isHead bool) (jsonutils.JSONObject, error) {
  75. userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
  76. model := disp.manager.Allocate()
  77. err := disp.manager.Get(ctx, idstr, model)
  78. // obj, err := disp.manager.GetJson(ctx, idstr)
  79. if err != nil {
  80. if err != etcd.ErrNoSuchKey {
  81. return nil, httperrors.NewGeneralError(err)
  82. } else {
  83. return nil, httperrors.NewResourceNotFoundError("%s %s not found", disp.manager.Keyword(), idstr)
  84. }
  85. }
  86. appParams := appsrv.AppContextGetParams(ctx)
  87. if appParams == nil && isHead {
  88. log.Errorf("fail to get http response writer???")
  89. return nil, httperrors.NewInternalServerError("fail to get http response writer from context")
  90. }
  91. hdrs := model.GetExtraDetailsHeaders(ctx, userCred, query)
  92. for k, v := range hdrs {
  93. appParams.Response.Header().Add(k, v)
  94. }
  95. if isHead {
  96. appParams.Response.Header().Add("Content-Length", "0")
  97. appParams.Response.Write([]byte{})
  98. return nil, nil
  99. }
  100. return jsonutils.Marshal(model), nil
  101. }
  102. func (disp *SEtcdModelHandler) GetSpecific(ctx context.Context, idstr string, spec string, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  103. userCred := auth.FetchUserCredential(ctx, policy.FilterPolicyCredential)
  104. model := disp.manager.Allocate()
  105. err := disp.manager.Get(ctx, idstr, model)
  106. if err != nil {
  107. if err != etcd.ErrNoSuchKey {
  108. return nil, httperrors.NewGeneralError(err)
  109. } else {
  110. return nil, httperrors.NewResourceNotFoundError("%s %s not found", disp.manager.Keyword(), idstr)
  111. }
  112. }
  113. params := []reflect.Value{
  114. reflect.ValueOf(ctx),
  115. reflect.ValueOf(userCred),
  116. reflect.ValueOf(query),
  117. }
  118. specCamel := utils.Kebab2Camel(spec, "-")
  119. modelValue := reflect.ValueOf(model)
  120. funcName := fmt.Sprintf("GetDetails%s", specCamel)
  121. funcValue := modelValue.MethodByName(funcName)
  122. if !funcValue.IsValid() || funcValue.IsNil() {
  123. return nil, httperrors.NewSpecNotFoundError("%s %s %s not found", disp.Keyword(), idstr, spec)
  124. }
  125. outs := funcValue.Call(params)
  126. if len(outs) != 2 {
  127. return nil, httperrors.NewInternalServerError("Invald %s return value", funcName)
  128. }
  129. resVal := outs[0].Interface()
  130. errVal := outs[1].Interface()
  131. if !gotypes.IsNil(errVal) {
  132. return nil, errVal.(error)
  133. } else {
  134. if gotypes.IsNil(resVal) {
  135. return nil, nil
  136. } else {
  137. return resVal.(jsonutils.JSONObject), nil
  138. }
  139. }
  140. }
  141. func (disp *SEtcdModelHandler) Create(ctx context.Context, query jsonutils.JSONObject, data jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (jsonutils.JSONObject, error) {
  142. return nil, httperrors.NewNotImplementedError("not implemented")
  143. }
  144. func (disp *SEtcdModelHandler) BatchCreate(ctx context.Context, query jsonutils.JSONObject, data jsonutils.JSONObject, count int, ctxIds []dispatcher.SResourceContext) ([]printutils.SubmitResult, error) {
  145. return nil, httperrors.NewNotImplementedError("not implemented")
  146. }
  147. func (disp *SEtcdModelHandler) PerformClassAction(ctx context.Context, action string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  148. return nil, httperrors.NewNotImplementedError("not implemented")
  149. }
  150. func (disp *SEtcdModelHandler) PerformAction(ctx context.Context, idstr string, action string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  151. return nil, httperrors.NewNotImplementedError("not implemented")
  152. }
  153. func (disp *SEtcdModelHandler) Update(ctx context.Context, idstr string, query jsonutils.JSONObject, data jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (jsonutils.JSONObject, error) {
  154. return nil, httperrors.NewNotImplementedError("not implemented")
  155. }
  156. func (disp *SEtcdModelHandler) Delete(ctx context.Context, idstr string, query jsonutils.JSONObject, data jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (jsonutils.JSONObject, error) {
  157. return nil, httperrors.NewNotImplementedError("not implemented")
  158. }
  159. func (disp *SEtcdModelHandler) UpdateSpec(ctx context.Context, idstr string, spec string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  160. return nil, httperrors.NewNotImplementedError("not implemented")
  161. }
  162. func (disp *SEtcdModelHandler) DeleteSpec(ctx context.Context, idstr string, spec string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  163. return nil, httperrors.NewNotImplementedError("not implemented")
  164. }