Skip to content

Commit

Permalink
feat(loadbalancer): Added the cmd loadbalancer
Browse files Browse the repository at this point in the history
Added the possibility the you can list, create, update and delete loadbalancer

BREAKING CHANGE: No

Signed-off-by: Alejandro JNM <[email protected]>
  • Loading branch information
alejandrojnm committed May 6, 2020
1 parent 0ad42ae commit 410abb5
Show file tree
Hide file tree
Showing 8 changed files with 428 additions and 2 deletions.
55 changes: 53 additions & 2 deletions cmd/loadbalancer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,57 @@
package cmd

// loadbalancer list -- list all load balancers [ls, all]
// loadbalancer list -- list all load balancers [ls, all] *
// loadbalancer create [OPTIONS] -- create a new load balancer with options [new]
// loadbalancer update ID [OPTIONS] -- update the load balancer ID with options provided [change]
// loadbalancer remove ID -- remove the load balancer with ID [delete, destroy, rm]
// loadbalancer remove ID -- remove the load balancer with ID [delete, destroy, rm] *

import (
"github.com/spf13/cobra"
)

var loadBalancerCmd = &cobra.Command{
Use: "loadbalancer",
Aliases: []string{"loadbalancer"},
Short: "Details of Civo Load Balancer",
}

func init() {
rootCmd.AddCommand(loadBalancerCmd)
loadBalancerCmd.AddCommand(loadBalancerListCmd)
loadBalancerCmd.AddCommand(loadBalancerRemoveCmd)
loadBalancerCmd.AddCommand(loadBalancerCreateCmd)
loadBalancerCmd.AddCommand(loadBalancerUpdateCmd)

/*
Flags for create a load balancer
*/
loadBalancerCreateCmd.Flags().StringVarP(&lbHostname, "hostname", "e", "", "If not supplied, will be in format loadbalancer-uuid.civo.com")
loadBalancerCreateCmd.Flags().StringVarP(&lbProtocol, "protocol", "p", "", "Either http or https. If you specify https then you must also provide the next two fields")
loadBalancerCreateCmd.Flags().StringVarP(&tlsCertificate, "tls_certificate", "c", "", "TLS certificate in Base64-encoded PEM. Required if --protocol is https")
loadBalancerCreateCmd.Flags().StringVarP(&tlsKey, "tls_key", "k", "", "TLS certificate in Base64-encoded PEM. Required if --protocol is https")
loadBalancerCreateCmd.Flags().StringVarP(&policy, "policy", "y", "", "<least_conn | random | round_robin | ip_hash> - Balancing policy to choose backends")
loadBalancerCreateCmd.Flags().IntVarP(&lbPort, "port", "r", 80, "Listening port. Defaults to 80 to match default http protocol")
loadBalancerCreateCmd.Flags().IntVarP(&maxRequestSize, "max_request_size", "m", 20, "Maximum request content size, in MB. Defaults to 20")
loadBalancerCreateCmd.Flags().StringVarP(&healthCheckPath, "health_check_path", "l", "", "URL to check for a valid (2xx/3xx) HTTP status on the backends. Defaults to /")
loadBalancerCreateCmd.Flags().IntVarP(&failTimeout, "fail_timeout", "t", 30, "Timeout in seconds to consider a backend to have failed. Defaults to 30")
loadBalancerCreateCmd.Flags().IntVarP(&maxConnections, "max_connections", "x", 10, "Maximum concurrent connections to each backend. Defaults to 10")
loadBalancerCreateCmd.Flags().BoolVarP(&ignoreInvalidBackendTLS, "ignore_invalid_backend_tls", "i", true, "Should self-signed/invalid certificates be ignored from backend servers? Defaults to true")
loadBalancerCreateCmd.Flags().StringArrayVarP(&backends, "backends", "b", []string{}, "Specify a backend instance to associate with the load balancer. Takes instance_id, protocol and port in the format --backend=instance:instance-id|instance-name,protocol:http,port:80")

/*
Flags for update a load balancer
*/
loadBalancerUpdateCmd.Flags().StringVarP(&lbHostnameUpdate, "hostname", "e", "", "If not supplied, will be in format loadbalancer-uuid.civo.com")
loadBalancerUpdateCmd.Flags().StringVarP(&lbProtocolUpdate, "protocol", "p", "", "Either http or https. If you specify https then you must also provide the next two fields")
loadBalancerUpdateCmd.Flags().StringVarP(&tlsCertificateUpdate, "tls_certificate", "c", "", "TLS certificate in Base64-encoded PEM. Required if --protocol is https")
loadBalancerUpdateCmd.Flags().StringVarP(&tlsKeyUpdate, "tls_key", "k", "", "TLS certificate in Base64-encoded PEM. Required if --protocol is https")
loadBalancerUpdateCmd.Flags().StringVarP(&policyUpdate, "policy", "y", "", "<least_conn | random | round_robin | ip_hash> - Balancing policy to choose backends")
loadBalancerUpdateCmd.Flags().IntVarP(&lbPortUpdate, "port", "r", 80, "Listening port. Defaults to 80 to match default http protocol")
loadBalancerUpdateCmd.Flags().IntVarP(&maxRequestSizeUpdate, "max_request_size", "m", 20, "Maximum request content size, in MB. Defaults to 20")
loadBalancerUpdateCmd.Flags().StringVarP(&healthCheckPathUpdate, "health_check_path", "l", "", "URL to check for a valid (2xx/3xx) HTTP status on the backends. Defaults to /")
loadBalancerUpdateCmd.Flags().IntVarP(&failTimeoutUpdate, "fail_timeout", "t", 30, "Timeout in seconds to consider a backend to have failed. Defaults to 30")
loadBalancerUpdateCmd.Flags().IntVarP(&maxConnectionsUpdate, "max_connections", "x", 10, "Maximum concurrent connections to each backend. Defaults to 10")
loadBalancerUpdateCmd.Flags().BoolVarP(&ignoreInvalidBackendTLSUpdate, "ignore_invalid_backend_tls", "i", true, "Should self-signed/invalid certificates be ignored from backend servers? Defaults to true")
loadBalancerUpdateCmd.Flags().StringArrayVarP(&backendsUpdate, "backends", "b", []string{}, "Specify a backend instance to associate with the load balancer. Takes instance_id, protocol and port in the format --backend=instance:instance-id|instance-name,protocol:http,port:80")

}
106 changes: 106 additions & 0 deletions cmd/loadbalancer_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package cmd

