@@ -89,126 +89,154 @@ func applyRandomizedStart() {
89
89
}
90
90
}
91
91
92
- var Cmd = & cobra.Command {
93
- Use : "apidump" ,
94
- Short : "Capture requests/responses from network traffic." ,
95
- Long : "Capture and store a sequence of requests/responses to a service by observing network traffic." ,
96
- SilenceUsage : true ,
97
- Args : cobra .ExactArgs (0 ),
98
- RunE : func (cmd * cobra.Command , _ []string ) error {
99
- applyRandomizedStart ()
92
+ // When run in a container or as a systemd service, we will automatically be restarted
93
+ // on failure. But, this will not correct misconfiguration errors; we will just get stuck
94
+ // in a boot loop, which can cause disruption to the services in the same pod.
95
+ //
96
+ // Instead, we will terminate normally when no error is returned, but loop indefinitely
97
+ // on error, as if randomized start failed.
98
+ //
99
+ // FIXME: do we need custom SIGTERM or SIGINT handlers? I do not think we do. But, it
100
+ // might be that apidump already installed one before returning error. Will that cause a problem?
101
+ //
102
+ // TODO: create a separate command for "run as a service" vs "run on command line"? I don't
103
+ // think there is a reliable way to tell the context otherwise.
104
+ func apidumpRunWithoutAbnormalExit (cmd * cobra.Command , args []string ) error {
105
+ err := apidumpRunInternal (cmd , args )
100
106
101
- traceTags , err := util .ParseTagsAndWarn (tagsFlag )
102
- if err != nil {
103
- return err
104
- }
107
+ if err == nil {
108
+ return nil
109
+ }
105
110
106
- plugins , err := pluginloader .Load (pluginsFlag )
111
+ // Log the error and wait forever.
112
+ printer .Stderr .Errorf ("Error during initiaization: %v\n " , err )
113
+ printer .Stdout .Infof ("This process will not exit, to avoid boot loops. Please correct the command line flags or environment and retry.\n " )
114
+
115
+ select {}
116
+ }
117
+
118
+ func apidumpRunInternal (cmd * cobra.Command , _ []string ) error {
119
+ applyRandomizedStart ()
120
+
121
+ traceTags , err := util .ParseTagsAndWarn (tagsFlag )
122
+ if err != nil {
123
+ return err
124
+ }
125
+
126
+ plugins , err := pluginloader .Load (pluginsFlag )
127
+ if err != nil {
128
+ return errors .Wrap (err , "failed to load plugins" )
129
+ }
130
+
131
+ // Check that exactly one of --project or --collection is specified.
132
+ if projectID == "" && postmanCollectionID == "" {
133
+ return errors .New ("exactly one of --project or --collection must be specified" )
134
+ }
135
+
136
+ // If --project was given, convert projectID to serviceID.
137
+ var serviceID akid.ServiceID
138
+ if projectID != "" {
139
+ err := akid .ParseIDAs (projectID , & serviceID )
107
140
if err != nil {
108
- return errors .Wrap (err , "failed to load plugins " )
141
+ return errors .Wrap (err , "failed to parse project ID " )
109
142
}
143
+ }
110
144
111
- // Check that exactly one of --project or --collection is specified.
112
- if projectID == "" && postmanCollectionID == "" {
113
- return errors .New ("exactly one of --project or --collection must be specified" )
145
+ // Look up existing trace by tags
146
+ if appendByTagFlag {
147
+ if outFlag .AkitaURI == nil {
148
+ return errors .New ("\" append-by-tag\" can only be used with a cloud-based trace" )
114
149
}
115
150
116
- // If --project was given, convert projectID to serviceID.
117
- var serviceID akid.ServiceID
118
- if projectID != "" {
119
- err := akid .ParseIDAs (projectID , & serviceID )
120
- if err != nil {
121
- return errors .Wrap (err , "failed to parse project ID" )
122
- }
151
+ if outFlag .AkitaURI .ObjectName != "" {
152
+ return errors .New ("Cannot specify a trace name together with \" append-by-tag\" " )
123
153
}
124
154
125
- // Look up existing trace by tags
126
- if appendByTagFlag {
127
- if outFlag .AkitaURI == nil {
128
- return errors .New ("\" append-by-tag\" can only be used with a cloud-based trace" )
129
- }
130
-
131
- if outFlag .AkitaURI .ObjectName != "" {
132
- return errors .New ("Cannot specify a trace name together with \" append-by-tag\" " )
133
- }
155
+ destURI , err := util .GetTraceURIByTags (rest .Domain ,
156
+ telemetry .GetClientID (),
157
+ outFlag .AkitaURI .ServiceName ,
158
+ traceTags ,
159
+ "append-by-tag" ,
160
+ )
161
+ if err != nil {
162
+ return err
163
+ }
164
+ if destURI .ObjectName != "" {
165
+ outFlag .AkitaURI = & destURI
166
+ }
167
+ }
134
168
135
- destURI , err := util .GetTraceURIByTags (rest .Domain ,
136
- telemetry .GetClientID (),
137
- outFlag .AkitaURI .ServiceName ,
138
- traceTags ,
139
- "append-by-tag" ,
140
- )
169
+ // Allow specification of an alternate rotation time, default 1h.
170
+ // We can rotate the trace if we're sending the output to a cloud-based trace.
171
+ // But, if the trace name is explicitly given, or selected by tag,
172
+ // or we're sending the output to a local file, then we cannot rotate.
173
+ traceRotateInterval := time .Duration (0 )
174
+ if (outFlag .AkitaURI != nil && outFlag .AkitaURI .ObjectName == "" ) || projectID != "" || postmanCollectionID != "" {
175
+ if traceRotateFlag != "" {
176
+ traceRotateInterval , err = time .ParseDuration (traceRotateFlag )
141
177
if err != nil {
142
- return err
143
- }
144
- if destURI .ObjectName != "" {
145
- outFlag .AkitaURI = & destURI
178
+ return errors .Wrap (err , "Failed to parse trace rotation interval." )
146
179
}
180
+ } else {
181
+ traceRotateInterval = apispec .DefaultTraceRotateInterval
147
182
}
183
+ }
148
184
149
- // Allow specification of an alternate rotation time, default 1h.
150
- // We can rotate the trace if we're sending the output to a cloud-based trace.
151
- // But, if the trace name is explicitly given, or selected by tag,
152
- // or we're sending the output to a local file, then we cannot rotate.
153
- traceRotateInterval := time .Duration (0 )
154
- if (outFlag .AkitaURI != nil && outFlag .AkitaURI .ObjectName == "" ) || projectID != "" || postmanCollectionID != "" {
155
- if traceRotateFlag != "" {
156
- traceRotateInterval , err = time .ParseDuration (traceRotateFlag )
157
- if err != nil {
158
- return errors .Wrap (err , "Failed to parse trace rotation interval." )
159
- }
160
- } else {
161
- traceRotateInterval = apispec .DefaultTraceRotateInterval
162
- }
163
- }
185
+ // Rate limit must be greater than zero.
186
+ if rateLimitFlag <= 0.0 {
187
+ rateLimitFlag = 1000.0
188
+ }
164
189
165
- // Rate limit must be greater than zero.
166
- if rateLimitFlag <= 0.0 {
167
- rateLimitFlag = 1000.0
190
+ // If we collect TLS information, we have to parse it
191
+ if collectTCPAndTLSReports {
192
+ if ! parseTLSHandshakes {
193
+ printer .Stderr .Warningf ("Overriding parse-tls-handshakes=false because TLS report collection is enabled.\n " )
194
+ parseTLSHandshakes = true
168
195
}
196
+ }
169
197
170
- // If we collect TLS information, we have to parse it
171
- if collectTCPAndTLSReports {
172
- if ! parseTLSHandshakes {
173
- printer .Stderr .Warningf ("Overriding parse-tls-handshakes=false because TLS report collection is enabled.\n " )
174
- parseTLSHandshakes = true
175
- }
176
- }
198
+ args := apidump.Args {
199
+ ClientID : telemetry .GetClientID (),
200
+ Domain : rest .Domain ,
201
+ Out : outFlag ,
202
+ PostmanCollectionID : postmanCollectionID ,
203
+ ServiceID : serviceID ,
204
+ Tags : traceTags ,
205
+ SampleRate : sampleRateFlag ,
206
+ WitnessesPerMinute : rateLimitFlag ,
207
+ Interfaces : interfacesFlag ,
208
+ Filter : filterFlag ,
209
+ PathExclusions : pathExclusionsFlag ,
210
+ HostExclusions : hostExclusionsFlag ,
211
+ PathAllowlist : pathAllowlistFlag ,
212
+ HostAllowlist : hostAllowlistFlag ,
213
+ ExecCommand : execCommandFlag ,
214
+ ExecCommandUser : execCommandUserFlag ,
215
+ Plugins : plugins ,
216
+ LearnSessionLifetime : traceRotateInterval ,
217
+ StatsLogDelay : statsLogDelay ,
218
+ TelemetryInterval : telemetryInterval ,
219
+ ProcFSPollingInterval : procFSPollingInterval ,
220
+ CollectTCPAndTLSReports : collectTCPAndTLSReports ,
221
+ ParseTLSHandshakes : parseTLSHandshakes ,
222
+ MaxWitnessSize_bytes : maxWitnessSize_bytes ,
223
+ DockerExtensionMode : dockerExtensionMode ,
224
+ HealthCheckPort : healthCheckPort ,
225
+ SendWitnessPayloads : sendWitnessPayloads ,
226
+ }
227
+ if err := apidump .Run (args ); err != nil {
228
+ return cmderr.AkitaErr {Err : err }
229
+ }
230
+ return nil
231
+ }
177
232
178
- args := apidump.Args {
179
- ClientID : telemetry .GetClientID (),
180
- Domain : rest .Domain ,
181
- Out : outFlag ,
182
- PostmanCollectionID : postmanCollectionID ,
183
- ServiceID : serviceID ,
184
- Tags : traceTags ,
185
- SampleRate : sampleRateFlag ,
186
- WitnessesPerMinute : rateLimitFlag ,
187
- Interfaces : interfacesFlag ,
188
- Filter : filterFlag ,
189
- PathExclusions : pathExclusionsFlag ,
190
- HostExclusions : hostExclusionsFlag ,
191
- PathAllowlist : pathAllowlistFlag ,
192
- HostAllowlist : hostAllowlistFlag ,
193
- ExecCommand : execCommandFlag ,
194
- ExecCommandUser : execCommandUserFlag ,
195
- Plugins : plugins ,
196
- LearnSessionLifetime : traceRotateInterval ,
197
- StatsLogDelay : statsLogDelay ,
198
- TelemetryInterval : telemetryInterval ,
199
- ProcFSPollingInterval : procFSPollingInterval ,
200
- CollectTCPAndTLSReports : collectTCPAndTLSReports ,
201
- ParseTLSHandshakes : parseTLSHandshakes ,
202
- MaxWitnessSize_bytes : maxWitnessSize_bytes ,
203
- DockerExtensionMode : dockerExtensionMode ,
204
- HealthCheckPort : healthCheckPort ,
205
- SendWitnessPayloads : sendWitnessPayloads ,
206
- }
207
- if err := apidump .Run (args ); err != nil {
208
- return cmderr.AkitaErr {Err : err }
209
- }
210
- return nil
211
- },
233
+ var Cmd = & cobra.Command {
234
+ Use : "apidump" ,
235
+ Short : "Capture requests/responses from network traffic." ,
236
+ Long : "Capture and store a sequence of requests/responses to a service by observing network traffic." ,
237
+ SilenceUsage : true ,
238
+ Args : cobra .ExactArgs (0 ),
239
+ RunE : apidumpRunWithoutAbnormalExit ,
212
240
}
213
241
214
242
func init () {
0 commit comments