1 package main
2
3 import (
4 "flag"
5 "fmt"
6 "os"
7 )
8
9 func usage() {
10 msg := `gke-iap: a gcloud wrapper to access GKE private cluster through IAP
11
12 Usage: gke-iap [Options...]
13 Options:
14 -p, -project The Google Cloud project ID to use for this invocation.
15 -c, -cluster Name of the GKE cluster. Default: default.
16 -ip, -instance-port The number of the GKE instance's port to connect to.
17 Default: 30443.
18 -lp, -local-port The number of the port on which should listen for
19 connections that should be tunneled. Default: 6443.
20 -v, -version Show version information.
21 -h, -help Show help message.
22
23 Author:
24 Raman Antanevich <r.antanevich@gmail.com>
25 <https://github.com/rantanevich>
26 `
27 fmt.Printf(msg)
28 }
29
30 type Options struct {
31 ProjectID string
32 ClusterName string
33 InstancePort int
34 LocalPort int
35 }
36
37 func ParseOptions(versionInfo string) *Options {
38 opts := &Options{}
39
40 var version bool
41
42 flag.StringVar(&opts.ProjectID, "p", "", "Google Cloud project ID")
43 flag.StringVar(&opts.ProjectID, "project", "", "Google Cloud project ID")
44 flag.StringVar(&opts.ClusterName, "c", "default", "Name of the GKE cluster")
45 flag.StringVar(&opts.ClusterName, "cluster", "default", "Name of the GKE cluster")
46 flag.IntVar(&opts.InstancePort, "ip", 30443, "The number of the GKE instance's port to connect to")
47 flag.IntVar(&opts.InstancePort, "instance-port", 30443, "The number of the GKE instance's port to connect to")
48 flag.IntVar(&opts.LocalPort, "lp", 6443, "The local port on which gcloud should listen for connections that should be tunneled")
49 flag.IntVar(&opts.LocalPort, "local-port", 6443, "The local port on which gcloud should listen for connections that should be tunneled")
50 flag.BoolVar(&version, "v", false, "Show version information")
51 flag.BoolVar(&version, "version", false, "Show version information")
52 flag.Usage = usage
53 flag.Parse()
54
55 if version {
56 fmt.Println(versionInfo)
57 os.Exit(0)
58 }
59
60 errMsg := opts.check()
61 if len(errMsg) == 1 {
62 fmt.Fprintf(os.Stderr, "Config error: %s\n", errMsg[0])
63 os.Exit(1)
64 } else if len(errMsg) > 1 {
65 fmt.Fprintln(os.Stderr, "Config error:")
66 for i, msg := range errMsg {
67 fmt.Fprintf(os.Stderr, "%d. %s\n", i+1, msg)
68 }
69 os.Exit(1)
70 }
71
72 return opts
73 }
74
75 func (o *Options) check() (errMsg []string) {
76 defaultProject := GetActiveProject()
77 if o.ProjectID == "" && defaultProject == "" {
78 errMsg = append(errMsg, "-p, -project: must be specified")
79 } else if o.ProjectID == "" && defaultProject != "" {
80 o.ProjectID = defaultProject
81 }
82
83 if o.ClusterName == "" {
84 errMsg = append(errMsg, "-c, -cluster: cannot be empty")
85 }
86
87 if o.InstancePort > 65535 || o.InstancePort <= 0 {
88 errMsg = append(errMsg, "Available INSTANCE_PORT range is 1-65535")
89 }
90
91 if o.LocalPort > 65535 || o.LocalPort < 0 {
92 errMsg = append(errMsg, "Available LOCAL_PORT range is 0-65535")
93 }
94
95 return
96 }
97
View as plain text