10
10
using System . Threading ;
11
11
using System . Threading . Tasks ;
12
12
using Microsoft . Extensions . DependencyInjection ;
13
+ using Microsoft . Extensions . Logging ;
13
14
using Pulumi . Automation . Commands . Exceptions ;
14
15
using Pulumi . Automation . Events ;
15
16
using Pulumi . Automation . Exceptions ;
16
17
using Semver ;
18
+ using Serilog ;
19
+ using Serilog . Extensions . Logging ;
17
20
using Xunit ;
21
+ using Xunit . Abstractions ;
22
+ using ILogger = Microsoft . Extensions . Logging . ILogger ;
18
23
19
24
namespace Pulumi . Automation . Tests
20
25
{
@@ -50,6 +55,20 @@ private static string NormalizeConfigKey(string key, string projectName)
50
55
return string . Empty ;
51
56
}
52
57
58
+ private ILogger TestLogger { get ; }
59
+
60
+ public LocalWorkspaceTests ( ITestOutputHelper output )
61
+ {
62
+ var logger = new LoggerConfiguration ( )
63
+ . MinimumLevel . Verbose ( )
64
+ . WriteTo . TestOutput ( output , outputTemplate : "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" )
65
+ . CreateLogger ( ) ;
66
+
67
+ var loggerFactory = new SerilogLoggerFactory ( logger ) ;
68
+
69
+ TestLogger = loggerFactory . CreateLogger < LocalWorkspaceTests > ( ) ;
70
+ }
71
+
53
72
[ Theory ]
54
73
[ InlineData ( "yaml" ) ]
55
74
[ InlineData ( "yml" ) ]
@@ -725,27 +744,27 @@ public async Task HandlesEvents()
725
744
try
726
745
{
727
746
// pulumi preview
728
- var previewResult = await RunCommand < PreviewResult , PreviewOptions > ( stack . PreviewAsync , "preview" ) ;
747
+ var previewResult = await RunCommand ( stack . PreviewAsync , "preview" , new PreviewOptions ( ) ) ;
729
748
Assert . True ( previewResult . ChangeSummary . TryGetValue ( OperationType . Create , out var createCount ) ) ;
730
749
Assert . Equal ( 1 , createCount ) ;
731
750
732
751
// pulumi up
733
- var upResult = await RunCommand < UpResult , UpOptions > ( stack . UpAsync , "up" ) ;
752
+ var upResult = await RunCommand ( stack . UpAsync , "up" , new UpOptions ( ) ) ;
734
753
Assert . Equal ( UpdateKind . Update , upResult . Summary . Kind ) ;
735
754
Assert . Equal ( UpdateState . Succeeded , upResult . Summary . Result ) ;
736
755
737
756
// pulumi preview
738
- var previewResultAgain = await RunCommand < PreviewResult , PreviewOptions > ( stack . PreviewAsync , "preview" ) ;
757
+ var previewResultAgain = await RunCommand ( stack . PreviewAsync , "preview" , new PreviewOptions ( ) ) ;
739
758
Assert . True ( previewResultAgain . ChangeSummary . TryGetValue ( OperationType . Same , out var sameCount ) ) ;
740
759
Assert . Equal ( 1 , sameCount ) ;
741
760
742
761
// pulumi refresh
743
- var refreshResult = await RunCommand < UpdateResult , RefreshOptions > ( stack . RefreshAsync , "refresh" ) ;
762
+ var refreshResult = await RunCommand ( stack . RefreshAsync , "refresh" , new RefreshOptions ( ) ) ;
744
763
Assert . Equal ( UpdateKind . Refresh , refreshResult . Summary . Kind ) ;
745
764
Assert . Equal ( UpdateState . Succeeded , refreshResult . Summary . Result ) ;
746
765
747
766
// pulumi destroy
748
- var destroyResult = await RunCommand < UpdateResult , DestroyOptions > ( stack . DestroyAsync , "destroy" ) ;
767
+ var destroyResult = await RunCommand ( stack . DestroyAsync , "destroy" , new DestroyOptions ( ) ) ;
749
768
Assert . Equal ( UpdateKind . Destroy , destroyResult . Summary . Kind ) ;
750
769
Assert . Equal ( UpdateState . Succeeded , destroyResult . Summary . Result ) ;
751
770
}
@@ -754,12 +773,12 @@ public async Task HandlesEvents()
754
773
await stack . Workspace . RemoveStackAsync ( stackName ) ;
755
774
}
756
775
757
- static async Task < T > RunCommand < T , TOptions > ( Func < TOptions , CancellationToken , Task < T > > func , string command )
776
+ static async Task < T > RunCommand < T , TOptions > ( Func < TOptions , CancellationToken , Task < T > > func , string command , TOptions options )
758
777
where TOptions : UpdateOptions , new ( )
759
778
{
760
779
var events = new List < EngineEvent > ( ) ;
761
-
762
- var result = await func ( new TOptions { OnEvent = events . Add } , CancellationToken . None ) ;
780
+ options . OnEvent = events . Add ;
781
+ var result = await func ( options , CancellationToken . None ) ;
763
782
764
783
var seenSummaryEvent = events . Any ( @event => @event . SummaryEvent != null ) ;
765
784
var seenCancelEvent = events . Any ( @event => @event . CancelEvent != null ) ;
@@ -872,17 +891,17 @@ public async Task ConfigSecretWarnings()
872
891
await stack . SetAllConfigAsync ( config ) ;
873
892
874
893
// pulumi preview
875
- await RunCommand < PreviewResult , PreviewOptions > ( stack . PreviewAsync , "preview" ) ;
894
+ await RunCommand ( stack . PreviewAsync , "preview" , new PreviewOptions ( ) ) ;
876
895
877
896
// pulumi up
878
- await RunCommand < UpResult , UpOptions > ( stack . UpAsync , "up" ) ;
897
+ await RunCommand ( stack . UpAsync , "up" , new UpOptions ( ) ) ;
879
898
}
880
899
finally
881
900
{
882
901
await stack . Workspace . RemoveStackAsync ( stackName ) ;
883
902
}
884
903
885
- static async Task < T > RunCommand < T , TOptions > ( Func < TOptions , CancellationToken , Task < T > > func , string command )
904
+ static async Task < T > RunCommand < T , TOptions > ( Func < TOptions , CancellationToken , Task < T > > func , string command , TOptions options )
886
905
where TOptions : UpdateOptions , new ( )
887
906
{
888
907
var expectedWarnings = new [ ]
@@ -927,17 +946,14 @@ static async Task<T> RunCommand<T, TOptions>(Func<TOptions, CancellationToken, T
927
946
} ;
928
947
929
948
var events = new List < DiagnosticEvent > ( ) ;
930
-
931
- var result = await func ( new TOptions
949
+ options . OnEvent = @event =>
932
950
{
933
- OnEvent = @event =>
951
+ if ( @event . DiagnosticEvent ? . Severity == "warning" )
934
952
{
935
- if ( @event . DiagnosticEvent ? . Severity == "warning" )
936
- {
937
- events . Add ( @event . DiagnosticEvent ) ;
938
- }
953
+ events . Add ( @event . DiagnosticEvent ) ;
939
954
}
940
- } , CancellationToken . None ) ;
955
+ } ;
956
+ var result = await func ( options , CancellationToken . None ) ;
941
957
942
958
foreach ( var expected in expectedWarnings )
943
959
{
@@ -1467,10 +1483,102 @@ await Assert.ThrowsAsync<ProjectSettingsConflictException>(() =>
1467
1483
) ;
1468
1484
}
1469
1485
1486
+ [ Fact ]
1487
+ public async Task InlineProgramLoggerCanBeOverridden ( )
1488
+ {
1489
+ var program = PulumiFn . Create ( ( ) =>
1490
+ {
1491
+ Log . Debug ( "test" ) ;
1492
+ } ) ;
1493
+
1494
+ var loggerWasInvoked = false ;
1495
+ var logger = new CustomLogger ( ( ) => loggerWasInvoked = true ) ;
1496
+
1497
+ var stackName = $ "{ RandomStackName ( ) } ";
1498
+ var projectName = "inline_logger_override" ;
1499
+
1500
+ using var stack = await LocalWorkspace . CreateOrSelectStackAsync (
1501
+ new InlineProgramArgs ( projectName , stackName , program )
1502
+ {
1503
+ Logger = logger ,
1504
+ } ) ;
1505
+
1506
+ // make sure workspace logger is used
1507
+ await stack . PreviewAsync ( ) ;
1508
+ Assert . True ( loggerWasInvoked ) ;
1509
+
1510
+ // preview logger is used
1511
+ loggerWasInvoked = false ;
1512
+ stack . Workspace . Logger = null ;
1513
+ await stack . PreviewAsync ( new PreviewOptions
1514
+ {
1515
+ Logger = logger ,
1516
+ } ) ;
1517
+ Assert . True ( loggerWasInvoked ) ;
1518
+
1519
+ // up logger is used
1520
+ loggerWasInvoked = false ;
1521
+ await stack . UpAsync ( new UpOptions
1522
+ {
1523
+ Logger = logger ,
1524
+ } ) ;
1525
+ Assert . True ( loggerWasInvoked ) ;
1526
+
1527
+ await stack . DestroyAsync ( ) ;
1528
+ }
1529
+
1530
+ [ Fact ]
1531
+ public async Task InlineProgramLoggerCanRedirectToTestOutput ( )
1532
+ {
1533
+ var program = PulumiFn . Create ( ( ) =>
1534
+ {
1535
+ Log . Info ( "Pulumi.Log calls appear in test output" ) ;
1536
+ } ) ;
1537
+
1538
+ var stackName = $ "{ RandomStackName ( ) } ";
1539
+ var projectName = "inline_logger_test_output" ;
1540
+
1541
+ using var stack = await LocalWorkspace . CreateOrSelectStackAsync (
1542
+ new InlineProgramArgs ( projectName , stackName , program )
1543
+ {
1544
+ Logger = TestLogger
1545
+ } ) ;
1546
+
1547
+ TestLogger . LogInformation ( "Previewing stack..." ) ;
1548
+ await stack . PreviewAsync ( ) ;
1549
+
1550
+ TestLogger . LogInformation ( "Updating stack..." ) ;
1551
+ await stack . UpAsync ( ) ;
1552
+
1553
+ TestLogger . LogInformation ( "Destroying stack..." ) ;
1554
+ await stack . DestroyAsync ( ) ;
1555
+ }
1556
+
1470
1557
private string ResourcePath ( string path , [ CallerFilePath ] string pathBase = "LocalWorkspaceTests.cs" )
1471
1558
{
1472
1559
var dir = Path . GetDirectoryName ( pathBase ) ?? "." ;
1473
1560
return Path . Combine ( dir , path ) ;
1474
1561
}
1562
+
1563
+ private class CustomLogger : ILogger
1564
+ {
1565
+ private readonly Action _action ;
1566
+
1567
+ public CustomLogger ( Action action )
1568
+ {
1569
+ _action = action ;
1570
+ }
1571
+
1572
+ public IDisposable BeginScope < TState > ( TState state )
1573
+ {
1574
+ throw new NotImplementedException ( ) ;
1575
+ }
1576
+
1577
+ public bool IsEnabled ( LogLevel logLevel )
1578
+ => true ;
1579
+
1580
+ public void Log < TState > ( LogLevel logLevel , EventId eventId , TState state , Exception exception , Func < TState , Exception , string > formatter )
1581
+ => _action ( ) ;
1582
+ }
1475
1583
}
1476
1584
}
0 commit comments