From 7ced036ef0f61af4f67e57a2484fee1f2ea72dbb Mon Sep 17 00:00:00 2001 From: Guinevere Saenger Date: Tue, 14 Nov 2023 14:57:30 -0800 Subject: [PATCH 1/2] Fix missing nil check on docInfo for doc discovery --- pkg/tfgen/docs.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/tfgen/docs.go b/pkg/tfgen/docs.go index 4e22ab0a1..c1c1859b7 100644 --- a/pkg/tfgen/docs.go +++ b/pkg/tfgen/docs.go @@ -259,9 +259,11 @@ func getDocsForResource(g *Generator, source DocsSource, kind DocKind, msg := fmt.Sprintf("could not find docs for %v %v. Override the Docs property in the %v mapping. See "+ "type tfbridge.DocInfo for details.", kind, formatEntityName(rawname), kind) - if cmdutil.IsTruthy(os.Getenv("PULUMI_MISSING_DOCS_ERROR")) && !info.GetDocs().AllowMissing { - g.error(msg) - return entityDocs{}, fmt.Errorf(msg) + if cmdutil.IsTruthy(os.Getenv("PULUMI_MISSING_DOCS_ERROR")) { + if docInfo == nil || !docInfo.AllowMissing { + g.error(msg) + return entityDocs{}, fmt.Errorf(msg) + } } // Ideally, we would still want to still return an error here and let upstream callers handle it, but at the From eec2329cc0d26333abaeed45be28da08a2dfc5ec Mon Sep 17 00:00:00 2001 From: Guinevere Saenger Date: Tue, 14 Nov 2023 17:04:31 -0800 Subject: [PATCH 2/2] Add test for docInfo==nil To test what happens when info.docs is empty, we mock out a resource that returns nil on info.GetDocs(). This satisfies the if docInfo ==nil condition and will panic if we do not have a nil check. The test verifies that there is an error as expected. --- pkg/tfgen/docs_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pkg/tfgen/docs_test.go b/pkg/tfgen/docs_test.go index f68818cc1..c3fa0ebad 100644 --- a/pkg/tfgen/docs_test.go +++ b/pkg/tfgen/docs_test.go @@ -1164,6 +1164,12 @@ func TestErrorMissingDocs(t *testing.T) { docs: tfbridge.DocInfo{AllowMissing: true}, forbidMissingDocsEnv: "true", }, + // DocInfo is nil so we error because docs are missing + { + source: mockSource{}, + forbidMissingDocsEnv: "true", + expectErr: true, + }, } for _, tt := range tests { @@ -1186,6 +1192,18 @@ func TestErrorMissingDocs(t *testing.T) { }) } } +func TestErrorNilDocs(t *testing.T) { + t.Run("", func(t *testing.T) { + g := &Generator{ + sink: mockSink{t}, + } + rawName := "nil_docs" + t.Setenv("PULUMI_MISSING_DOCS_ERROR", "true") + info := mockNilDocsResource{token: tokens.Token(rawName)} + _, err := getDocsForResource(g, mockSource{}, ResourceDocs, rawName, &info) + assert.NotNil(t, err) + }) +} type mockSource map[string]string @@ -1240,6 +1258,15 @@ func (r *mockResource) GetTok() tokens.Token { return r.token } +type mockNilDocsResource struct { + token tokens.Token + mockResource +} + +func (nr *mockNilDocsResource) GetDocs() *tfbridge.DocInfo { + return nil +} + func readfile(t *testing.T, file string) string { t.Helper() bytes, err := os.ReadFile(file)