github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/create/create_etc_hosts.go (about) 1 package create 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/url" 7 "strings" 8 9 "github.com/olli-ai/jx/v2/pkg/cmd/create/options" 10 11 "github.com/olli-ai/jx/v2/pkg/cmd/helper" 12 13 "github.com/olli-ai/jx/v2/pkg/kube/services" 14 15 "github.com/jenkins-x/jx-logging/pkg/log" 16 "github.com/olli-ai/jx/v2/pkg/cmd/opts" 17 "github.com/olli-ai/jx/v2/pkg/cmd/templates" 18 "github.com/olli-ai/jx/v2/pkg/util" 19 "github.com/spf13/cobra" 20 ) 21 22 const ( 23 optionName = "name" 24 ) 25 26 var ( 27 create_etc_hosts_long = templates.LongDesc(` 28 Creates /etc/hosts entries for all current exposed services 29 `) 30 31 create_etc_hosts_example = templates.Examples(` 32 # Creates /etc/hosts entries for all current exposed services 33 sudo jx create etc-hosts 34 `) 35 ) 36 37 // CreateEtcHostsOptions the options for the create spring command 38 type CreateEtcHostsOptions struct { 39 options.CreateOptions 40 41 Name string 42 IP string 43 } 44 45 // NewCmdCreateEtcHosts creates a command object for the "create" command 46 func NewCmdCreateEtcHosts(commonOpts *opts.CommonOptions) *cobra.Command { 47 options := &CreateEtcHostsOptions{ 48 CreateOptions: options.CreateOptions{ 49 CommonOptions: commonOpts, 50 }, 51 } 52 53 cmd := &cobra.Command{ 54 Use: "etc-hosts kind [url]", 55 Short: "Creates a new Git server URL", 56 Aliases: []string{"etchosts", "etc_hosts"}, 57 Long: create_etc_hosts_long, 58 Example: create_etc_hosts_example, 59 Run: func(cmd *cobra.Command, args []string) { 60 options.Cmd = cmd 61 options.Args = args 62 err := options.Run() 63 helper.CheckErr(err) 64 }, 65 } 66 67 cmd.Flags().StringVarP(&options.Name, optionName, "n", "/etc/hosts", "The etc hosts file to edit") 68 cmd.Flags().StringVarP(&options.IP, "ip", "i", "", "The IP address of the node to point the host entries to") 69 return cmd 70 } 71 72 // Run implements the command 73 func (o *CreateEtcHostsOptions) Run() error { 74 name := o.Name 75 if name == "" { 76 return util.MissingOption(name) 77 } 78 client, ns, err := o.KubeClientAndNamespace() 79 if err != nil { 80 return err 81 } 82 urls, err := services.FindServiceURLs(client, ns) 83 if err != nil { 84 return err 85 } 86 exists, err := util.FileExists(name) 87 if err != nil { 88 return err 89 } 90 if !exists { 91 return fmt.Errorf("hosts file %s does not exist!", name) 92 } 93 data, err := ioutil.ReadFile(name) 94 if err != nil { 95 return err 96 } 97 text := string(data) 98 lines := strings.Split(text, "\n") 99 idx, ipLine := o.findIPLine(&lines) 100 for _, u := range urls { 101 ipLine = o.addUrl(u, ipLine) 102 } 103 lines[idx] = ipLine 104 newText := strings.Join(lines, "\n") 105 if newText != text { 106 err = ioutil.WriteFile(name, []byte(newText), util.DefaultWritePermissions) 107 if err != nil { 108 return err 109 } 110 log.Logger().Infof("Updated file %s", util.ColorInfo(name)) 111 } 112 return nil 113 } 114 115 func (o *CreateEtcHostsOptions) addUrl(serviceUrl services.ServiceURL, ipLine string) string { 116 text := serviceUrl.URL 117 u, err := url.Parse(text) 118 if err != nil { 119 log.Logger().Warnf("Ignored invalid URL %s %s", text, err) 120 return ipLine 121 } 122 host := u.Host 123 fields := strings.Fields(ipLine) 124 for i := 1; i < len(fields); i++ { 125 if fields[i] == host { 126 return ipLine 127 } 128 } 129 if !strings.HasSuffix(ipLine, " ") { 130 ipLine += " " 131 } 132 return ipLine + host 133 } 134 135 func (o *CreateEtcHostsOptions) findIPLine(lines *[]string) (int, string) { 136 prefix := o.IP + " " 137 for i, line := range *lines { 138 if strings.HasPrefix(line, prefix) { 139 return i, line 140 } 141 } 142 143 idx := len(*lines) + 2 144 *lines = append(*lines, "", "# jx added services entries", prefix) 145 return idx, prefix 146 147 }