Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5bfa74b

Browse files
Extensive update
Add service details. Extra Go formatting. Use null delimiters. Add tasks under service.
1 parent d83c017 commit 5bfa74b

File tree

8 files changed

+602
-44
lines changed

8 files changed

+602
-44
lines changed

‎DockerClient.cs‎

Lines changed: 203 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4+
using System.Linq;
45
using System.Text;
56

67
namespace StackDeployCheck
@@ -16,14 +17,32 @@ public StackState GetCurrentState(string stackName)
1617
};
1718

1819
GetStackTasks(stackName);
20+
GetStackServices(stackName);
21+
22+
foreach (var service in currentStackState.Services)
23+
{
24+
GetServiceStates(service.Name);
25+
}
26+
1927

2028
return currentStackState;
2129
}
2230

23-
public void GetStackTasks(string stackName)
31+
private void GetServiceStates(string serviceName)
2432
{
25-
var formatString = "{{.ID}} {{.Name}} {{.Image}} {{.Node}} {{.DesiredState}} [{{.CurrentState}}] [{{.Error}}]";
26-
ProcessStartInfo processStartInfo = new ProcessStartInfo("docker", $"stack ps {stackName} --no-trunc --format \"{formatString}\"")
33+
var formatString = "{{.Spec.Name}} " +
34+
"{{if not .UpdateStatus}}" +
35+
"NotUpdated" +
36+
"{{else}}" +
37+
"{{if eq .UpdateStatus.State \\\"rollback_started\\\"}}" +
38+
"RollbackStarted" +
39+
"{{else if eq .UpdateStatus.State \\\"rollback_completed\\\"}}" +
40+
"RollbackCompleted" +
41+
"{{else}}" +
42+
"{{.UpdateStatus.State}}" +
43+
"{{end}}" +
44+
"{{end}}";
45+
ProcessStartInfo processStartInfo = new ProcessStartInfo("docker", $"service inspect {serviceName} --format \"{formatString}\"")
2746
{
2847
RedirectStandardError = true,
2948
RedirectStandardOutput = true,
@@ -37,7 +56,7 @@ public void GetStackTasks(string stackName)
3756
EnableRaisingEvents = true
3857
})
3958
{
40-
process.OutputDataReceived += Process_OutputDataReceived;
59+
process.OutputDataReceived += Process_OutputServiceStateDataReceived;
4160
process.ErrorDataReceived += Process_ErrorDataReceived;
4261
//process.Exited += Process_Exited;
4362
process.Start();
@@ -48,53 +67,139 @@ public void GetStackTasks(string stackName)
4867
}
4968
}
5069

70+
private void Process_OutputServiceStateDataReceived(object sender, DataReceivedEventArgs e)
71+
{
72+
if (e.Data == String.Empty
73+
|| e.Data == null)
74+
{
75+
return;
76+
}
77+
78+
string currentLine = e.Data;
5179

52-
private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
80+
if (currentLine.StartsWith("Status: Template parsing error", StringComparison.InvariantCultureIgnoreCase))
81+
{
82+
return;
83+
}
84+
85+
var serviceStateElements = currentLine.Split(" ");
86+
if (serviceStateElements.Length < 2)
87+
{
88+
return;
89+
}
90+
91+
// "{{.Spec.Name}} {{.UpdateStatus.State}} {{.UpdateStatus.CompletedAt}} {{.UpdateStatus.Message}}";
92+
93+
string name = serviceStateElements[0];
94+
string state = serviceStateElements[1];
95+
96+
if (state.Equals("completed_rollback"))
97+
{
98+
state = "RolledBack";
99+
}
100+
101+
var service = currentStackState.Services.FirstOrDefault<DockerService>(ds => ds.Name == name);
102+
if (service != null)
103+
{
104+
UpdateState updateState;
105+
if (Enum.TryParse<UpdateState>(state, true, out updateState))
106+
{
107+
service.UpdateState = updateState;
108+
}
109+
else
110+
{
111+
Console.Error.WriteLine($"ERROR: unable to parse service update state {state}");
112+
service.UpdateState = UpdateState.Unknown;
113+
}
114+
}
115+
}
116+
117+
public void GetStackTasks(string stackName)
53118
{
54-
if (!String.IsNullOrEmpty(e.Data))
119+
var formatString = "{{.ID}}{{\\\"\\x00\\\"}}{{.Name}}{{\\\"\\x00\\\"}}{{.Image}}{{\\\"\\x00\\\"}}{{.Node}}{{\\\"\\x00\\\"}}{{.DesiredState}}{{\\\"\\x00\\\"}}{{.CurrentState}}{{\\\"\\x00\\\"}}{{.Error}}";
120+
ProcessStartInfo processStartInfo = new ProcessStartInfo("docker", $"stack ps {stackName} --no-trunc --format \"{formatString}\"")
121+
{
122+
RedirectStandardError = true,
123+
RedirectStandardOutput = true,
124+
RedirectStandardInput = true,
125+
UseShellExecute = false,
126+
CreateNoWindow = true
127+
};
128+
using (Process process = new Process()
129+
{
130+
StartInfo = processStartInfo,
131+
EnableRaisingEvents = true
132+
})
55133
{
56-
Console.Error.WriteLineAsync($"ERROR: {e.Data}");
134+
process.OutputDataReceived += Process_OutputTasksDataReceived;
135+
process.ErrorDataReceived += Process_ErrorDataReceived;
136+
//process.Exited += Process_Exited;
137+
process.Start();
138+
process.BeginOutputReadLine();
139+
process.BeginErrorReadLine();
140+
//process.WaitForExit(waitTimeout);
141+
process.WaitForExit();
57142
}
58143
}
59144