import (
"fmt"
"github.com/civo/civogo"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"os"
"strconv"
)

var lbHostname, lbProtocol, tlsCertificate, tlsKey, policy, healthCheckPath string
var lbPort, maxRequestSize, failTimeout, maxConnections int
var ignoreInvalidBackendTLS bool
var backends []string

var loadBalancerCreateCmd = &cobra.Command{
Use: "create",
Aliases: []string{"new", "add"},
Short: "Create a new Load Balancer",
//Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
client, err := config.CivoAPIClient()
if err != nil {
fmt.Printf("Unable to create a Civo API Client: %s\n", aurora.Red(err))
os.Exit(1)
}

configLoadBalancer := &civogo.LoadBalancerConfig{
Port: lbPort,
MaxRequestSize: maxRequestSize,
FailTimeout: failTimeout,
MaxConns: maxConnections,
IgnoreInvalidBackendTLS: ignoreInvalidBackendTLS,
}

if lbHostname != "" {
configLoadBalancer.Hostname = lbHostname
}

if lbProtocol != "" {
configLoadBalancer.Protocol = lbProtocol
}

if tlsCertificate != "" {
configLoadBalancer.TLSCertificate = tlsCertificate
}

if tlsKey != "" {
configLoadBalancer.TLSKey = tlsKey
}

if policy != "" {
configLoadBalancer.Policy = policy
}

if healthCheckPath != "" {
configLoadBalancer.HealthCheckPath = healthCheckPath
}

if len(backends) > 0 {
var configLoadBalancerBackend []civogo.LoadBalancerBackendConfig

for _, backend := range backends {
data := utility.GetStringMap(backend)
instance, err := client.FindInstance(data["instance"])
if err != nil {
fmt.Printf("Unable to find the instance: %s\n", aurora.Red(err))
os.Exit(1)
}

portBackend, err := strconv.Atoi(data["port"])
if err != nil {
fmt.Println(err)
}

configLoadBalancerBackend = append(configLoadBalancerBackend, civogo.LoadBalancerBackendConfig{
InstanceID: instance.ID,
Protocol: data["protocol"],
Port: portBackend,
})
}

configLoadBalancer.Backends = configLoadBalancerBackend
}

loadBalancer, err := client.CreateLoadBalancer(configLoadBalancer)
if err != nil {
fmt.Printf("Unable to create a load balancer: %s\n", aurora.Red(err))
os.Exit(1)
}

ow := utility.NewOutputWriterWithMap(map[string]string{"ID": loadBalancer.ID, "Hostname": loadBalancer.Hostname})

switch outputFormat {
case "json":
ow.WriteSingleObjectJSON()
case "custom":
ow.WriteCustomOutput(outputFields)
default:
fmt.Printf("Created a new Load Balancer with hostname %s with ID %s\n", aurora.Green(loadBalancer.Hostname), aurora.Green(loadBalancer.ID))
}
},
}
91 changes: 91 additions & 0 deletions cmd/loadbalancer_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package cmd

