start.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. package cmd
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "github.com/porter-dev/porter/cli/cmd/docker"
  7. "k8s.io/client-go/util/homedir"
  8. "github.com/porter-dev/porter/cli/cmd/credstore"
  9. "github.com/spf13/cobra"
  10. "github.com/docker/docker/api/types/mount"
  11. )
  12. type startOps struct {
  13. insecure *bool
  14. skipKubeconfig *bool
  15. kubeconfigPath string
  16. contexts *[]string
  17. imageTag string `form:"required"`
  18. db string `form:"oneof=sqlite memory postgres"`
  19. }
  20. var opts = &startOps{}
  21. // startCmd represents the start command
  22. var startCmd = &cobra.Command{
  23. Args: func(cmd *cobra.Command, args []string) error {
  24. return nil
  25. },
  26. Use: "start",
  27. Short: "Starts a Porter instance using the Docker engine.",
  28. Run: func(cmd *cobra.Command, args []string) {
  29. closeHandler(stop)
  30. err := start(
  31. opts.imageTag,
  32. opts.kubeconfigPath,
  33. opts.db,
  34. *opts.contexts,
  35. *opts.insecure,
  36. *opts.skipKubeconfig,
  37. )
  38. if err != nil {
  39. fmt.Println("Error running start:", err.Error())
  40. os.Exit(1)
  41. }
  42. },
  43. }
  44. func init() {
  45. // closeHandler(stop)
  46. rootCmd.AddCommand(startCmd)
  47. opts.insecure = startCmd.PersistentFlags().Bool(
  48. "insecure",
  49. false,
  50. "skip admin setup and authorization",
  51. )
  52. opts.skipKubeconfig = startCmd.PersistentFlags().Bool(
  53. "skip-kubeconfig",
  54. false,
  55. "skip initialization of the kubeconfig",
  56. )
  57. opts.contexts = startCmd.PersistentFlags().StringArray(
  58. "contexts",
  59. nil,
  60. "the list of contexts to use (defaults to the current context)",
  61. )
  62. startCmd.PersistentFlags().StringVar(
  63. &opts.db,
  64. "db",
  65. "sqlite",
  66. "the db to use",
  67. )
  68. startCmd.PersistentFlags().StringVar(
  69. &opts.kubeconfigPath,
  70. "kubeconfig",
  71. "",
  72. "path to kubeconfig",
  73. )
  74. startCmd.PersistentFlags().StringVar(
  75. &opts.imageTag,
  76. "image-tag",
  77. "latest",
  78. "the Porter image tag to use",
  79. )
  80. }
  81. func stop() error {
  82. agent, err := docker.NewAgentFromEnv()
  83. if err != nil {
  84. return err
  85. }
  86. err = agent.StopPorterContainers()
  87. if err != nil {
  88. return err
  89. }
  90. return nil
  91. }
  92. func start(
  93. imageTag string,
  94. kubeconfigPath string,
  95. db string,
  96. contexts []string,
  97. insecure bool,
  98. skipKubeconfig bool,
  99. ) error {
  100. var username, pw string
  101. var err error
  102. home := homedir.HomeDir()
  103. outputConfPath := filepath.Join(home, ".porter", "porter.kubeconfig")
  104. containerConfPath := "/porter/porter.kubeconfig"
  105. // if not insecure, or username/pw set incorrectly, prompt for new username/pw
  106. if username, pw, err = credstore.Get(); !insecure && err != nil {
  107. username, err = promptPlaintext("Email: ")
  108. if err != nil {
  109. return err
  110. }
  111. pw, err = promptPasswordWithConfirmation()
  112. if err != nil {
  113. return err
  114. }
  115. credstore.Set(username, pw)
  116. }
  117. if !skipKubeconfig {
  118. err = generate(
  119. kubeconfigPath,
  120. outputConfPath,
  121. false,
  122. contexts,
  123. )
  124. if err != nil {
  125. return err
  126. }
  127. }
  128. agent, err := docker.NewAgentFromEnv()
  129. if err != nil {
  130. return err
  131. }
  132. // the volume mounts to use
  133. mounts := make([]mount.Mount, 0)
  134. // the volumes passed to the Porter container
  135. volumesMap := make(map[string]struct{})
  136. if !skipKubeconfig {
  137. // add a bind mount with the kubeconfig
  138. mount := mount.Mount{
  139. Type: mount.TypeBind,
  140. Source: outputConfPath,
  141. Target: containerConfPath,
  142. ReadOnly: true,
  143. Consistency: mount.ConsistencyFull,
  144. }
  145. mounts = append(mounts, mount)
  146. }
  147. switch db {
  148. case "sqlite":
  149. // check if sqlite volume exists, create it if not
  150. vol, err := agent.CreateLocalVolumeIfNotExist("porter_sqlite")
  151. if err != nil {
  152. return err
  153. }
  154. // create mount
  155. mount := mount.Mount{
  156. Type: mount.TypeVolume,
  157. Source: vol.Name,
  158. Target: "/sqlite",
  159. ReadOnly: false,
  160. Consistency: mount.ConsistencyFull,
  161. }
  162. mounts = append(mounts, mount)
  163. volumesMap[vol.Name] = struct{}{}
  164. case "postgres":
  165. // check if postgres volume exists, create it if not
  166. vol, err := agent.CreateLocalVolumeIfNotExist("porter_postgres")
  167. if err != nil {
  168. return err
  169. }
  170. // pgMount is mount for postgres container
  171. pgMount := []mount.Mount{
  172. mount.Mount{
  173. Type: mount.TypeVolume,
  174. Source: vol.Name,
  175. Target: "/var/lib/postgresql/data",
  176. ReadOnly: false,
  177. Consistency: mount.ConsistencyFull,
  178. },
  179. }
  180. // create postgres container with mount
  181. // TODO
  182. fmt.Println(pgMount)
  183. }
  184. // create Porter container
  185. // TODO -- look for unused port
  186. startOpts := docker.PorterStartOpts{
  187. Name: "porter_server",
  188. Image: "porter1/porter:" + imageTag,
  189. HostPort: 8080,
  190. ContainerPort: 8080,
  191. Mounts: mounts,
  192. VolumeMap: volumesMap,
  193. Env: []string{
  194. "QUICK_START=true",
  195. "SQL_LITE_PATH=/sqlite/porter.db",
  196. },
  197. }
  198. return agent.StartPorterContainerAndWait(startOpts)
  199. }