60-
private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
145+
private void Process_OutputTasksDataReceived(object sender, DataReceivedEventArgs e)
61146
{
62147
if (e.Data == String.Empty
63148
|| e.Data == null)
64149
{
65150
return;
66151
}
67-
//if (e.Data.StartsWith("ID "))
68-
//{
69-
// //headerLine = e.Data;
70-
// return;
71-
//}
72-
string currentLine = e.Data;
73152

74-
var currentStart = currentLine.IndexOf("[") + 1;
75-
var currentEnd = currentLine.IndexOf("]");
76-
var errorStart = currentLine.IndexOf("[", currentEnd) + 1;
77-
var errorEnd = currentLine.LastIndexOf("]");
153+
var taskElements = e.Data.Split('\x00');
154+
if (taskElements.Length < 7)
155+
{
156+
return;
157+
}
78158

79-
var taskElements = e.Data.Split(" ");
80159
var dockerTask = new DockerTask()
81160
{
82161
Id = taskElements[0],
83162
Name = taskElements[1],
84163
Image = taskElements[2],
85164
Node = taskElements[3],
86-
DesiredState = taskElements[4],
87-
CurrentState = currentLine.Substring(currentStart, currentEnd - currentStart),
88-
Error = currentLine.Substring(errorStart, errorEnd - errorStart)
165+
Error = taskElements[6]
89166
};
167+
dockerTask.SetDesiredState(taskElements[4]);
168+
dockerTask.SetCurrentState(taskElements[5]);
90169

91-
if (dockerTask.DesiredState == "Ready"
92-
|| dockerTask.DesiredState == "Running")
93-
{
94-
dockerTask.IsCurrent = true;
95-
}
96170
currentStackState.Tasks.Add(dockerTask);
97171

172+
//if (e.Data.StartsWith("ID "))
173+
//{
174+
// //headerLine = e.Data;
175+
// return;
176+
//}
177+
//string currentLine = e.Data;
178+
179+
//var currentStart = currentLine.IndexOf("[") + 1;
180+
//var currentEnd = currentLine.IndexOf("]");
181+
//var errorStart = currentLine.IndexOf("[", currentEnd) + 1;
182+
//var errorEnd = currentLine.LastIndexOf("]");
183+
184+
//var taskElements = e.Data.Split(" ");
185+
//if (taskElements.Length < 5)
186+
//{
187+
// return;
188+
//}
189+
190+
//var dockerTask = new DockerTask()
191+
//{
192+
// Id = taskElements[0],
193+
// Name = taskElements[1],
194+
// Image = taskElements[2],
195+
// Node = taskElements[3],
196+
// Error = currentLine.Substring(errorStart, errorEnd - errorStart)
197+
//};
198+
//dockerTask.SetDesiredState(taskElements[4]);
199+
//dockerTask.SetCurrentState(currentLine.Substring(currentStart, currentEnd - currentStart));
200+
201+
//currentStackState.Tasks.Add(dockerTask);
202+
98203
//Console.Error.WriteLineAsync($"OUT: {e.Data}");
99204
//Console.Out.WriteLine(dockerTask.Id);
100205
//Console.Out.WriteLine($"{dockerTask.IsCurrent} {dockerTask.Name}");
@@ -103,7 +208,77 @@ private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
103208
//Console.Out.WriteLine(dockerTask.DesiredState);
104209
//Console.Out.WriteLine(dockerTask.CurrentState);
105210
//Console.Out.WriteLine(dockerTask.Error);
106-
//Console.Out.WriteLine("");
211+
//Console.Out.WriteLine("--------------------------------------------------");
212+
}
213+
public void GetStackServices(string stackName)
214+
{
215+
var formatString = "{{.ID}}{{\\\"\\x00\\\"}}{{.Name}}{{\\\"\\x00\\\"}}{{.Mode}}{{\\\"\\x00\\\"}}{{.Replicas}}{{\\\"\\x00\\\"}}{{.Image}}{{\\\"\\x00\\\"}}{{.Ports}}";
216+
ProcessStartInfo processStartInfo = new ProcessStartInfo("docker", $"stack services {stackName} --format \"{formatString}\"")
217+
{
218+
RedirectStandardError = true,
219+
RedirectStandardOutput = true,
220+
RedirectStandardInput = true,
221+
UseShellExecute = false,
222+
CreateNoWindow = true
223+
};
224+
using (Process process = new Process()
225+
{
226+
StartInfo = processStartInfo,
227+
EnableRaisingEvents = true
228+
})
229+
{
230+
process.OutputDataReceived += Process_OutputServicesDataReceived;
231+
process.ErrorDataReceived += Process_ErrorDataReceived;
232+
//process.Exited += Process_Exited;
233+
process.Start();
234+
process.BeginOutputReadLine();
235+
process.BeginErrorReadLine();
236+
//process.WaitForExit(waitTimeout);
237+
process.WaitForExit();
238+
}
239+
240+
//
107241
}
242+
243+
private void Process_OutputServicesDataReceived(object sender, DataReceivedEventArgs e)
244+
{
245+
if (e.Data == String.Empty
246+
|| e.Data == null)
247+
{
248+
return;
249+
}
250+
string currentLine = e.Data;
251+
var serviceElements = currentLine.Split("\x00");
252+
if (serviceElements.Length < 6)
253+
{
254+
return;
255+
}
256+
257+
var dockerService = new DockerService()
258+
{
259+
Id = serviceElements[0],
260+
Name = serviceElements[1],
261+
Mode = serviceElements[2],
262+
Image = serviceElements[4],
263+
Ports = serviceElements[5]
264+
};
265+
dockerService.SetReplicas(serviceElements[3]);
266+
currentStackState.Services.Add(dockerService);
267+
}
268+
private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
269+
{
270+
if (!String.IsNullOrEmpty(e.Data))
271+
{
272+
// don't log if no tasks found
273+
if (e.Data.StartsWith("nothing found in stack", StringComparison.InvariantCultureIgnoreCase)
274+
|| e.Data.StartsWith("Status: Template parsing error: template: :1:30: executing", StringComparison.InvariantCultureIgnoreCase))
275+
{
276+
return;
277+
}
278+
Console.Out.WriteLineAsync($"ERROR FROM DOCKER: {e.Data}");
279+
}
280+
}
281+
282+
108283
}
109284
}

