Skip to content

Commit 14d4d3f

Browse files
authored
Enable setting the log verbosity level of Pulumi CLI for a stack/workspace (#824)
### Proposed changes This PR adds a new optional Stack spec field: `PulumiLogVerbosity`. This field determines the log verbosity level of pulumi up/down/refresh operations. ### Related issues (optional) Closes: #823
1 parent 67ba387 commit 14d4d3f

17 files changed

+218
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
- Garbage collection for Update objects. [#810](https://github.com/pulumi/pulumi-kubernetes-operator/pull/810)
1313
- Use correct logic for OwnerReferencesChangedPredicate. [#815](https://github.com/pulumi/pulumi-kubernetes-operator/pull/815)
1414
- Use audience-scoped access token. [#816](https://github.com/pulumi/pulumi-kubernetes-operator/pull/816)
15+
- Enable setting the log verbosity of Pulumi CLI operations for a given workspace. [#824](https://github.com/pulumi/pulumi-kubernetes-operator/pull/824)
1516

1617
## 2.0.0-beta.3 (2024-11-27)
1718

agent/cmd/serve.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var (
5151
_audiences []string
5252
_workspaceNamespace string
5353
_workspaceName string
54+
_pulumiLogLevel uint
5455
)
5556

5657
// serveCmd represents the serve command
@@ -156,7 +157,8 @@ var serveCmd = &cobra.Command{
156157

157158
// Create the automation service
158159
autoServer, err := server.NewServer(ctx, workspace, &server.Options{
159-
StackName: _stack,
160+
StackName: _stack,
161+
PulumiLogLevel: _pulumiLogLevel,
160162
})
161163
if err != nil {
162164
return fmt.Errorf("unable to make an automation server: %w", err)
@@ -218,4 +220,5 @@ func init() {
218220
serveCmd.Flags().StringArrayVar(&_audiences, "kube-audience", nil, "The audience to expect in the token (for kubernetes auth mode)")
219221
serveCmd.Flags().StringVar(&_workspaceNamespace, "kube-workspace-namespace", os.Getenv("WORKSPACE_NAMESPACE"), "The Workspace object namespace (for kubernetes auth mode)")
220222
serveCmd.Flags().StringVar(&_workspaceName, "kube-workspace-name", os.Getenv("WORKSPACE_NAME"), "The Workspace object name (for kubernetes auth mode)")
223+
serveCmd.Flags().UintVar(&_pulumiLogLevel, "pulumi-log-level", 0, "The level of logging to use for the Pulumi CLI")
221224
}

agent/pkg/server/server.go

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"k8s.io/utils/ptr"
3737

3838
"github.com/pulumi/pulumi/sdk/v3/go/auto"
39+
"github.com/pulumi/pulumi/sdk/v3/go/auto/debug"
3940
"github.com/pulumi/pulumi/sdk/v3/go/auto/events"
4041
"github.com/pulumi/pulumi/sdk/v3/go/auto/optdestroy"
4142
"github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview"
@@ -49,12 +50,13 @@ import (
4950
var _userAgent = fmt.Sprintf("pulumi-kubernetes-operator/%s", version.Version)
5051

5152
type Server struct {
52-
log *zap.SugaredLogger
53-
plog *zap.Logger
54-
stopping atomic.Bool
55-
ws auto.Workspace
56-
stackLock sync.Mutex
57-
stack *auto.Stack
53+
log *zap.SugaredLogger
54+
plog *zap.Logger
55+
stopping atomic.Bool
56+
ws auto.Workspace
57+
stackLock sync.Mutex
58+
stack *auto.Stack
59+
pulumiLogLevel uint
5860

5961
pb.UnimplementedAutomationServiceServer
6062
}
@@ -66,6 +68,9 @@ type Options struct {
6668
StackName string
6769
// SecretsProvider is the secrets provider to use for new stacks (optional).
6870
SecretsProvider string
71+
72+
// PulumiLogLevel is the log level to use for Pulumi CLI operations.
73+
PulumiLogLevel uint
6974
}
7075

7176
// NewServer creates a new automation server for the given workspace.
@@ -79,9 +84,10 @@ func NewServer(ctx context.Context, ws auto.Workspace, opts *Options) (*Server,
7984
plog := zap.L().Named("pulumi")
8085

8186
server := &Server{
82-
log: log,
83-
plog: plog,
84-
ws: ws,
87+
log: log,
88+
plog: plog,
89+
ws: ws,
90+
pulumiLogLevel: opts.PulumiLogLevel,
8591
}
8692

8793
// select the initial stack, if provided
@@ -342,6 +348,11 @@ func (s *Server) Preview(in *pb.PreviewRequest, srv pb.AutomationService_Preview
342348
optpreview.UserAgent(_userAgent),
343349
optpreview.Diff(), /* richer result? */
344350
}
351+
if s.pulumiLogLevel > 0 {
352+
// We need to conidtionally enable debug logging as upstream pu/pu will set the log level to be
353+
// at least 1 if debug.LoggingOptions is not nil.
354+
opts = append(opts, optpreview.DebugLogging(debug.LoggingOptions{LogLevel: &s.pulumiLogLevel, LogToStdErr: true}))
355+
}
345356
if in.Parallel != nil {
346357
opts = append(opts, optpreview.Parallel(int(*in.Parallel)))
347358
}
@@ -434,6 +445,11 @@ func (s *Server) Refresh(in *pb.RefreshRequest, srv pb.AutomationService_Refresh
434445
opts := []optrefresh.Option{
435446
optrefresh.UserAgent(_userAgent),
436447
}
448+
if s.pulumiLogLevel > 0 {
449+
// We need to conidtionally enable debug logging as upstream pu/pu will set the log level to be
450+
// at least 1 if debug.LoggingOptions is not nil.
451+
opts = append(opts, optrefresh.DebugLogging(debug.LoggingOptions{LogLevel: &s.pulumiLogLevel, LogToStdErr: true}))
452+
}
437453
if in.Parallel != nil {
438454
opts = append(opts, optrefresh.Parallel(int(*in.Parallel)))
439455
}
@@ -516,6 +532,11 @@ func (s *Server) Up(in *pb.UpRequest, srv pb.AutomationService_UpServer) error {
516532
optup.SuppressProgress(),
517533
optup.Diff(), /* richer result? */
518534
}
535+
if s.pulumiLogLevel > 0 {
536+
// We need to conidtionally enable debug logging as upstream pu/pu will set the log level to be
537+
// at least 1 if debug.LoggingOptions is not nil.
538+
opts = append(opts, optup.DebugLogging(debug.LoggingOptions{LogLevel: &s.pulumiLogLevel, LogToStdErr: true}))
539+
}
519540
if in.Parallel != nil {
520541
opts = append(opts, optup.Parallel(int(*in.Parallel)))
521542
}
@@ -620,6 +641,11 @@ func (s *Server) Destroy(in *pb.DestroyRequest, srv pb.AutomationService_Destroy
620641
opts := []optdestroy.Option{
621642
optdestroy.UserAgent(_userAgent),
622643
}
644+
if s.pulumiLogLevel > 0 {
645+
// We need to conidtionally enable debug logging as upstream pu/pu will set the log level to be
646+
// at least 1 if debug.LoggingOptions is not nil.
647+
opts = append(opts, optdestroy.DebugLogging(debug.LoggingOptions{LogLevel: &s.pulumiLogLevel, LogToStdErr: true}))
648+
}
623649
if in.Parallel != nil {
624650
opts = append(opts, optdestroy.Parallel(int(*in.Parallel)))
625651
}

agent/pkg/server/server_test.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ func TestUp(t *testing.T) {
479479
name string
480480
projectDir string
481481
stacks []string
482+
serverOpts *Options
482483
req *pb.UpRequest
483484
wantErr any
484485
want auto.ConfigMap
@@ -496,13 +497,20 @@ func TestUp(t *testing.T) {
496497
stacks: []string{TestStackName},
497498
req: &pb.UpRequest{},
498499
},
500+
{
501+
name: "Pulumi CLI verbose logging enabled: lvl 11",
502+
projectDir: "./testdata/simple",
503+
stacks: []string{TestStackName},
504+
serverOpts: &Options{PulumiLogLevel: 11},
505+
req: &pb.UpRequest{},
506+
},
499507
}
500508
for _, tt := range tests {
501509
t.Run(tt.name, func(t *testing.T) {
502510
t.Parallel()
503511
g := gomega.NewWithT(t)
504512
ctx := newContext(t)
505-
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks})
513+
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks, ServerOpts: tt.serverOpts})
506514

507515
srv := &upStream{
508516
ctx: ctx,
@@ -517,6 +525,11 @@ func TestUp(t *testing.T) {
517525
g.Expect(srv.result).ToNot(gomega.BeNil())
518526
g.Expect(srv.result.Summary).ToNot(gomega.BeNil())
519527
g.Expect(srv.result.Summary.Result).To(gomega.Equal("succeeded"))
528+
529+
if tt.serverOpts != nil {
530+
// ensure that the extra logs are present
531+
g.Expect(srv.result).To(gomega.ContainSubstring("log level 11 will print sensitive information"))
532+
}
520533
}
521534
})
522535
}
@@ -556,6 +569,7 @@ func TestPreview(t *testing.T) {
556569
projectDir string
557570
stacks []string
558571
req *pb.PreviewRequest
572+
serverOpts *Options
559573
wantErr any
560574
want auto.ConfigMap
561575
}{
@@ -572,13 +586,20 @@ func TestPreview(t *testing.T) {
572586
stacks: []string{TestStackName},
573587
req: &pb.PreviewRequest{},
574588
},
589+
{
590+
name: "Pulumi CLI verbose logging enabled",
591+
projectDir: "./testdata/simple",
592+
stacks: []string{TestStackName},
593+
serverOpts: &Options{PulumiLogLevel: 11},
594+
req: &pb.PreviewRequest{},
595+
},
575596
}
576597
for _, tt := range tests {
577598
t.Run(tt.name, func(t *testing.T) {
578599
t.Parallel()
579600
g := gomega.NewWithT(t)
580601
ctx := newContext(t)
581-
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks})
602+
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks, ServerOpts: tt.serverOpts})
582603

583604
srv := &previewStream{
584605
ctx: ctx,
@@ -591,6 +612,11 @@ func TestPreview(t *testing.T) {
591612
g.Expect(err).ToNot(gomega.HaveOccurred())
592613
g.Expect(srv.events).ToNot(gomega.BeEmpty())
593614
g.Expect(srv.result).ToNot(gomega.BeNil())
615+
616+
if tt.serverOpts != nil {
617+
// ensure that the extra logs are present
618+
g.Expect(srv.result).To(gomega.ContainSubstring("log level 11 will print sensitive information"))
619+
}
594620
}
595621
})
596622
}
@@ -630,6 +656,7 @@ func TestRefresh(t *testing.T) {
630656
projectDir string
631657
stacks []string
632658
req *pb.RefreshRequest
659+
serverOpts *Options
633660
wantErr any
634661
want auto.ConfigMap
635662
}{
@@ -646,13 +673,20 @@ func TestRefresh(t *testing.T) {
646673
stacks: []string{TestStackName},
647674
req: &pb.RefreshRequest{},
648675
},
676+
{
677+
name: "Pulumi CLI verbose logging enabled",
678+
projectDir: "./testdata/simple",
679+
stacks: []string{TestStackName},
680+
serverOpts: &Options{PulumiLogLevel: 11},
681+
req: &pb.RefreshRequest{},
682+
},
649683
}
650684
for _, tt := range tests {
651685
t.Run(tt.name, func(t *testing.T) {
652686
t.Parallel()
653687
g := gomega.NewWithT(t)
654688
ctx := newContext(t)
655-
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks})
689+
tc := newTC(ctx, t, tcOptions{ProjectDir: tt.projectDir, Stacks: tt.stacks, ServerOpts: tt.serverOpts})
656690

657691
srv := &refreshStream{
658692
ctx: ctx,
@@ -667,6 +701,11 @@ func TestRefresh(t *testing.T) {
667701
g.Expect(srv.result).ToNot(gomega.BeNil())
668702
g.Expect(srv.result.Summary).ToNot(gomega.BeNil())
669703
g.Expect(srv.result.Summary.Result).To(gomega.Equal("succeeded"))
704+
705+
if tt.serverOpts != nil {
706+
// ensure that the extra logs are present
707+
g.Expect(srv.result).To(gomega.ContainSubstring("log level 11 will print sensitive information"))
708+
}
670709
}
671710
})
672711
}
@@ -706,6 +745,7 @@ func TestDestroy(t *testing.T) {
706745
projectDir string
707746
stacks []string
708747
req *pb.DestroyRequest
748+
serverOpts *Options
709749
wantErr any
710750
want auto.ConfigMap
711751
}{
@@ -722,6 +762,13 @@ func TestDestroy(t *testing.T) {
722762
stacks: []string{TestStackName},
723763
req: &pb.DestroyRequest{},
724764
},
765+
{
766+
name: "Pulumi CLI verbose logging enabled",
767+
projectDir: "./testdata/simple",
768+
stacks: []string{TestStackName},
769+
serverOpts: &Options{PulumiLogLevel: 11},
770+
req: &pb.DestroyRequest{},
771+
},
725772
}
726773
for _, tt := range tests {
727774
t.Run(tt.name, func(t *testing.T) {

deploy/crds/auto.pulumi.com_workspaces.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8454,6 +8454,14 @@ spec:
84548454
- containers
84558455
type: object
84568456
type: object
8457+
pulumiLogLevel:
8458+
description: |-
8459+
PulumiLogVerbosity is the log verbosity level to use for the Pulumi CLI.
8460+
If unset,verbose logging is disabled.
8461+
See: https://www.pulumi.com/docs/iac/support/troubleshooting/#verbose-logging
8462+
for more information about log levels.
8463+
format: int32
8464+
type: integer
84578465
resources:
84588466
description: |-
84598467
Compute Resources required by this workspace.

deploy/crds/pulumi.com_stacks.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9381,6 +9381,9 @@ spec:
93819381
- containers
93829382
type: object
93839383
type: object
9384+
pulumiLogLevel:
9385+
format: int32
9386+
type: integer
93849387
resources:
93859388
description: ResourceRequirements describes the compute resource
93869389
requirements.
@@ -19017,6 +19020,9 @@ spec:
1901719020
- containers
1901819021
type: object
1901919022
type: object
19023+
pulumiLogLevel:
19024+
format: int32
19025+
type: integer
1902019026
resources:
1902119027
description: ResourceRequirements describes the compute resource
1902219028
requirements.

deploy/helm/pulumi-operator/crds/auto.pulumi.com_workspaces.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8454,6 +8454,14 @@ spec:
84548454
- containers
84558455
type: object
84568456
type: object
8457+
pulumiLogLevel:
8458+
description: |-
8459+
PulumiLogVerbosity is the log verbosity level to use for the Pulumi CLI.
8460+
If unset,verbose logging is disabled.
8461+
See: https://www.pulumi.com/docs/iac/support/troubleshooting/#verbose-logging
8462+
for more information about log levels.
8463+
format: int32
8464+
type: integer
84578465
resources:
84588466
description: |-
84598467
Compute Resources required by this workspace.

deploy/helm/pulumi-operator/crds/pulumi.com_stacks.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9381,6 +9381,9 @@ spec:
93819381
- containers
93829382
type: object
93839383
type: object
9384+
pulumiLogLevel:
9385+
format: int32
9386+
type: integer
93849387
resources:
93859388
description: ResourceRequirements describes the compute resource
93869389
requirements.
@@ -19017,6 +19020,9 @@ spec:
1901719020
- containers
1901819021
type: object
1901919022
type: object
19023+
pulumiLogLevel:
19024+
format: int32
19025+
type: integer
1902019026
resources:
1902119027
description: ResourceRequirements describes the compute resource
1902219028
requirements.

docs/stacks.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,15 @@ with apply.<br/>
22802280
with apply.<br/>
22812281
</td>
22822282
<td>false</td>
2283+
</tr><tr>
2284+
<td><b>pulumiLogLevel</b></td>
2285+
<td>integer</td>
2286+
<td>
2287+
<br/>
2288+
<br/>
2289+
<i>Format</i>: int32<br/>
2290+
</td>
2291+
<td>false</td>
22832292
</tr><tr>
22842293
<td><b><a href="#stackspecworkspacetemplatespecresources">resources</a></b></td>
22852294
<td>object</td>
@@ -21715,6 +21724,15 @@ with apply.<br/>
2171521724
with apply.<br/>
2171621725
</td>
2171721726
<td>false</td>
21727+
</tr><tr>
21728+
<td><b>pulumiLogLevel</b></td>
21729+
<td>integer</td>
21730+
<td>
21731+
<br/>
21732+
<br/>
21733+
<i>Format</i>: int32<br/>
21734+
</td>
21735+
<td>false</td>
2171821736
</tr><tr>
2171921737
<td><b><a href="#stackspecworkspacetemplatespecresources-1">resources</a></b></td>
2172021738
<td>object</td>

0 commit comments

Comments
 (0)