Skip to content

Commit

Permalink
Ensure logging from dynamic schema generation is structured
Browse files Browse the repository at this point in the history
For logging to show by default, it needs to be in structured form. This PR correctly
preserves the log sink after calls to Parameterize, and uses that log sink as the `Sink`
in tfgen generator calls.
  • Loading branch information
iwahbe committed Jan 10, 2025
1 parent 5616df5 commit 03a3081
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 31 deletions.
96 changes: 65 additions & 31 deletions dynamic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/pkg/errors"
"github.com/pulumi/pulumi/pkg/v3/codegen/schema"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/spf13/afero"
Expand All @@ -46,6 +45,20 @@ const (
baseProviderName = "terraform-provider"
)

func main() {
ctx := context.Background()

defaultInfo, metadata, close := initialSetup()

defer func() {
if err := close(); err != nil {
fmt.Printf("Failed to close TF provder: %s", err.Error())
}
}()

pfbridge.Main(ctx, baseProviderName, defaultInfo, metadata)
}

func initialSetup() (info.Provider, pfbridge.ProviderMetadata, func() error) {
var tfServer run.Provider
info := info.Provider{
Expand Down Expand Up @@ -73,14 +86,12 @@ func initialSetup() (info.Provider, pfbridge.ProviderMetadata, func() error) {
XGetSchema: func(ctx context.Context, req plugin.GetSchemaRequest) ([]byte, error) {
// Create a custom generator for schema. Examples will only be generated if `fullDocs` is set.
g, err := tfgen.NewGenerator(tfgen.GeneratorOptions{
Package: info.Name,
Version: info.Version,
Language: tfgen.Schema,
ProviderInfo: info,
Root: afero.NewMemMapFs(),
Sink: diag.DefaultSink(os.Stdout, os.Stderr, diag.FormatOptions{
Color: colors.Always,
}),
Package: info.Name,
Version: info.Version,
Language: tfgen.Schema,
ProviderInfo: info,
Root: afero.NewMemMapFs(),
Sink: loggerSink{tfbridge.GetLogger(ctx)},
XInMemoryDocs: !fullDocs,
SkipExamples: !fullDocs,
})
Expand All @@ -100,14 +111,12 @@ func initialSetup() (info.Provider, pfbridge.ProviderMetadata, func() error) {
if indexDocOutDir != "" {
// Create a custom generator for registry docs (_index.md).
indexGenerator, err := tfgen.NewGenerator(tfgen.GeneratorOptions{
Package: info.Name,
Version: info.Version,
Language: tfgen.RegistryDocs,
ProviderInfo: info,
Root: afero.NewBasePathFs(afero.NewOsFs(), indexDocOutDir),
Sink: diag.DefaultSink(os.Stdout, os.Stderr, diag.FormatOptions{
Color: colors.Always,
}),
Package: info.Name,
Version: info.Version,
Language: tfgen.RegistryDocs,
ProviderInfo: info,
Root: afero.NewBasePathFs(afero.NewOsFs(), indexDocOutDir),
Sink: loggerSink{tfbridge.GetLogger(ctx)},
XInMemoryDocs: false,
SkipExamples: false,
})
Expand Down Expand Up @@ -255,20 +264,6 @@ func (d doubleParameterizeErr) Error() string {
d.existing.name, d.existing.version)
}

func main() {
ctx := context.Background()

defaultInfo, metadata, close := initialSetup()

defer func() {
if err := close(); err != nil {
fmt.Printf("Failed to close TF provder: %s", err.Error())
}
}()

pfbridge.Main(ctx, baseProviderName, defaultInfo, metadata)
}

func getProvider(ctx context.Context, args parameterize.Args) (run.Provider, error) {
if local := args.Local; local != nil {
return run.LocalProvider(ctx, local.Path)
Expand All @@ -280,3 +275,42 @@ func getProvider(ctx context.Context, args parameterize.Args) (run.Provider, err

return run.NamedProvider(ctx, remote.Name, remote.Version)
}

type loggerSink struct{ logger tfbridge.Logger }

func (l loggerSink) Logf(sev diag.Severity, d *diag.Diag, args ...interface{}) {
msg, detail := l.Stringify(sev, d, args...)
var log func(string)
switch sev {
case diag.Debug:
log = l.logger.Debug
case diag.Infoerr:
log = l.logger.Info
case diag.Warning:
log = l.logger.Warn
case diag.Error:
log = l.logger.Error
case diag.Info:
fallthrough
default:
log = l.logger.Info
}

log(msg)
if detail != "" {
log(detail)
}
}

func (l loggerSink) Debugf(d *diag.Diag, args ...interface{}) { l.Logf(diag.Debug, d, args...) }
func (l loggerSink) Infof(d *diag.Diag, args ...interface{}) { l.Logf(diag.Info, d, args...) }
func (l loggerSink) Infoerrf(d *diag.Diag, args ...interface{}) { l.Logf(diag.Infoerr, d, args...) }
func (l loggerSink) Errorf(d *diag.Diag, args ...interface{}) { l.Logf(diag.Error, d, args...) }
func (l loggerSink) Warningf(d *diag.Diag, args ...interface{}) { l.Logf(diag.Warning, d, args...) }

func (l loggerSink) Stringify(_ diag.Severity, d *diag.Diag, args ...interface{}) (string, string) {
if d.Raw {
return fmt.Sprint(append([]any{d.Message}, args...)), ""
}
return fmt.Sprintf(d.Message, args...), ""
}
3 changes: 3 additions & 0 deletions pkg/pf/tfbridge/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ func (p *provider) ParameterizeWithContext(
if err != nil {
return err
}
pp.Unwrap().logSink = p.logSink // Preserve the log sink from p

*p = *pp.Unwrap()

return nil
})

Expand Down

0 comments on commit 03a3081

Please sign in to comment.