import (
"fmt"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"os"
"strconv"
"strings"
)

var loadBalancerListCmd = &cobra.Command{
Use: "ls",
Aliases: []string{"list", "all"},
Short: "List Load Balancer",
Long: `List all current Load Balancer.
If you wish to use a custom format, the available fields are:
* ID
* Name
* Protocol
* Port
* TLSCertificate
* TLSKey
* Policy
* HealthCheckPath
* FailTimeout
* MaxConns
* IgnoreInvalidBackendTLS
* Backends
Example: civo loadbalancer ls -o custom -f "ID: Name"`,
Run: func(cmd *cobra.Command, args []string) {
client, err := config.CivoAPIClient()
if err != nil {
fmt.Printf("Unable to create a Civo API Client: %s\n", aurora.Red(err))
os.Exit(1)
}

lbs, err := client.ListLoadBalancers()
if err != nil {
fmt.Printf("Unable to list Load Balancer: %s\n", aurora.Red(err))
os.Exit(1)
}

ow := utility.NewOutputWriter()
for _, lb := range lbs {
ow.StartLine()

ow.AppendData("ID", lb.ID)
ow.AppendData("Name", lb.Hostname)
ow.AppendData("Protocol", lb.Protocol)
ow.AppendData("Port", strconv.Itoa(lb.Port))

if outputFormat == "json" || outputFormat == "custom" {
ow.AppendDataWithLabel("TLSCertificate", lb.TLSCertificate, "TLS Cert")
ow.AppendDataWithLabel("TLSKey", lb.TLSKey, "TLS Key")
ow.AppendData("Policy", lb.Policy)
ow.AppendDataWithLabel("HealthCheckPath", lb.HealthCheckPath, "Health Check Path")
ow.AppendDataWithLabel("FailTimeout", strconv.Itoa(lb.FailTimeout), "Fail Timeout")
ow.AppendDataWithLabel("MaxConns", strconv.Itoa(lb.MaxConns), "Max. Connections")
ow.AppendDataWithLabel("IgnoreInvalidBackendTLS", strconv.FormatBool(lb.IgnoreInvalidBackendTLS), "Ignore Invalid Backend TLS?")
}

var backendList []string

for _, backend := range lb.Backends {
instance, err := client.FindInstance(backend.InstanceID)
if err != nil {
fmt.Printf("Unable to find the instance: %s\n", aurora.Red(err))
os.Exit(1)
}
backendList = append(backendList, instance.Hostname)
}

ow.AppendData("Backends", strings.Join(backendList, ", "))

}

switch outputFormat {
case "json":
ow.WriteMultipleObjectsJSON()
case "custom":
ow.WriteCustomOutput(outputFields)
default:
ow.WriteTable()
}
},
}
43 changes: 43 additions & 0 deletions cmd/loadbalancer_remove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cmd

import (
"fmt"
"github.com/civo/cli/config"
"github.com/civo/cli/utility"
"github.com/logrusorgru/aurora"
"github.com/spf13/cobra"
"os"
)

var loadBalancerRemoveCmd = &cobra.Command{
Use: "remove",
Aliases: []string{"rm", "delete", "destroy"},
Short: "Remove a Load Balancer",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
client, err := config.CivoAPIClient()
if err != nil {
fmt.Printf("Unable to create a Civo API Client: %s\n", aurora.Red(err))
os.Exit(1)
}

lb, err := client.FindLoadBalancer(args[0])
if err != nil {
fmt.Printf("Unable to find load balancer for your search: %s\n", aurora.Red(err))
os.Exit(1)
}

_, err = client.DeleteLoadBalancer(lb.ID)

ow := utility.NewOutputWriterWithMap(map[string]string{"ID": lb.ID, "Hostname": lb.Hostname})

switch outputFormat {
case "json":
ow.WriteSingleObjectJSON()
case "custom":
ow.WriteCustomOutput(outputFields)
default:
fmt.Printf("The load blancer %s with ID %s was delete\n", aurora.Green(lb.Hostname), aurora.Green(lb.ID))
}
},
}
Loading

0 comments on commit 410abb5

Please sign in to comment.