11using System . CommandLine . Invocation ;
2- using System . Reflection ;
32using System . Text ;
4- using System . Text . Json ;
5- using System . Text . Json . Serialization ;
63using Azure . Sdk . Tools . SecretRotation . Configuration ;
74using Azure . Sdk . Tools . SecretRotation . Core ;
85
@@ -18,93 +15,80 @@ protected override async Task HandleCommandAsync(ILogger logger, RotationConfigu
1815 InvocationContext invocationContext )
1916 {
2017 var timeProvider = new TimeProvider ( ) ;
21- IEnumerable < RotationPlan > plans = rotationConfiguration . GetAllRotationPlans ( logger , timeProvider ) ;
18+ RotationPlan [ ] plans = rotationConfiguration . GetAllRotationPlans ( logger , timeProvider ) . ToArray ( ) ;
2219
23- List < ( RotationPlan Plan , RotationPlanStatus Status ) > statuses = new ( ) ;
20+ logger . LogInformation ( $ "Getting status for { plans . Length } plans" ) ;
2421
25- foreach ( RotationPlan plan in plans )
26- {
27- logger . LogInformation ( $ "Getting status for plan '{ plan . Name } '") ;
28- RotationPlanStatus status = await plan . GetStatusAsync ( ) ;
29-
30- if ( logger . IsEnabled ( LogLevel . Debug ) )
31- {
32- var builder = new StringBuilder ( ) ;
33-
34- builder . AppendLine ( $ " Plan:") ;
35- builder . AppendLine ( $ " RotationPeriod: { plan . RotationPeriod } ") ;
36- builder . AppendLine ( $ " RotationThreshold: { plan . RotationThreshold } ") ;
37- builder . AppendLine ( $ " RevokeAfterPeriod: { plan . RevokeAfterPeriod } ") ;
38-
39- builder . AppendLine ( $ " Status:") ;
40- builder . AppendLine ( $ " ExpirationDate: { status . ExpirationDate } ") ;
41- builder . AppendLine ( $ " State: { status . State } ") ;
42- builder . AppendLine ( $ " RequiresRevocation: { status . RequiresRevocation } ") ;
43- builder . AppendLine ( $ " Exception: { status . Exception ? . Message } ") ;
44-
45- logger . LogDebug ( builder . ToString ( ) ) ;
46- }
22+ ( RotationPlan Plan , RotationPlanStatus Status ) [ ] statuses = await plans
23+ . Select ( async plan => {
24+ logger . LogDebug ( $ "Getting status for plan '{ plan . Name } '.") ;
25+ return ( plan , await plan . GetStatusAsync ( ) ) ;
26+ } )
27+ . LimitConcurrencyAsync ( 10 ) ;
4728
4829
49- statuses . Add ( ( plan , status ) ) ;
50- }
51-
5230 var plansBuyState = statuses . GroupBy ( x => x . Status . State )
5331 . ToDictionary ( x => x . Key , x => x . ToArray ( ) ) ;
5432
55- var statusBuilder = new StringBuilder ( ) ;
5633
57- void AppendStatusSection ( RotationState state , string header )
34+ void LogStatusSection ( RotationState state , string header )
5835 {
59- if ( ! plansBuyState . TryGetValue ( RotationState . Expired , out var matchingPlans ) )
36+ if ( ! plansBuyState . TryGetValue ( state , out var matchingPlans ) )
6037 {
6138 return ;
6239 }
6340
64- statusBuilder . AppendLine ( ) ;
65- statusBuilder . AppendLine ( header ) ;
41+ logger . LogInformation ( $ " \n { header } " ) ;
42+
6643 foreach ( ( RotationPlan plan , RotationPlanStatus status ) in matchingPlans )
6744 {
68- foreach ( string line in GetPlanStatusLine ( plan , status ) . Split ( "\n " ) )
45+ var builder = new StringBuilder ( ) ;
46+ var debugBuilder = new StringBuilder ( ) ;
47+
48+ builder . Append ( $ " { plan . Name } - ") ;
49+ DateTimeOffset ? expirationDate = status . ExpirationDate ;
50+ if ( expirationDate . HasValue )
51+ {
52+ builder . AppendLine ( $ "{ expirationDate } ({ FormatTimeSpan ( expirationDate . Value . Subtract ( DateTimeOffset . UtcNow ) ) } )") ;
53+ }
54+ else
6955 {
70- statusBuilder . Append ( " " ) ;
71- statusBuilder . AppendLine ( line ) ;
56+ builder . AppendLine ( "no expiration date" ) ;
7257 }
58+
59+ debugBuilder . AppendLine ( $ " Plan:") ;
60+ debugBuilder . AppendLine ( $ " Rotation Period: { plan . RotationPeriod } ") ;
61+ debugBuilder . AppendLine ( $ " Rotation Threshold: { plan . RotationThreshold } ") ;
62+ debugBuilder . AppendLine ( $ " Warning Threshold: { plan . WarningThreshold } ") ;
63+ debugBuilder . AppendLine ( $ " Revoke After Period: { plan . RevokeAfterPeriod } ") ;
64+ debugBuilder . AppendLine ( $ " Status:") ;
65+ debugBuilder . AppendLine ( $ " Expiration Date: { status . ExpirationDate } ") ;
66+ debugBuilder . AppendLine ( $ " State: { status . State } ") ;
67+ debugBuilder . AppendLine ( $ " Requires Revocation: { status . RequiresRevocation } ") ;
68+
69+ if ( status . Exception != null )
70+ {
71+ builder . AppendLine ( $ " Exception:") ;
72+ builder . AppendLine ( $ " { status . Exception . Message } ") ;
73+ }
74+
75+ logger . LogInformation ( builder . ToString ( ) ) ;
76+ logger . LogDebug ( debugBuilder . ToString ( ) ) ;
7377 }
7478 }
7579
76- AppendStatusSection ( RotationState . Expired , "Expired:" ) ;
77- AppendStatusSection ( RotationState . Warning , "Expiring:" ) ;
78- AppendStatusSection ( RotationState . Rotate , "Should Rotate:" ) ;
79- AppendStatusSection ( RotationState . UpToDate , "Up-to-date:" ) ;
80- AppendStatusSection ( RotationState . Error , "Error reading plan status:" ) ;
81-
82- logger . LogInformation ( statusBuilder . ToString ( ) ) ;
80+ LogStatusSection ( RotationState . Expired , "Expired:" ) ;
81+ LogStatusSection ( RotationState . Warning , "Expiring:" ) ;
82+ LogStatusSection ( RotationState . Rotate , "Should Rotate:" ) ;
83+ LogStatusSection ( RotationState . UpToDate , "Up-to-date:" ) ;
84+ LogStatusSection ( RotationState . Error , "Error reading plan status:" ) ;
8385
8486 if ( statuses . Any ( x => x . Status . State is RotationState . Expired or RotationState . Warning ) )
8587 {
8688 invocationContext . ExitCode = 1 ;
8789 }
8890 }
8991
90- private static string GetPlanStatusLine ( RotationPlan plan , RotationPlanStatus status )
91- {
92- if ( status . Exception != null )
93- {
94- return $ "{ plan . Name } :\n { status . Exception . Message } ";
95- }
96-
97- DateTimeOffset ? expirationDate = status . ExpirationDate ;
98-
99- DateTimeOffset now = DateTimeOffset . UtcNow ;
100-
101- string expiration = expirationDate . HasValue
102- ? $ "{ FormatTimeSpan ( expirationDate . Value . Subtract ( now ) ) } "
103- : "No expiration date" ;
104-
105- return $ "{ plan . Name } - { expiration } / ({ FormatTimeSpan ( plan . RotationPeriod ) } @ { FormatTimeSpan ( plan . RotationThreshold ) } )";
106- }
107-
10892 private static string FormatTimeSpan ( TimeSpan timeSpan )
10993 {
11094 if ( timeSpan == TimeSpan . Zero )
0 commit comments