-
Notifications
You must be signed in to change notification settings - Fork 235
Expand file tree
/
Copy pathStatusCommand.cs
More file actions
131 lines (109 loc) · 4.61 KB
/
StatusCommand.cs
File metadata and controls
131 lines (109 loc) · 4.61 KB
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
using System.CommandLine.Invocation;
using System.Text;
using Azure.Sdk.Tools.SecretRotation.Configuration;
using Azure.Sdk.Tools.SecretRotation.Core;
namespace Azure.Sdk.Tools.SecretManagement.Cli.Commands;
public class StatusCommand : RotationCommandBase
{
public StatusCommand() : base("status", "Show secret rotation status")
{
}
protected override async Task HandleCommandAsync(ILogger logger, RotationConfiguration rotationConfiguration,
InvocationContext invocationContext)
{
var timeProvider = new TimeProvider();
RotationPlan[] plans = rotationConfiguration.GetAllRotationPlans(logger, timeProvider).ToArray();
logger.LogInformation($"Getting status for {plans.Length} plans");
(RotationPlan Plan, RotationPlanStatus Status)[] statuses = await plans
.Select(async plan => {
logger.LogDebug($"Getting status for plan '{plan.Name}'.");
return (plan, await plan.GetStatusAsync());
})
.LimitConcurrencyAsync(10);
var plansBuyState = statuses.GroupBy(x => x.Status.State)
.ToDictionary(x => x.Key, x => x.ToArray());
void LogStatusSection(RotationState state, string header)
{
if (!plansBuyState.TryGetValue(state, out var matchingPlans))
{
return;
}
logger.LogInformation($"\n{header}");
foreach ((RotationPlan plan, RotationPlanStatus status) in matchingPlans)
{
var builder = new StringBuilder();
var debugBuilder = new StringBuilder();
builder.Append($" {plan.Name} - ");
DateTimeOffset? expirationDate = status.ExpirationDate;
if (expirationDate.HasValue)
{
builder.AppendLine($"{expirationDate} ({FormatTimeSpan(expirationDate.Value.Subtract(DateTimeOffset.UtcNow))})");
}
else
{
builder.AppendLine("no expiration date");
}
debugBuilder.AppendLine($" Plan:");
debugBuilder.AppendLine($" Rotation Period: {plan.RotationPeriod}");
debugBuilder.AppendLine($" Rotation Threshold: {plan.RotationThreshold}");
debugBuilder.AppendLine($" Warning Threshold: {plan.WarningThreshold}");
debugBuilder.AppendLine($" Revoke After Period: {plan.RevokeAfterPeriod}");
debugBuilder.AppendLine($" Status:");
debugBuilder.AppendLine($" Expiration Date: {status.ExpirationDate}");
debugBuilder.AppendLine($" State: {status.State}");
debugBuilder.AppendLine($" Requires Revocation: {status.RequiresRevocation}");
if (status.Exception != null)
{
builder.AppendLine($" Exception:");
builder.AppendLine($" {status.Exception.Message}");
}
logger.LogInformation(builder.ToString());
logger.LogDebug(debugBuilder.ToString());
}
}
LogStatusSection(RotationState.Expired, "Expired:");
LogStatusSection(RotationState.Warning, "Expiring:");
LogStatusSection(RotationState.Rotate, "Should Rotate:");
LogStatusSection(RotationState.UpToDate, "Up-to-date:");
LogStatusSection(RotationState.Error, "Error reading plan status:");
if (statuses.Any(x => x.Status.State is RotationState.Expired or RotationState.Warning))
{
invocationContext.ExitCode = 1;
}
}
private static string FormatTimeSpan(TimeSpan timeSpan)
{
if (timeSpan == TimeSpan.Zero)
{
return "0d";
}
StringBuilder builder = new StringBuilder();
if (timeSpan.Days > 0)
{
builder.Append(timeSpan.Days);
builder.Append('d');
}
if (timeSpan.Days < 2 && timeSpan.TotalDays - timeSpan.Days > 0)
{
if (timeSpan.Hours > 0)
{
if (builder.Length > 0)
{
builder.Append(' ');
}
builder.Append(timeSpan.Hours);
builder.Append('h');
}
if (timeSpan.Minutes > 0)
{
if (builder.Length > 0)
{
builder.Append(' ');
}
builder.Append(timeSpan.Minutes);
builder.Append('m');
}
}
return builder.ToString();
}
}