docker.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package cmd
  2. import (
  3. "context"
  4. "encoding/json"
  5. "io/ioutil"
  6. "net/url"
  7. "os"
  8. "os/exec"
  9. "path/filepath"
  10. "strings"
  11. "github.com/fatih/color"
  12. "github.com/porter-dev/porter/cli/cmd/api"
  13. "github.com/porter-dev/porter/cli/cmd/github"
  14. "github.com/spf13/cobra"
  15. "github.com/docker/cli/cli/config/configfile"
  16. )
  17. var dockerCmd = &cobra.Command{
  18. Use: "docker",
  19. Short: "Commands to configure Docker for a project",
  20. }
  21. var configureCmd = &cobra.Command{
  22. Use: "configure",
  23. Short: "Configures the host's Docker instance",
  24. Run: func(cmd *cobra.Command, args []string) {
  25. err := checkLoginAndRun(args, dockerConfig)
  26. if err != nil {
  27. os.Exit(1)
  28. }
  29. },
  30. }
  31. func init() {
  32. rootCmd.AddCommand(dockerCmd)
  33. dockerCmd.AddCommand(configureCmd)
  34. }
  35. func dockerConfig(user *api.AuthCheckResponse, client *api.Client, args []string) error {
  36. pID := getProjectID()
  37. // get all registries that should be added
  38. regToAdd := make([]string, 0)
  39. // get the list of namespaces
  40. registries, err := client.ListRegistries(
  41. context.Background(),
  42. pID,
  43. )
  44. if err != nil {
  45. return err
  46. }
  47. for _, registry := range registries {
  48. if registry.URL != "" {
  49. rURL := registry.URL
  50. if !strings.Contains(rURL, "http") {
  51. rURL = "http://" + rURL
  52. }
  53. // strip the protocol
  54. regURL, err := url.Parse(rURL)
  55. if err != nil {
  56. continue
  57. }
  58. regToAdd = append(regToAdd, regURL.Host)
  59. }
  60. }
  61. dockerConfigFile := filepath.Join(home, ".docker", "config.json")
  62. // determine if configfile exists
  63. if info, err := os.Stat(dockerConfigFile); info.IsDir() || os.IsNotExist(err) {
  64. // if it does not exist, create it
  65. err := ioutil.WriteFile(dockerConfigFile, []byte("{}"), 0700)
  66. if err != nil {
  67. return err
  68. }
  69. }
  70. // read the file bytes
  71. configBytes, err := ioutil.ReadFile(dockerConfigFile)
  72. if err != nil {
  73. return err
  74. }
  75. // check if the docker credential helper exists
  76. if !commandExists("docker-credential-porter") {
  77. err := downloadCredMatchingRelease()
  78. if err != nil {
  79. color.New(color.FgRed).Println("Failed to download credential helper binary:", err.Error())
  80. os.Exit(1)
  81. }
  82. }
  83. // otherwise, check the version flag of the binary
  84. cmdVersionCred := exec.Command("docker-credential-porter", "--version")
  85. writer := &versionWriter{}
  86. cmdVersionCred.Stdout = writer
  87. err = cmdVersionCred.Run()
  88. if err != nil || writer.Version != Version {
  89. err := downloadCredMatchingRelease()
  90. if err != nil {
  91. color.New(color.FgRed).Println("Failed to download credential helper binary:", err.Error())
  92. os.Exit(1)
  93. }
  94. }
  95. config := &configfile.ConfigFile{
  96. Filename: dockerConfigFile,
  97. }
  98. err = json.Unmarshal(configBytes, config)
  99. if err != nil {
  100. return err
  101. }
  102. for _, regURL := range regToAdd {
  103. config.CredentialHelpers[regURL] = "porter"
  104. }
  105. return config.Save()
  106. }
  107. func downloadCredMatchingRelease() error {
  108. // download the porter cred helper
  109. z := &github.ZIPReleaseGetter{
  110. AssetName: "docker-credential-porter",
  111. AssetFolderDest: "/usr/local/bin",
  112. ZipFolderDest: filepath.Join(home, ".porter"),
  113. ZipName: "docker-credential-porter_latest.zip",
  114. EntityID: "porter-dev",
  115. RepoName: "porter",
  116. IsPlatformDependent: true,
  117. }
  118. return z.GetRelease(Version)
  119. }
  120. func commandExists(cmd string) bool {
  121. _, err := exec.LookPath(cmd)
  122. return err == nil
  123. }