diff --git a/README.md b/README.md index ab56b8c..f07e9ad 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,21 @@ A golang F5 rest client ## To do - everything + + +### Pool + +**https://10.60.99.241/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool** + +``` +RawText +{"kind":"tm:ltm:pool:poolstate","name":"audmzbilltweb-sit_443_pool","partition":"DMZ","fullPath":"/DMZ/audmzbilltweb-sit_443_pool","generation":211,"selfLink":"https://localhost/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool?ver=11.6.0","allowNat":"yes","allowSnat":"yes","ignorePersistedWeight":"disabled","ipTosToClient":"pass-through","ipTosToServer":"pass-through","linkQosToClient":"pass-through","linkQosToServer":"pass-through","loadBalancingMode":"round-robin","minActiveMembers":0,"minUpMembers":0,"minUpMembersAction":"failover","minUpMembersChecking":"disabled","monitor":"min 1 of { /Common/tcp }","queueDepthLimit":0,"queueOnConnectionLimit":"disabled","queueTimeLimit":0,"reselectTries":0,"serviceDownAction":"none","slowRampTime":10,"membersReference":{"link":"https://localhost/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members?ver=11.6.0","isSubcollection":true}} +``` + +### Members + +**https://10.60.99.242/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members?ver=11.6.0** + +``` +{"kind":"tm:ltm:pool:members:memberscollectionstate","selfLink":"https://localhost/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members?ver=11.6.0","items":[{"kind":"tm:ltm:pool:members:membersstate","name":"audmzbilltweb01-sit:443","partition":"DMZ","fullPath":"/DMZ/audmzbilltweb01-sit:443","generation":233,"selfLink":"https://localhost/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members/~DMZ~audmzbilltweb01-sit:443?ver=11.6.0","address":"10.60.61.215%6","connectionLimit":0,"dynamicRatio":1,"ephemeral":"false","fqdn":{"autopopulate":"disabled"},"inheritProfile":"enabled","logging":"disabled","monitor":"default","priorityGroup":0,"rateLimit":"disabled","ratio":1,"session":"monitor-enabled","state":"up"},{"kind":"tm:ltm:pool:members:membersstate","name":"audmzbilltweb02-sit:443","partition":"DMZ","fullPath":"/DMZ/audmzbilltweb02-sit:443","generation":153,"selfLink":"https://localhost/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members/~DMZ~audmzbilltweb02-sit:443?ver=11.6.0","address":"10.60.61.216%6","connectionLimit":0,"dynamicRatio":1,"ephemeral":"false","fqdn":{"autopopulate":"disabled"},"inheritProfile":"enabled","logging":"disabled","monitor":"default","priorityGroup":0,"rateLimit":"disabled","ratio":1,"session":"monitor-enabled","state":"up"}]} +``` diff --git a/f5er b/f5er index 6c98772..277baa1 100755 Binary files a/f5er and b/f5er differ diff --git a/src/f5er.go b/src/f5er.go index 5670a0e..83c9574 100644 --- a/src/f5er.go +++ b/src/f5er.go @@ -17,7 +17,6 @@ import ( // "github.com/kr/pretty" "code.google.com/p/gopass" "crypto/tls" - "errors" "fmt" "github.com/jmcvetta/napping" "github.com/spf13/cobra" @@ -25,41 +24,70 @@ import ( "log" "net/http" "net/url" + //"strings" // "time" ) -var F5Cmd = &cobra.Command{ +var ( + f5Host string + username string + passwd string + partition string + poolname string + cfgFile string = "f5.json" +) + +var f5Cmd = &cobra.Command{ Use: "f5er", Short: "tickle an F5 load balancer using REST", - Long: `A utility to create and manage F5 configuration objects`, + Long: "A utility to create and manage F5 configuration objects", +} + +var showCmd = &cobra.Command{ + Use: "show", + Short: "show F5 objects", + Long: "show current state of F5 objects. Show requires an object, eg. f5er show pool", Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - InitialiseConfig() - Run() + if len(args) < 1 { + cmd.Help() + bail("show needs an argument - the object type to show perhaps??") + } }, } -func getConfigurable(k string) (v string, err error) { - v = viper.GetString(k) - if len(v) > 0 { - return v, nil +var showPoolCmd = &cobra.Command{ + Use: "pool", + Short: "show a pool", + Long: "show the current state of a pool", + Run: func(cmd *cobra.Command, args []string) { + if len(args) < 1 { + fmt.Println("f5er show pool") + showPools() + } else { + pname := args[0] + fmt.Println("f5er show pool " + pname) + showPool(pname) + } + }, +} + +type httperr struct { + Message string + Errors []struct { + Resource string + Field string + Code string } - errstr := "undefined configurable: " + k - err = errors.New(errstr) - return v, err } -var ( - f5Host string - username string - passwd string - cfgFile string = "f5.json" -) +type LBPool struct { + Name string `json:"name"` + Partition string `json:"partition"` + Fullpath string `json:"fullPath"` +} -func init() { - F5Cmd.PersistentFlags().StringVarP(&f5Host, "f5", "f", "", "IP or hostname of F5 to poke") - viper.BindPFlag("f5", F5Cmd.Flags().Lookup("f5")) - log.SetFlags(log.Ltime | log.Lshortfile) +type LBPools struct { + Items []LBPool `json:"items"` } func InitialiseConfig() { @@ -72,18 +100,19 @@ func InitialiseConfig() { if err != nil { fmt.Println("Can't find your config file: %s", cfgFile) } + checkRequiredFlag("f5") f5Host = viper.GetString("f5") username = viper.GetString("username") passwd = viper.GetString("passwd") + partition = viper.GetString("partition") + poolname = viper.GetString("poolname") } -func CheckRequiredFlags() { +func checkRequiredFlag(flg string) { - if !viper.IsSet("f5") { + if !viper.IsSet(flg) { log.SetFlags(0) - log.Println("") - log.Println("error: missing required option --f5") - log.Fatalln("") + log.Fatalf("\nerror: missing required option --%s\n\n", flg) } if !viper.IsSet("username") { promptForCreds() @@ -107,28 +136,56 @@ func promptForCreds() { } } -func Run() { +func bail(msg string) { + log.SetFlags(0) + log.Fatalf("\n%s\n\n", msg) +} - CheckRequiredFlags() +func showPools() { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} // - // Compose request + // Setup HTTP Basic auth for this session (ONLY use this with SSL). Auth + // can also be configured on a per-request basis when using Send(). // - // http://developer.github.com/v3/oauth/#create-a-new-authorization + s := napping.Session{ + Client: client, + Userinfo: url.UserPassword(username, passwd), + } + + url := "https://" + f5Host + "/mgmt/tm/ltm/pool" + res := LBPools{} + + //url := "https://10.60.99.241/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool" + //url := "https://10.60.99.241/mgmt/tm/ltm/pool" + //url := "https://10.60.99.242/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members?ver=11.6.0" + // + // Send request to server // - //payload := struct { - // Scopes []string `json:"scopes"` - // Note string `json:"note"` - // }{ - // Scopes: []string{"public_repo"}, - // Note: "testing Go napping" + time.Now().String(), - // } - - type LBPool struct { - Name string `json:"name"` - Partition string `json:"partition"` - Fullpath string `json:"fullPath"` + e := httperr{} + resp, err := s.Get(url, nil, &res, &e) + if err != nil { + log.Fatal(err) + } + for _, v := range res.Items { + fmt.Printf("pool\npartition:\t%s\n", v.Partition) + fmt.Printf("name:\t\t%s\n", v.Name) + fmt.Printf("fullpath:\t\t%s\n\n", v.Fullpath) } + fmt.Println("response Status:", resp.Status()) + fmt.Println("--------------------------------------------------------------------------------") + fmt.Println("Header") + fmt.Println(resp.HttpResponse().Header) + fmt.Println("--------------------------------------------------------------------------------") + fmt.Println("RawText") + fmt.Println(resp.RawText()) + println("") +} + +func showPool(pname string) { /* { @@ -164,38 +221,6 @@ func Run() { } */ - // - // Struct to hold response data - // - type ResponseUserAgent struct { - Useragent string `json:"user-agent"` - } - // - // Struct to hold response data - // - // res := struct { - // Id int - // Url string - // Scopes []string - // Token string - // App map[string]string - // Note string - // NoteUrl string `json:"note_url"` - // UpdatedAt string `json:"updated_at"` - // CreatedAt string `json:"created_at"` - // }{} - // - // Struct to hold error response - // - e := struct { - Message string - Errors []struct { - Resource string - Field string - Code string - } - }{} - tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } @@ -208,36 +233,26 @@ func Run() { Client: client, Userinfo: url.UserPassword(username, passwd), } - url := "https://10.60.99.241/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool" + + // url := "https://" + f5Host + "/mgmt/tm/ltm/pool/" + poolname + "?\\$expand=*" + url := "https://" + f5Host + "/mgmt/tm/ltm/pool/~" + partition + "~" + poolname + res := LBPool{} + + //url := "https://10.60.99.241/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool" + //url := "https://10.60.99.241/mgmt/tm/ltm/pool" + //url := "https://10.60.99.242/mgmt/tm/ltm/pool/~DMZ~audmzbilltweb-sit_443_pool/members?ver=11.6.0" // // Send request to server // - res := LBPool{} + e := httperr{} resp, err := s.Get(url, nil, &res, &e) if err != nil { log.Fatal(err) } - // - // Process response - // - // println("") - // if resp.Status() == 201 { - // fmt.Printf("Github auth token: %s\n\n", res.Token) - // } else { - // fmt.Println("Bad response status from Github server") - // fmt.Printf("\t Status: %v\n", resp.Status()) - // fmt.Printf("\t Message: %v\n", e.Message) - // fmt.Printf("\t Errors: %v\n", e.Message) - // pretty.Println(e.Errors) - // } - // println("") - - // - // Process response - // - println("") - fmt.Printf("pool fullpath: %s\n\n", res.Fullpath) - println("") + fmt.Printf("url:\t%s\n", url) + fmt.Printf("pool\npartition:\t%s\n", res.Partition) + fmt.Printf("name:\t\t%s\n", res.Name) + fmt.Printf("fullpath:\t\t%s\n\n", res.Fullpath) fmt.Println("response Status:", resp.Status()) fmt.Println("--------------------------------------------------------------------------------") fmt.Println("Header") @@ -248,8 +263,17 @@ func Run() { println("") } -func main() { +func init() { + f5Cmd.Flags().StringVarP(&f5Host, "f5", "f", "", "IP or hostname of F5 to poke") + viper.BindPFlag("f5", f5Cmd.Flags().Lookup("f5")) + f5Cmd.AddCommand(showCmd) + showCmd.AddCommand(showPoolCmd) + // log.SetFlags(log.Ltime | log.Lshortfile) + log.SetFlags(0) + InitialiseConfig() +} +func main() { viper.AutomaticEnv() - F5Cmd.Execute() + f5Cmd.Execute() }