├── go.mod ├── url.go ├── list.go ├── LICENSE ├── _example └── main.go ├── delete.go ├── client.go ├── submit.go ├── README.md ├── cmd └── kutt │ └── main.go └── go.sum /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/raahii/kutt-go 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/mitchellh/go-homedir v1.1.0 7 | github.com/nasum/culc v0.0.0-20181216121539-fb9798f9a636 8 | github.com/olekukonko/tablewriter v0.0.4 9 | github.com/pkg/errors v0.8.1 10 | github.com/spf13/cobra v0.0.5 11 | github.com/spf13/pflag v1.0.5 // indirect 12 | github.com/spf13/viper v1.6.1 13 | ) 14 | -------------------------------------------------------------------------------- /url.go: -------------------------------------------------------------------------------- 1 | package kutt 2 | 3 | import "time" 4 | 5 | type URL struct { 6 | ID string `json:"id"` 7 | Target string `json:"target"` 8 | ShortURL string `json:"shortUrl"` 9 | Password bool `json:"password"` 10 | Reuse bool `json:"reuse"` 11 | DomainID string `json:"domain_id"` 12 | VisitCount int `json:"visit_count"` 13 | CreatedAt time.Time `json:"created_at"` 14 | UpdatedAt time.Time `json:"updated_at"` 15 | } 16 | -------------------------------------------------------------------------------- /list.go: -------------------------------------------------------------------------------- 1 | package kutt 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | type listResponse struct { 10 | URLs []*URL `json:"list"` 11 | Count int `json:"countAll"` 12 | } 13 | 14 | func (cli *Client) List() ([]*URL, error) { 15 | path := "/api/url/geturls" 16 | reqURL := cli.BaseURL + path 17 | 18 | req, err := http.NewRequest(http.MethodGet, reqURL, nil) 19 | if err != nil { 20 | return nil, fmt.Errorf("create HTTP request: %w", err) 21 | } 22 | 23 | resp, err := cli.do(req) 24 | if err != nil { 25 | return nil, fmt.Errorf("do HTTP request: %w", err) 26 | } 27 | 28 | defer resp.Body.Close() 29 | 30 | if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) { 31 | return nil, fmt.Errorf("HTTP response: %w", cli.error(resp.StatusCode, resp.Body)) 32 | } 33 | 34 | var r listResponse 35 | if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { 36 | return nil, fmt.Errorf("parse HTTP body: %w", err) 37 | } 38 | 39 | return r.URLs, nil 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 raahii 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/raahii/kutt-go" 9 | ) 10 | 11 | func printURL(u *kutt.URL) { 12 | fmt.Printf("id: %s, target: %s, short_url: %s\n", u.ID, u.Target, u.ShortURL) 13 | } 14 | 15 | func main() { 16 | // new api client with api key 17 | key := os.Getenv("API_KEY") 18 | if key == "" { 19 | fmt.Println("api key is not set.") 20 | os.Exit(1) 21 | } 22 | cli := kutt.NewClient(key) 23 | 24 | // create shorter url 25 | target := "https://github.com/raahii/kutt-go" 26 | URL, err := cli.Submit( 27 | target, 28 | // kutt.WithCustomURL("kutt-go"), 29 | // kutt.WithPassword("foobar"), 30 | // kutt.WithReuse(true), 31 | ) 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | 36 | fmt.Println(">> created") 37 | printURL(URL) 38 | 39 | // list registerd urls 40 | URLs, err := cli.List() 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | 45 | fmt.Println("\n>> all urls") 46 | for _, u := range URLs { 47 | printURL(u) 48 | } 49 | 50 | // delete url 51 | err = cli.Delete( 52 | URL.ID, 53 | // kutt.WithDomain("xxx"), 54 | ) 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | fmt.Println("\n>> url deleted") 59 | printURL(URL) 60 | } 61 | -------------------------------------------------------------------------------- /delete.go: -------------------------------------------------------------------------------- 1 | package kutt 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | type DeleteParams struct { 11 | ID string `json:"id"` 12 | Domain *string `json:"domain"` 13 | } 14 | 15 | type DeleteOption func(*DeleteParams) 16 | 17 | func WithDomain(v string) DeleteOption { 18 | return func(p *DeleteParams) { 19 | p.Domain = &v 20 | } 21 | } 22 | 23 | func (cli *Client) Delete(ID string, opts ...DeleteOption) error { 24 | path := "/api/url/deleteurl" 25 | reqURL := cli.BaseURL + path 26 | 27 | payload := &DeleteParams{ 28 | ID: ID, 29 | } 30 | 31 | for _, opt := range opts { 32 | opt(payload) 33 | } 34 | 35 | jsonBytes, err := json.Marshal(payload) 36 | if err != nil { 37 | return fmt.Errorf("marshal json: %w", err) 38 | } 39 | 40 | body := strings.NewReader(string(jsonBytes)) 41 | req, err := http.NewRequest(http.MethodPost, reqURL, body) 42 | if err != nil { 43 | return fmt.Errorf("create HTTP request: %w", err) 44 | } 45 | req.Header.Set("Content-Type", "application/json") 46 | 47 | resp, err := cli.do(req) 48 | if err != nil { 49 | return fmt.Errorf("do HTTP request: %w", err) 50 | } 51 | 52 | defer resp.Body.Close() 53 | 54 | if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) { 55 | return fmt.Errorf("HTTP response: %w", cli.error(resp.StatusCode, resp.Body)) 56 | } 57 | 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package kutt 2 | 3 | import ( 4 | "io" 5 | "io/ioutil" 6 | "net/http" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | const version = "0.0.1" 12 | 13 | const baseURL = "https://kutt.it" 14 | 15 | func init() { 16 | defaultUserAgent = "kutt-go/" + version + " (+https://github.com/raahii/kutt-go)" 17 | } 18 | 19 | var defaultUserAgent string 20 | 21 | type Client struct { 22 | HTTPClient *http.Client 23 | ApiKey string 24 | BaseURL string 25 | UserAgent string 26 | } 27 | 28 | func NewClient(apiKey string) *Client { 29 | var cli Client 30 | cli.ApiKey = apiKey 31 | cli.BaseURL = baseURL 32 | cli.UserAgent = defaultUserAgent 33 | 34 | return &cli 35 | } 36 | 37 | func (cli *Client) getUA() string { 38 | if cli.UserAgent != "" { 39 | return cli.UserAgent 40 | } 41 | return defaultUserAgent 42 | } 43 | 44 | func (cli *Client) httpClient() *http.Client { 45 | if cli.HTTPClient != nil { 46 | return cli.HTTPClient 47 | } 48 | return http.DefaultClient 49 | } 50 | 51 | func (cli *Client) do(req *http.Request) (*http.Response, error) { 52 | req.Header.Set("X-API-Key", cli.ApiKey) 53 | req.Header.Set("User-Agent", cli.getUA()) 54 | req.Header.Set("Content-Type", "application/json") 55 | req.Header.Set("Accept", "application/json") 56 | return cli.httpClient().Do(req) 57 | } 58 | 59 | func (cli *Client) error(statusCode int, body io.Reader) error { 60 | buf, err := ioutil.ReadAll(body) 61 | if err != nil || len(buf) == 0 { 62 | return errors.Errorf("request failed with status code %d", statusCode) 63 | } 64 | return errors.Errorf("StatusCode: %d, Error: %s", statusCode, string(buf)) 65 | } 66 | -------------------------------------------------------------------------------- /submit.go: -------------------------------------------------------------------------------- 1 | package kutt 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | type SubmitParams struct { 11 | URL string `json:"target"` 12 | CustomURL *string `json:"customurl"` 13 | Password *string `json:"password"` 14 | Reuse *bool `json:"reuse"` 15 | } 16 | 17 | type SubmitOption func(*SubmitParams) 18 | 19 | func WithCustomURL(v string) SubmitOption { 20 | return func(p *SubmitParams) { 21 | p.CustomURL = &v 22 | } 23 | } 24 | 25 | func WithPassword(v string) SubmitOption { 26 | return func(p *SubmitParams) { 27 | p.Password = &v 28 | } 29 | } 30 | 31 | func WithReuse(v bool) SubmitOption { 32 | return func(p *SubmitParams) { 33 | p.Reuse = &v 34 | } 35 | } 36 | 37 | func (cli *Client) Submit(target string, opts ...SubmitOption) (*URL, error) { 38 | path := "/api/url/submit" 39 | reqURL := cli.BaseURL + path 40 | 41 | payload := &SubmitParams{ 42 | URL: target, 43 | } 44 | 45 | for _, opt := range opts { 46 | opt(payload) 47 | } 48 | 49 | jsonBytes, err := json.Marshal(payload) 50 | if err != nil { 51 | return nil, fmt.Errorf("marshal json: %w", err) 52 | } 53 | 54 | body := strings.NewReader(string(jsonBytes)) 55 | req, err := http.NewRequest(http.MethodPost, reqURL, body) 56 | if err != nil { 57 | return nil, fmt.Errorf("create HTTP request: %w", err) 58 | } 59 | req.Header.Set("Content-Type", "application/json") 60 | 61 | resp, err := cli.do(req) 62 | if err != nil { 63 | return nil, fmt.Errorf("do HTTP request: %w", err) 64 | } 65 | 66 | defer resp.Body.Close() 67 | 68 | if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) { 69 | return nil, fmt.Errorf("HTTP response: %w", cli.error(resp.StatusCode, resp.Body)) 70 | } 71 | 72 | var u URL 73 | if err := json.NewDecoder(resp.Body).Decode(&u); err != nil { 74 | return nil, fmt.Errorf("parse HTTP body: %w", err) 75 | } 76 | 77 | return &u, nil 78 | } 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