‎DockerService.cs‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace StackDeployCheck
6+
{
7+
public class DockerService
8+
{
9+
public string Id { get; internal set; }
10+
public string Name { get; internal set; }
11+
public string Mode { get; internal set; }
12+
public string ReplicasDesc { get; internal set; }
13+
public int CurrentReplicas { get; internal set; }
14+
public int DesiredReplicas { get; internal set; }
15+
public string Image { get; internal set; }
16+
public string Ports { get; internal set; }
17+
public UpdateState UpdateState { get; internal set; }
18+
public string LastUpdated { get; internal set; }
19+
public string UpdateMessage { get; internal set; }
20+
21+
public int TotalTasks { get; internal set; }
22+
public int StableTasks { get; internal set; }
23+
public int CompleteTasks { get; internal set; }
24+
25+
public DockerService()
26+
{
27+
UpdateState = UpdateState.NotUpdated;
28+
}
29+
30+
public void SetReplicas(string replicasString)
31+
{
32+
ReplicasDesc = replicasString;
33+
var parts = replicasString.Split(@"/");
34+
CurrentReplicas = 0;
35+
DesiredReplicas = 0;
36+
int current;
37+
if (!int.TryParse(parts[0], out current))
38+
{
39+
Console.Error.WriteLine($"ERROR: unable to parse current replicas {replicasString}");
40+
return;
41+
}
42+
CurrentReplicas = current;
43+
44+
int desired;
45+
if (!int.TryParse(parts[1], out desired))
46+
{
47+
Console.Error.WriteLine($"ERROR: unable to parse desired replicas {replicasString}");
48+
return;
49+
}
50+
DesiredReplicas = desired;
51+
}
52+
}
53+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /