1package loadbalancer 2 3import ( 4 "fmt" 5 6 "github.com/hetznercloud/cli/internal/cmd/cmpl" 7 "github.com/hetznercloud/cli/internal/cmd/util" 8 "github.com/hetznercloud/cli/internal/state" 9 "github.com/hetznercloud/hcloud-go/hcloud" 10 "github.com/spf13/cobra" 11) 12 13func newAddServiceCommand(cli *state.State) *cobra.Command { 14 cmd := &cobra.Command{ 15 Use: "add-service LOADBALANCER FLAGS", 16 Short: "Add a service from a Load Balancer", 17 Args: cobra.ExactArgs(1), 18 ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(cli.LoadBalancerNames)), 19 TraverseChildren: true, 20 DisableFlagsInUseLine: true, 21 PreRunE: util.ChainRunE(validateAddService, cli.EnsureToken), 22 RunE: cli.Wrap(runAddService), 23 } 24 cmd.Flags().String("protocol", "", "Protocol of the service (required)") 25 cmd.MarkFlagRequired("protocol") 26 27 cmd.Flags().Int("listen-port", 0, "Listen port of the service") 28 cmd.Flags().Int("destination-port", 0, "Destination port of the service on the targets") 29 cmd.Flags().Bool("proxy-protocol", false, "Enable proxyprotocol") 30 31 cmd.Flags().Bool("http-sticky-sessions", false, "Enable Sticky Sessions") 32 cmd.Flags().String("http-cookie-name", "", "Sticky Sessions: Cookie Name we set") 33 cmd.Flags().Duration("http-cookie-lifetime", 0, "Sticky Sessions: Lifetime of the cookie") 34 cmd.Flags().IntSlice("http-certificates", []int{}, "ID of Certificates which are attached to this Load Balancer") 35 cmd.Flags().Bool("http-redirect-http", false, "Redirect all traffic on port 80 to port 443") 36 37 return cmd 38} 39 40func validateAddService(cmd *cobra.Command, args []string) error { 41 protocol, _ := cmd.Flags().GetString("protocol") 42 listenPort, _ := cmd.Flags().GetInt("listen-port") 43 destinationPort, _ := cmd.Flags().GetInt("destination-port") 44 httpCertificates, _ := cmd.Flags().GetIntSlice("http-certificates") 45 46 if protocol == "" { 47 return fmt.Errorf("required flag protocol not set") 48 } 49 50 switch hcloud.LoadBalancerServiceProtocol(protocol) { 51 case hcloud.LoadBalancerServiceProtocolHTTP: 52 break 53 case hcloud.LoadBalancerServiceProtocolTCP: 54 if listenPort == 0 { 55 return fmt.Errorf("please specify a listen port") 56 } 57 58 if destinationPort == 0 { 59 return fmt.Errorf("please specify a destination port") 60 } 61 break 62 case hcloud.LoadBalancerServiceProtocolHTTPS: 63 if len(httpCertificates) == 0 { 64 return fmt.Errorf("no certificate specified") 65 } 66 default: 67 return fmt.Errorf("%s is not a valid protocol", protocol) 68 } 69 if listenPort > 65535 { 70 return fmt.Errorf("%d is not a valid listen port", listenPort) 71 } 72 73 if destinationPort > 65535 { 74 return fmt.Errorf("%d is not a valid destination port", destinationPort) 75 } 76 return nil 77} 78 79func runAddService(cli *state.State, cmd *cobra.Command, args []string) error { 80 idOrName := args[0] 81 protocol, _ := cmd.Flags().GetString("protocol") 82 listenPort, _ := cmd.Flags().GetInt("listen-port") 83 destinationPort, _ := cmd.Flags().GetInt("destination-port") 84 proxyProtocol, _ := cmd.Flags().GetBool("proxy-protocol") 85 86 httpStickySessions, _ := cmd.Flags().GetBool("http-sticky-sessions") 87 httpCookieName, _ := cmd.Flags().GetString("http-cookie-name") 88 httpCookieLifetime, _ := cmd.Flags().GetDuration("http-cookie-lifetime") 89 httpCertificates, _ := cmd.Flags().GetIntSlice("http-certificates") 90 httpRedirect, _ := cmd.Flags().GetBool("http-redirect-http") 91 92 loadBalancer, _, err := cli.Client().LoadBalancer.Get(cli.Context, idOrName) 93 if err != nil { 94 return err 95 } 96 if loadBalancer == nil { 97 return fmt.Errorf("Load Balancer not found: %s", idOrName) 98 } 99 100 opts := hcloud.LoadBalancerAddServiceOpts{ 101 Protocol: hcloud.LoadBalancerServiceProtocol(protocol), 102 Proxyprotocol: hcloud.Bool(proxyProtocol), 103 } 104 105 if listenPort != 0 { 106 opts.ListenPort = hcloud.Int(listenPort) 107 } 108 if destinationPort != 0 { 109 opts.DestinationPort = hcloud.Int(destinationPort) 110 } 111 112 if protocol != string(hcloud.LoadBalancerServiceProtocolTCP) { 113 opts.HTTP = &hcloud.LoadBalancerAddServiceOptsHTTP{ 114 StickySessions: hcloud.Bool(httpStickySessions), 115 RedirectHTTP: hcloud.Bool(httpRedirect), 116 } 117 if httpCookieName != "" { 118 opts.HTTP.CookieName = hcloud.String(httpCookieName) 119 } 120 if httpCookieLifetime != 0 { 121 opts.HTTP.CookieLifetime = hcloud.Duration(httpCookieLifetime) 122 } 123 for _, certificateID := range httpCertificates { 124 opts.HTTP.Certificates = append(opts.HTTP.Certificates, &hcloud.Certificate{ID: certificateID}) 125 } 126 } 127 action, _, err := cli.Client().LoadBalancer.AddService(cli.Context, loadBalancer, opts) 128 if err != nil { 129 return err 130 } 131 if err := cli.ActionProgress(cli.Context, action); err != nil { 132 return err 133 } 134 fmt.Printf("Service was added to Load Balancer %d\n", loadBalancer.ID) 135 136 return nil 137} 138