sdk.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 misc
  15. import (
  16. "fmt"
  17. "io/ioutil"
  18. "os"
  19. "strings"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/utils"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. "yunion.io/x/onecloud/pkg/mcclient/modulebase"
  26. )
  27. func init() {
  28. type SdkGenerateOptions struct {
  29. SERVICE string `help:"Service type" choices:"compute|report|meter|cloudid|yunionconf|yunionagent"`
  30. SDK_PATH string
  31. }
  32. R(&SdkGenerateOptions{}, "generate-python-sdk", "generate python sdk mod", func(s *mcclient.ClientSession, args *SdkGenerateOptions) error {
  33. keywords := []string{"quota", "usage"}
  34. path := fmt.Sprintf("%s/yunionclient/api", args.SDK_PATH)
  35. files, err := os.ReadDir(path)
  36. if err != nil {
  37. return errors.Wrapf(err, "read sdk path %s", path)
  38. }
  39. for i := range files {
  40. if files[i].IsDir() {
  41. continue
  42. }
  43. data, _ := ioutil.ReadFile(fmt.Sprintf("%s/%s", path, files[i].Name()))
  44. lines := strings.Split(string(data), "\n")
  45. for _, line := range lines {
  46. if strings.Contains(line, "keyword ") {
  47. info := strings.Split(line, "=")
  48. if len(info) == 2 {
  49. keyword := strings.Trim(info[1], " ")
  50. keyword = strings.ReplaceAll(keyword, "'", "")
  51. keyword = strings.ReplaceAll(keyword, `"`, "")
  52. keywords = append(keywords, keyword)
  53. }
  54. }
  55. }
  56. }
  57. template := `from yunionclient.common import base
  58. class %s(base.ResourceBase):
  59. pass
  60. class %sManager(base.%sManager):
  61. resource_class = %s
  62. keyword = '%s'
  63. keyword_plural = '%s'
  64. _columns = %s`
  65. shellTemplate := `import yunionclient
  66. from yunionclient.common import utils
  67. @utils.arg('--limit', metavar='<NUMBER>', default=20, help='Page limit')
  68. @utils.arg('--offset', metavar='<OFFSET>', help='Page offset')
  69. @utils.arg('--order-by', metavar='<ORDER_BY>', help='Name of fields order by')
  70. @utils.arg('--order', metavar='<ORDER>', choices=['desc', 'asc'], help='order')
  71. @utils.arg('--details', action='store_true', help='More detailed list')
  72. @utils.arg('--search', metavar='<KEYWORD>', help='Filter result by simple keyword search')
  73. @utils.arg('--meta', action='store_true', help='Piggyback metadata')
  74. @utils.arg('--filter', metavar='<FILTER>', action='append', help='Filters')
  75. @utils.arg('--filter-any', action='store_true', help='If true, match if any of the filters matches; otherwise, match if all of the filters match')
  76. @utils.arg('--admin', action='store_true', help='Is admin call?')
  77. @utils.arg('--tenant', metavar='<TENANT>', help='Tenant ID or Name')
  78. @utils.arg('--field', metavar='<FIELD>', action='append', help='Show only specified fields')
  79. def do_%s_list(client, args):
  80. """ List all %s"""
  81. page_info = utils.get_paging_info(args)
  82. %s = client.%s.list(**page_info)
  83. utils.print_list(%s, client.%s.columns)`
  84. mods, _ := modulebase.GetRegisterdModules()
  85. invalidMods := []string{}
  86. imports, clients, shells := []string{}, []string{}, []string{}
  87. for i := range mods {
  88. mod, err := modulebase.GetModule(s, mods[i])
  89. if err != nil {
  90. invalidMods = append(invalidMods, mods[i])
  91. continue
  92. }
  93. if mod.ServiceType() != args.SERVICE {
  94. continue
  95. }
  96. if strings.Contains(mod.GetKeyword(), "-") {
  97. continue
  98. }
  99. manager := "Standalone"
  100. if args.SERVICE != "compute" {
  101. manager = utils.Capitalize(args.SERVICE)
  102. }
  103. if !utils.IsInStringArray(mod.GetKeyword(), keywords) {
  104. cls := utils.Kebab2Camel(mod.GetKeyword(), "_")
  105. columes := mod.GetColumns(s)
  106. data := fmt.Sprintf(template, cls, cls, manager, cls, mod.GetKeyword(), mod.KeyString(), jsonutils.Marshal(columes))
  107. filename := strings.ReplaceAll(mod.KeyString(), "_", "")
  108. filePath := fmt.Sprintf("%s/%s.py", path, filename)
  109. err := ioutil.WriteFile(filePath, []byte(data), 0644)
  110. if err != nil {
  111. log.Errorf("write %s error: %v", filePath, err)
  112. continue
  113. }
  114. log.Infof("mod %s generage...", mod.GetKeyword())
  115. imports = append(imports, fmt.Sprintf("from yunionclient.api import %s", filename))
  116. clients = append(clients, fmt.Sprintf(" self.%s = %s.%sManager(self)", filename, filename, cls))
  117. shell := fmt.Sprintf(shellTemplate, mod.GetKeyword(), strings.ReplaceAll(mod.KeyString(), "_", ""), filename, filename, filename, filename)
  118. filePath = fmt.Sprintf("%s/yunionclient/shells/%s.py", args.SDK_PATH, filename)
  119. err = ioutil.WriteFile(filePath, []byte(shell), 0644)
  120. if err != nil {
  121. log.Errorf("write %s error: %v", filePath, err)
  122. continue
  123. }
  124. shells = append(shells, fmt.Sprintf("from .%s import *", filename))
  125. }
  126. }
  127. clientPath := fmt.Sprintf("%s/client.py", path)
  128. data, err := ioutil.ReadFile(clientPath)
  129. if err != nil {
  130. return errors.Wrapf(err, "read client")
  131. }
  132. newLines := []string{}
  133. lines := strings.Split(string(data), "\n")
  134. isImport, isClient := false, false
  135. for i := len(lines) - 1; i >= 0; i-- {
  136. if !isImport && strings.HasPrefix(lines[i], "from") {
  137. newLines = append(imports, newLines...)
  138. isImport = true
  139. }
  140. if !isClient && strings.HasSuffix(lines[i], "Manager(self)") {
  141. isClient = true
  142. newLines = append(clients, newLines...)
  143. }
  144. newLines = append([]string{lines[i]}, newLines...)
  145. }
  146. err = ioutil.WriteFile(clientPath, []byte(strings.Join(newLines, "\n")), 0755)
  147. if err != nil {
  148. return errors.Wrapf(err, "write client")
  149. }
  150. shellPath := fmt.Sprintf("%s/yunionclient/shells/__init__.py", args.SDK_PATH)
  151. data, err = ioutil.ReadFile(shellPath)
  152. if err != nil {
  153. return errors.Wrapf(err, "read shell")
  154. }
  155. lines = strings.Split(string(data), "\n")
  156. lines = append(lines, shells...)
  157. return ioutil.WriteFile(shellPath, []byte(strings.Join(lines, "\n")), 0755)
  158. })
  159. }