secrets.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. Copyright 2020 Docker Compose CLI authors
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cmd
  14. import (
  15. "fmt"
  16. "io"
  17. "io/ioutil"
  18. "os"
  19. "github.com/spf13/cobra"
  20. "github.com/docker/compose-cli/api/client"
  21. "github.com/docker/compose-cli/api/secrets"
  22. "github.com/docker/compose-cli/formatter"
  23. )
  24. // SecretCommand manage secrets
  25. func SecretCommand() *cobra.Command {
  26. cmd := &cobra.Command{
  27. Use: "secret",
  28. Short: "Manages secrets",
  29. }
  30. cmd.AddCommand(
  31. createSecret(),
  32. inspectSecret(),
  33. listSecrets(),
  34. deleteSecret(),
  35. )
  36. return cmd
  37. }
  38. func createSecret() *cobra.Command {
  39. cmd := &cobra.Command{
  40. Use: "create [OPTIONS] SECRET [file|-]",
  41. Short: "Creates a secret.",
  42. Args: cobra.RangeArgs(1, 2),
  43. RunE: func(cmd *cobra.Command, args []string) error {
  44. c, err := client.New(cmd.Context())
  45. if err != nil {
  46. return err
  47. }
  48. file := "-"
  49. if len(args) == 2 {
  50. file = args[1]
  51. }
  52. if len(file) == 0 {
  53. return fmt.Errorf("secret data source empty: %q", file)
  54. }
  55. var in io.ReadCloser
  56. switch file {
  57. case "-":
  58. in = os.Stdin
  59. default:
  60. in, err = os.Open(file)
  61. if err != nil {
  62. return err
  63. }
  64. defer func() { _ = in.Close() }()
  65. }
  66. content, err := ioutil.ReadAll(in)
  67. if err != nil {
  68. return fmt.Errorf("failed to read content from %q: %v", file, err)
  69. }
  70. name := args[0]
  71. secret := secrets.NewSecret(name, content)
  72. id, err := c.SecretsService().CreateSecret(cmd.Context(), secret)
  73. if err != nil {
  74. return err
  75. }
  76. fmt.Println(id)
  77. return nil
  78. },
  79. }
  80. return cmd
  81. }
  82. func inspectSecret() *cobra.Command {
  83. cmd := &cobra.Command{
  84. Use: "inspect ID",
  85. Short: "Displays secret details",
  86. Args: cobra.ExactArgs(1),
  87. RunE: func(cmd *cobra.Command, args []string) error {
  88. c, err := client.New(cmd.Context())
  89. if err != nil {
  90. return err
  91. }
  92. secret, err := c.SecretsService().InspectSecret(cmd.Context(), args[0])
  93. if err != nil {
  94. return err
  95. }
  96. out, err := secret.ToJSON()
  97. if err != nil {
  98. return err
  99. }
  100. fmt.Println(out)
  101. return nil
  102. },
  103. }
  104. return cmd
  105. }
  106. type listSecretsOpts struct {
  107. format string
  108. quiet bool
  109. }
  110. func listSecrets() *cobra.Command {
  111. var opts listSecretsOpts
  112. cmd := &cobra.Command{
  113. Use: "list",
  114. Aliases: []string{"ls"},
  115. Short: "List secrets stored for the existing account.",
  116. RunE: func(cmd *cobra.Command, args []string) error {
  117. c, err := client.New(cmd.Context())
  118. if err != nil {
  119. return err
  120. }
  121. secretsList, err := c.SecretsService().ListSecrets(cmd.Context())
  122. if err != nil {
  123. return err
  124. }
  125. if opts.quiet {
  126. for _, s := range secretsList {
  127. fmt.Println(s.ID)
  128. }
  129. return nil
  130. }
  131. view := viewFromSecretList(secretsList)
  132. return formatter.Print(view, opts.format, os.Stdout, func(w io.Writer) {
  133. for _, secret := range view {
  134. _, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", secret.ID, secret.Name, secret.Description)
  135. }
  136. }, "ID", "NAME")
  137. },
  138. }
  139. cmd.Flags().StringVar(&opts.format, "format", "", "Format the output. Values: [pretty | json]. (Default: pretty)")
  140. cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Only display IDs")
  141. return cmd
  142. }
  143. type secretView struct {
  144. ID string
  145. Name string
  146. Description string
  147. }
  148. func viewFromSecretList(secretList []secrets.Secret) []secretView {
  149. retList := make([]secretView, len(secretList))
  150. for i, s := range secretList {
  151. retList[i] = secretView{
  152. ID: s.ID,
  153. Name: s.Name,
  154. }
  155. }
  156. return retList
  157. }
  158. type deleteSecretOptions struct {
  159. recover bool
  160. }
  161. func deleteSecret() *cobra.Command {
  162. opts := deleteSecretOptions{}
  163. cmd := &cobra.Command{
  164. Use: "delete NAME",
  165. Aliases: []string{"rm", "remove"},
  166. Short: "Removes a secret.",
  167. Args: cobra.ExactArgs(1),
  168. RunE: func(cmd *cobra.Command, args []string) error {
  169. c, err := client.New(cmd.Context())
  170. if err != nil {
  171. return err
  172. }
  173. return c.SecretsService().DeleteSecret(cmd.Context(), args[0], opts.recover)
  174. },
  175. }
  176. cmd.Flags().BoolVar(&opts.recover, "recover", false, "Enable recovery.")
  177. return cmd
  178. }