summaryrefslogtreecommitdiff
path: root/internal/config/args.go
blob: 42aff85959253a8bdb161497be5c55053eeab411 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package config

import (
	"encoding/base64"
	"fmt"
	"strconv"
	"strings"

	"github.com/mimecast/dtail/internal/lcontext"
	"github.com/mimecast/dtail/internal/omode"

	gossh "golang.org/x/crypto/ssh"
)

// Args is a helper struct to summarize common client arguments.
type Args struct {
	lcontext.LContext
	Arguments             []string
	ConfigFile            string
	ConnectionsPerCPU     int
	ControlTTYPath        string
	Discovery             string
	InteractiveQuery      bool
	LogDir                string
	Logger                string
	LogLevel              string
	Mode                  omode.Mode
	NoAuthKey             bool
	NoColor               bool
	QueryStr              string
	Quiet                 bool
	RegexInvert           bool
	RegexStr              string
	SSHAgentKeyIndex      int
	SSHAuthMethods        []gossh.AuthMethod
	SSHBindAddress        string
	SSHHostKeyCallback    gossh.HostKeyCallback
	SSHPort               int
	SSHPrivateKeyFilePath string
	Serverless            bool
	ServersStr            string
	Plain                 bool
	Timeout               int
	TrustAllHosts         bool
	UserName              string
	What                  string
}

func (a *Args) String() string {
	var sb strings.Builder

	sb.WriteString("Args(")

	sb.WriteString(fmt.Sprintf("%s:%v,", "Arguments", a.Arguments))
	sb.WriteString(fmt.Sprintf("%s:%v,", "ConfigFile", a.ConfigFile))
	sb.WriteString(fmt.Sprintf("%s:%v,", "ConnectionsPerCPU", a.ConnectionsPerCPU))
	sb.WriteString(fmt.Sprintf("%s:%v,", "ControlTTYPath", a.ControlTTYPath))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Discovery", a.Discovery))
	sb.WriteString(fmt.Sprintf("%s:%v,", "InteractiveQuery", a.InteractiveQuery))
	sb.WriteString(fmt.Sprintf("%s:%v,", "LogDir", a.LogDir))
	sb.WriteString(fmt.Sprintf("%s:%v,", "LogLevel", a.LogLevel))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Logger", a.Logger))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Mode", a.Mode))
	sb.WriteString(fmt.Sprintf("%s:%v,", "NoAuthKey", a.NoAuthKey))
	sb.WriteString(fmt.Sprintf("%s:%v,", "NoColor", a.NoColor))
	sb.WriteString(fmt.Sprintf("%s:%v,", "QueryStr", a.QueryStr))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Quiet", a.Quiet))
	sb.WriteString(fmt.Sprintf("%s:%v,", "RegexInvert", a.RegexInvert))
	sb.WriteString(fmt.Sprintf("%s:%v,", "RegexStr", a.RegexStr))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHAgentKeyIndex", a.SSHAgentKeyIndex))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHAuthMethods", a.SSHAuthMethods))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHBindAddress", a.SSHBindAddress))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHHostKeyCallback", a.SSHHostKeyCallback))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHPrivateKeyFilePath", a.SSHPrivateKeyFilePath))
	sb.WriteString(fmt.Sprintf("%s:%v,", "SSHPort", a.SSHPort))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Serverless", a.Serverless))
	sb.WriteString(fmt.Sprintf("%s:%v,", "ServersStr", a.ServersStr))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Plain", a.Plain))
	sb.WriteString(fmt.Sprintf("%s:%v,", "Timeout", a.Timeout))
	sb.WriteString(fmt.Sprintf("%s:%v,", "TrustAllHosts", a.TrustAllHosts))
	sb.WriteString(fmt.Sprintf("%s:%v,", "UserName", a.UserName))
	sb.WriteString(fmt.Sprintf("%s:%v", "What", a.What))
	sb.WriteString(")")

	return sb.String()
}

// SerializeOptions returns a string ready to be sent over the wire to the server.
func (a *Args) SerializeOptions() string {
	options := make(map[string]string)

	if a.Quiet {
		options["quiet"] = fmt.Sprintf("%v", a.Quiet)
	}
	if a.Plain {
		options["plain"] = fmt.Sprintf("%v", a.Plain)
	}
	if a.Serverless {
		options["serverless"] = fmt.Sprintf("%v", a.Serverless)
	}
	if a.LContext.MaxCount != 0 {
		options["max"] = fmt.Sprintf("%d", a.LContext.MaxCount)
	}
	if a.LContext.BeforeContext != 0 {
		options["before"] = fmt.Sprintf("%d", a.LContext.BeforeContext)
	}
	if a.LContext.AfterContext != 0 {
		options["after"] = fmt.Sprintf("%d", a.LContext.AfterContext)
	}

	var sb strings.Builder
	var i int
	for k, v := range options {
		if i > 0 {
			sb.WriteString(":")
		}
		sb.WriteString(k)
		sb.WriteString("=")
		sb.WriteString(v)
		i++
	}
	return sb.String()
}

// DeserializeOptions deserializes the options, but into a map.
func DeserializeOptions(opts []string) (map[string]string, lcontext.LContext, error) {
	options := make(map[string]string, len(opts))
	var ltx lcontext.LContext

	for _, o := range opts {
		kv := strings.SplitN(o, "=", 2)
		if len(kv) != 2 {
			return options, ltx, fmt.Errorf("Unable to parse options: %v", kv)
		}
		key := kv[0]
		val := kv[1]

		if strings.HasPrefix(val, "base64%") {
			s := strings.SplitN(val, "%", 2)
			decoded, err := base64.StdEncoding.DecodeString(s[1])
			if err != nil {
				return options, ltx, err
			}
			val = string(decoded)
		}

		var err error
		if options, err = setOption(key, val, options, &ltx); err != nil {
			return options, ltx, err
		}
	}

	return options, ltx, nil
}

func setOption(key, val string, options map[string]string, ltx *lcontext.LContext) (map[string]string, error) {
	switch key {
	case "before":
		iVal, err := strconv.Atoi(val)
		if err != nil {
			return options, err
		}
		ltx.BeforeContext = iVal
	case "after":
		iVal, err := strconv.Atoi(val)
		if err != nil {
			return options, err
		}
		ltx.AfterContext = iVal
	case "max":
		iVal, err := strconv.Atoi(val)
		if err != nil {
			return options, err
		}
		ltx.MaxCount = iVal
	default:
		options[key] = val
	}
	return options, nil
}