roles.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // Copyright Joyent, Inc.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package main
  7. //lint:file-ignore U1000 WIP
  8. import (
  9. "bytes"
  10. "errors"
  11. "fmt"
  12. "net/url"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "time"
  17. "github.com/gofrs/uuid"
  18. "github.com/jawher/mow.cli"
  19. "github.com/olekukonko/tablewriter"
  20. )
  21. type RackRoles struct {
  22. *Conch
  23. }
  24. func (c *Conch) RackRoles() *RackRoles {
  25. return &RackRoles{c}
  26. }
  27. /****/
  28. type RackRoleList []RackRole
  29. func (r RackRoleList) Len() int {
  30. return len(r)
  31. }
  32. func (r RackRoleList) Swap(i, j int) {
  33. r[i], r[j] = r[j], r[i]
  34. }
  35. func (r RackRoleList) Less(i, j int) bool {
  36. return r[i].Name < r[j].Name
  37. }
  38. /****/
  39. type RackRole struct {
  40. ID uuid.UUID `json:"id"`
  41. Name string `json:"name"`
  42. RackSize int `json:"rack_size"`
  43. Created time.Time `json:"created"`
  44. Updated time.Time `json:"updated"`
  45. }
  46. func (rl RackRoleList) String() string {
  47. sort.Sort(rl)
  48. if API.JsonOnly {
  49. return API.AsJSON(rl)
  50. }
  51. tableString := &strings.Builder{}
  52. table := tablewriter.NewWriter(tableString)
  53. TableToMarkdown(table)
  54. table.SetHeader([]string{
  55. "Name",
  56. "RackSize",
  57. "Created",
  58. "Updated",
  59. })
  60. for _, r := range rl {
  61. table.Append([]string{
  62. r.Name,
  63. strconv.Itoa(r.RackSize),
  64. TimeStr(r.Created),
  65. TimeStr(r.Updated),
  66. })
  67. }
  68. table.Render()
  69. return tableString.String()
  70. }
  71. func (r RackRole) String() string {
  72. if API.JsonOnly {
  73. return API.AsJSON(r)
  74. }
  75. t, err := NewTemplate().Parse(rackRoleTemplate)
  76. if err != nil {
  77. panic(err)
  78. }
  79. buf := new(bytes.Buffer)
  80. if err := t.Execute(buf, r); err != nil {
  81. panic(err)
  82. }
  83. return buf.String()
  84. }
  85. /****/
  86. func (r *RackRoles) GetAll() RackRoleList {
  87. rl := make(RackRoleList, 0)
  88. res := r.Do(r.Sling().Get("/rack_role"))
  89. if ok := res.Parse(&rl); !ok {
  90. panic(res)
  91. }
  92. return rl
  93. }
  94. func (r *RackRoles) Get(id uuid.UUID) RackRole {
  95. var role RackRole
  96. uri := fmt.Sprintf(
  97. "/rack_role/%s",
  98. url.PathEscape(id.String()),
  99. )
  100. res := r.Do(r.Sling().Get(uri))
  101. if ok := res.Parse(&role); !ok {
  102. panic(res)
  103. }
  104. return role
  105. }
  106. func (r *RackRoles) GetByName(name string) RackRole {
  107. var role RackRole
  108. uri := fmt.Sprintf(
  109. "/rack_role/name=%s",
  110. url.PathEscape(name),
  111. )
  112. res := r.Do(r.Sling().Get(uri))
  113. if ok := res.Parse(&role); !ok {
  114. panic(res)
  115. }
  116. return role
  117. }
  118. func (r *RackRoles) FindID(name string) (bool, uuid.UUID) {
  119. var role RackRole
  120. uri := fmt.Sprintf(
  121. "/rack_role/name=%s",
  122. url.PathEscape(name),
  123. )
  124. res := r.DoBadly(r.Sling().Get(uri))
  125. if res.IsError() {
  126. return false, uuid.UUID{}
  127. }
  128. return res.Parse(&role), role.ID
  129. }
  130. func (r *RackRoles) Create(name string, rackSize int) RackRole {
  131. if name == "" {
  132. panic(errors.New("'name' is required"))
  133. }
  134. if rackSize == 0 {
  135. panic(errors.New("'rackSize' is required and cannot be 0"))
  136. }
  137. payload := make(map[string]interface{})
  138. payload["name"] = name
  139. payload["rack_size"] = rackSize
  140. var role RackRole
  141. // We get a 303 on success
  142. res := r.Do(
  143. r.Sling().New().Post("/rack_role").
  144. Set("Content-Type", "application/json").
  145. BodyJSON(payload),
  146. )
  147. if ok := res.Parse(&role); !ok {
  148. panic(res)
  149. }
  150. return role
  151. }
  152. func (r *RackRoles) Update(id uuid.UUID, newName string, rackSize int) RackRole {
  153. payload := make(map[string]interface{})
  154. if newName != "" {
  155. payload["name"] = newName
  156. }
  157. if rackSize > 0 {
  158. payload["rack_size"] = rackSize
  159. }
  160. var role RackRole
  161. uri := fmt.Sprintf(
  162. "/rack_role/%s",
  163. url.PathEscape(id.String()),
  164. )
  165. // We get a 303 on success
  166. res := r.Do(
  167. r.Sling().New().Post(uri).
  168. Set("Content-Type", "application/json").
  169. BodyJSON(payload),
  170. )
  171. if ok := res.Parse(&role); !ok {
  172. panic(res)
  173. }
  174. return role
  175. }
  176. func (r *RackRoles) Delete(id uuid.UUID) {
  177. uri := fmt.Sprintf("/rack_role/%s", url.PathEscape(id.String()))
  178. res := r.Do(r.Sling().New().Delete(uri))
  179. if res.StatusCode() != 204 {
  180. // I know this is weird. Like in other places, it should be impossible
  181. // to reach here unless the status code is 204. The API returns 204
  182. // (which gets us here) or 409 (which will explode before it gets here).
  183. // If we got here via some other code, then there's some new behavior
  184. // that we need to know about.
  185. panic(res)
  186. }
  187. }
  188. /****/
  189. func init() {
  190. App.Command("roles", "Work with datacenter rack roles", func(cmd *cli.Cmd) {
  191. cmd.Before = RequireSysAdmin
  192. cmd.Command("get", "Get a list of all rack roles", func(cmd *cli.Cmd) {
  193. cmd.Action = func() { fmt.Println(API.RackRoles().GetAll()) }
  194. })
  195. cmd.Command("create", "Create a new rack role", func(cmd *cli.Cmd) {
  196. var (
  197. nameOpt = cmd.StringOpt("name", "", "The name of the role")
  198. rackSizeOpt = cmd.IntOpt("rack-size", 0, "Size of the rack necessary for this role")
  199. )
  200. cmd.Spec = "--name --rack-size"
  201. cmd.Action = func() {
  202. if *nameOpt == "" {
  203. panic(errors.New("--name is required"))
  204. }
  205. if *rackSizeOpt == 0 {
  206. panic(errors.New("--rack-size is required and cannot be 0"))
  207. }
  208. fmt.Println(API.RackRoles().Create(*nameOpt, *rackSizeOpt))
  209. }
  210. })
  211. })
  212. App.Command("role", "Work with a single rack role", func(cmd *cli.Cmd) {
  213. var roleID uuid.UUID
  214. nameArg := cmd.StringArg(
  215. "NAME",
  216. "",
  217. "The name of the rack role",
  218. )
  219. cmd.Spec = "NAME"
  220. cmd.Before = func() {
  221. RequireSysAdmin()
  222. var ok bool
  223. if ok, roleID = API.RackRoles().FindID(*nameArg); !ok {
  224. panic(errors.New("could not find the role"))
  225. }
  226. }
  227. cmd.Command("get", "Get information about a single rack role", func(cmd *cli.Cmd) {
  228. cmd.Action = func() { fmt.Println(API.RackRoles().Get(roleID)) }
  229. })
  230. cmd.Command("update", "Update information about a single rack role", func(cmd *cli.Cmd) {
  231. var (
  232. nameOpt = cmd.StringOpt("name", "", "The name of the role")
  233. rackSizeOpt = cmd.IntOpt("rack-size", 0, "Size of the rack necessary for this role")
  234. )
  235. cmd.Action = func() {
  236. fmt.Println(API.RackRoles().Update(roleID, *nameOpt, *rackSizeOpt))
  237. }
  238. })
  239. cmd.Command("delete", "Delete a single rack role", func(cmd *cli.Cmd) {
  240. cmd.Action = func() {
  241. API.RackRoles().Delete(roleID)
  242. fmt.Println(API.RackRoles().GetAll())
  243. }
  244. })
  245. })
  246. }