kutt-go

5 |

6 | Kutt.it API Client for Go and CLI tool 7 |

8 |
9 | 10 | [Kutt.it](https://kutt.it/) is a **Modern Open Source URL shortener.** 11 | 12 | - Custom domain 13 | - Password for the URL 14 | - Managing links 15 | - Free & Open Source 16 | - **50** URLs shortening per day. 17 | 18 | 19 | 20 | This repo contains a CLI and golang package for the service. 21 | 22 | 23 | 24 | ## CLI 25 | 26 | ### Installation 27 | 28 | ```shell 29 | $ go install github.com/raahii/kutt-go/cmd/kutt@latest 30 | ``` 31 | 32 | 33 | 34 | ### Usage 35 | 36 | ```sh 37 | $ kutt register 38 | $ kutt submit 39 | https://kutt.it/ztPDmK 40 | ``` 41 | 42 | ```sh 43 | ❯ kutt --help 44 | CLI tool for Kutt.it (URL Shortener) 45 | 46 | Usage: 47 | kutt [command] 48 | 49 | Available Commands: 50 | apikey Register your api key to cli 51 | delete Delete a shorted link (Give me url id or url shorted) 52 | list List of last 5 URL objects. 53 | submit Submit a new short URL 54 | help Help about any command 55 | 56 | Flags: 57 | -k, --apikey string api key for Kutt.it 58 | -h, --help help for kutt 59 | 60 | Use "kutt [command] --help" for more information about a command. 61 | ``` 62 | 63 | 64 | 65 | ## Go Package 66 | 67 | ### Installation 68 | 69 | ```sh 70 | $ go get -u github.com/raahii/kutt-go 71 | ``` 72 | 73 | 74 | 75 | ### Example 76 | 77 | This is a example to get shorter url. See also codes in `_example` directory. 78 | 79 | ```go 80 | package main 81 | 82 | import ( 83 | "fmt" 84 | "log" 85 | 86 | "github.com/raahii/kutt-go" 87 | ) 88 | 89 | func main() { 90 | cli := kutt.NewClient("") 91 | 92 | // create a short url 93 | target := "https://github.com/raahii/kutt-go" 94 | URL, err := cli.Submit( 95 | target, 96 | // kutt.WithCustomURL("kutt-go"), 97 | // kutt.WithPassword("foobar"), 98 | // kutt.WithReuse(true), 99 | ) 100 | if err != nil { 101 | log.Fatal(err) 102 | } 103 | 104 | fmt.Println(URL.ShortURL) // https://kutt.it/kutt-go 105 | } 106 | ``` 107 | 108 | ```go 109 | type URL struct { 110 | ID string `json:"id"` 111 | Target string `json:"target"` 112 | ShortURL string `json:"shortUrl"` 113 | Password bool `json:"password"` 114 | Reuse bool `json:"reuse"` 115 | DomainID string `json:"domain_id"` 116 | VisitCount int `json:"visit_count"` 117 | CreatedAt time.Time `json:"created_at"` 118 | UpdatedAt time.Time `json:"updated_at"` 119 | } 120 | ``` 121 | 122 | 123 | 124 | ## Reference 125 | 126 | - [thedevs-network/kutt: Free Modern URL Shortener.](https://github.com/thedevs-network/kutt#api) 127 | - [Kutt API v2 documentation](https://docs.kutt.it/) 128 | 129 | 130 | 131 | ## Licence 132 | 133 | Code released under the [MIT License](LICENSE). 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /cmd/kutt/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "fmt" 7 | "os" 8 | "path/filepath" 9 | "strconv" 10 | "time" 11 | 12 | "github.com/mitchellh/go-homedir" 13 | "github.com/olekukonko/tablewriter" 14 | "github.com/raahii/kutt-go" 15 | "github.com/spf13/cobra" 16 | ) 17 | 18 | var cfgPath string 19 | 20 | var RootCmd *cobra.Command 21 | 22 | func init() { 23 | cobra.OnInitialize() 24 | 25 | RootCmd = rootCmd() 26 | RootCmd.AddCommand( 27 | apikeyCmd(), 28 | submitCmd(), 29 | listCmd(), 30 | deleteCmd(), 31 | ) 32 | } 33 | 34 | func exists(filename string) bool { 35 | _, err := os.Stat(filename) 36 | return err == nil 37 | } 38 | 39 | func loadApiKey() (string, error) { 40 | if !exists(cfgPath) { 41 | return "", errors.New("api key is not registerd. run 'kutt apikey '") 42 | } 43 | 44 | // read the file 45 | fp, err := os.Open(cfgPath) 46 | if err != nil { 47 | return "", fmt.Errorf("reading api key from file: %w", err) 48 | } 49 | defer fp.Close() 50 | 51 | scanner := bufio.NewScanner(fp) 52 | scanner.Scan() 53 | apiKey := scanner.Text() 54 | 55 | if apiKey == "" { 56 | return "", fmt.Errorf("api key is empty. remove %s and run 'kutt apikey' again.", cfgPath) 57 | } 58 | 59 | return apiKey, nil 60 | } 61 | 62 | // root command 63 | func rootCmd() *cobra.Command { 64 | cmd := &cobra.Command{ 65 | Use: "kutt", 66 | Short: "CLI tool for Kutt.it (URL Shortener)", 67 | } 68 | 69 | cmd.PersistentFlags().StringP("apikey", "k", "", "api key for Kutt.it") 70 | 71 | return cmd 72 | } 73 | 74 | // apikey command 75 | func apikeyCmd() *cobra.Command { 76 | cmd := &cobra.Command{ 77 | Use: "apikey ", 78 | Short: "Register your api key to cli", 79 | RunE: func(cmd *cobra.Command, args []string) error { 80 | if len(args) < 1 { 81 | return errors.New("apikey is required.") 82 | } 83 | key := args[0] 84 | 85 | if exists(cfgPath) { 86 | err := os.Remove(cfgPath) 87 | if err != nil { 88 | return fmt.Errorf("removing %s: %w", cfgPath, err) 89 | } 90 | } 91 | 92 | fp, err := os.Create(cfgPath) 93 | if err != nil { 94 | return fmt.Errorf("creating %s to store api key: %w", cfgPath, err) 95 | } 96 | defer fp.Close() 97 | 98 | fp.Write(([]byte)(key)) 99 | 100 | return nil 101 | }, 102 | } 103 | 104 | cmd.Flags().StringP("customurl", "c", "", "Custom ID for custom URL") 105 | cmd.Flags().StringP("password", "p", "", "Password for the URL") 106 | cmd.Flags().BoolP("reuse", "r", false, "Return last object of target if exists") 107 | cmd.Flags().BoolP("verbose", "v", false, "Show detailed output for the created url") 108 | 109 | return cmd 110 | } 111 | 112 | // submit command 113 | func submitCmd() *cobra.Command { 114 | var apiKey string 115 | cmd := &cobra.Command{ 116 | Use: "submit ", 117 | Short: "Submit a new short URL", 118 | PreRunE: func(cmd *cobra.Command, args []string) error { 119 | var err error 120 | apiKey, err = loadApiKey() 121 | return err 122 | }, 123 | RunE: func(cmd *cobra.Command, args []string) error { 124 | if len(args) < 1 { 125 | return errors.New("target URL is required.") 126 | } 127 | target := args[0] 128 | flags := cmd.Flags() 129 | 130 | opts := []kutt.SubmitOption{} 131 | 132 | // customURL 133 | if flags.Lookup("customURL") != nil { 134 | customURL, err := flags.GetString("customURL") 135 | if err != nil { 136 | return err 137 | } 138 | opts = append(opts, kutt.WithCustomURL(customURL)) 139 | } 140 | 141 | // password 142 | if flags.Lookup("password") != nil { 143 | password, err := flags.GetString("password") 144 | if err != nil { 145 | return err 146 | } 147 | opts = append(opts, kutt.WithPassword(password)) 148 | } 149 | 150 | // reuse 151 | if flags.Lookup("reuse") != nil { 152 | reuse, err := flags.GetBool("reuse") 153 | if err != nil { 154 | return err 155 | } 156 | opts = append(opts, kutt.WithReuse(reuse)) 157 | } 158 | 159 | cli := kutt.NewClient(apiKey) 160 | u, err := cli.Submit(target, opts...) 161 | if err != nil { 162 | return err 163 | } 164 | 165 | verbose, err := flags.GetBool("verbose") 166 | if err != nil { 167 | return err 168 | } 169 | 170 | if verbose { 171 | table := tablewriter.NewWriter(os.Stdout) 172 | table.SetHeader(URLHeader()) 173 | table.Append(tabulate(u)) 174 | table.Render() 175 | } else { 176 | fmt.Println(u.ShortURL) 177 | } 178 | 179 | return nil 180 | }, 181 | } 182 | 183 | cmd.Flags().StringP("customurl", "c", "", "Custom ID for custom URL") 184 | cmd.Flags().StringP("password", "p", "", "Password for the URL") 185 | cmd.Flags().BoolP("reuse", "r", false, "Return last object of target if exists") 186 | cmd.Flags().BoolP("verbose", "v", false, "Show detailed output for the created url") 187 | 188 | return cmd 189 | } 190 | 191 | // list command 192 | func listCmd() *cobra.Command { 193 | var apiKey string 194 | cmd := &cobra.Command{ 195 | Use: "list", 196 | Short: "List of last 5 URL objects.", 197 | PreRunE: func(cmd *cobra.Command, args []string) error { 198 | var err error 199 | apiKey, err = loadApiKey() 200 | return err 201 | }, 202 | RunE: func(cmd *cobra.Command, args []string) error { 203 | cli := kutt.NewClient(apiKey) 204 | us, err := cli.List() 205 | if err != nil { 206 | return err 207 | } 208 | 209 | table := tablewriter.NewWriter(os.Stdout) 210 | table.SetHeader(URLHeader()) 211 | for _, u := range us { 212 | table.Append(tabulate(u)) 213 | } 214 | table.Render() 215 | 216 | return nil 217 | }, 218 | } 219 | 220 | return cmd 221 | } 222 | 223 | // delete command 224 | func deleteCmd() *cobra.Command { 225 | var apiKey string 226 | cmd := &cobra.Command{ 227 | Use: "delete ", 228 | Short: "Delete a shorted link (Give me url id or url shorted)", 229 | PreRunE: func(cmd *cobra.Command, args []string) error { 230 | var err error 231 | apiKey, err = loadApiKey() 232 | return err 233 | }, 234 | RunE: func(cmd *cobra.Command, args []string) error { 235 | if len(args) < 1 { 236 | return errors.New("target URL ID is required.") 237 | } 238 | ID := args[0] 239 | flags := cmd.Flags() 240 | 241 | opts := []kutt.DeleteOption{} 242 | 243 | // domain 244 | if flags.Lookup("domain") != nil { 245 | domain, err := flags.GetString("domain") 246 | if err != nil { 247 | return err 248 | } 249 | opts = append(opts, kutt.WithDomain(domain)) 250 | } 251 | 252 | cli := kutt.NewClient(apiKey) 253 | err := cli.Delete(ID, opts...) 254 | if err != nil { 255 | return err 256 | } 257 | 258 | return nil 259 | }, 260 | } 261 | 262 | cmd.Flags().StringP("domain", "d", "", "Domain for the URL") 263 | 264 | return cmd 265 | } 266 | 267 | func URLHeader() []string { 268 | return []string{"id", "target", "short url", "password", "visit", "created at"} 269 | } 270 | 271 | func tabulate(u *kutt.URL) []string { 272 | layout := "2006-01-02 15:04:05 MST" 273 | 274 | password := "false" 275 | if u.Password { 276 | password = "true" 277 | } 278 | 279 | return []string{ 280 | u.ID, 281 | u.Target, 282 | u.ShortURL, 283 | password, 284 | strconv.Itoa(u.VisitCount), 285 | u.CreatedAt.In(time.Now().Location()).Format(layout), 286 | } 287 | } 288 | 289 | func main() { 290 | // config file path 291 | home, err := homedir.Dir() 292 | if err != nil { 293 | fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], err) 294 | os.Exit(1) 295 | } 296 | 297 | cfgPath = filepath.Join(home, ".kutt") 298 | 299 | // execute 300 | if err := RootCmd.Execute(); err != nil { 301 | fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], err) 302 | os.Exit(1) 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 4 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 5 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 6 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 7 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 8 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 9 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 10 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 11 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 12 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 13 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 14 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 15 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 16 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 17 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 18 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 19 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 20 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 21 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 22 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 23 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 24 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 25 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 26 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 27 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 28 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 29 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 30 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 31 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 32 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 33 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 34 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 35 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 36 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 37 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 38 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 39 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 40 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 41 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 42 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 43 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 44 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 45 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 46 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 47 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 48 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 49 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 50 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 51 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 52 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 53 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 54 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 55 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 56 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 57 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 58 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 59 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 60 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 61 | github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= 62 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 63 | github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= 64 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 65 | github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= 66 | github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 67 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 68 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 69 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 70 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 71 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 72 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 73 | github.com/nasum/culc v0.0.0-20181216121539-fb9798f9a636 h1:/4YnfdKrQ5RZxUycjKZAYUZ8B5q1iKjzMBno9E+z3OM= 74 | github.com/nasum/culc v0.0.0-20181216121539-fb9798f9a636/go.mod h1:AI1txHvn9rfqOXJSF2beBjHmc1IiUqDsQOZniUtVN6Y= 75 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 76 | github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= 77 | github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= 78 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 79 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 80 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 81 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 82 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 83 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 84 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 85 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 86 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 87 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 88 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 89 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 90 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 91 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 92 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 93 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 94 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 95 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 96 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 97 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 98 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 99 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 100 | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 101 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 102 | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 103 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 104 | github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= 105 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 106 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 107 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 108 | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 109 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 110 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 111 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 112 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 113 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 114 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 115 | github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= 116 | github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= 117 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 118 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 119 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 120 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 121 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 122 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 123 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 124 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 125 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 126 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 127 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 128 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 129 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 130 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 131 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 132 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 133 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 134 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 135 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 136 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 137 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 138 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 139 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 140 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 141 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 142 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 143 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 144 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 145 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 146 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 147 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 148 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 149 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 150 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 151 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 152 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 153 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 154 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 155 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 156 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 157 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 158 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 159 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 160 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 161 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 162 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 163 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 164 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 165 | gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= 166 | gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 167 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 168 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 169 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 170 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 171 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 172 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 173 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 174 | --------------------------------------------------------------------------------