Skip to content

Commit

Permalink
check: Verify data source and resource file mismatches
Browse files Browse the repository at this point in the history
Closes #13
Closes #14

If `-providers-schema-json` flag is provided, verifies all known data sources and resources have an associated documentation file. Also, verifies that no extraneous or incorrectly named documentation files exist.
  • Loading branch information
bflad committed Dec 17, 2019
1 parent dcadc71 commit 93bdafc
Show file tree
Hide file tree
Showing 7 changed files with 401 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ ENHANCEMENTS

* check: Verify number of documentation files for Terraform Registry storage limits
* check: Verify size of documentation files for Terraform Registry storage limits
* check: Verify all known data sources and resources have an associated documentation file (if `-providers-schema-json` is provided)
* check: Verify no extraneous or incorrectly named documentation files exist (if `-providers-schema-json` is provided)

# v0.1.2

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ The `tfproviderdocs check` command verifies the Terraform Provider documentation
- Verifies that no invalid directories are found in the documentation directory structure.
- Ensures that there is not a mix (legacy and Terraform Registry) of directory structures, which is not supported during Terraform Registry documentation ingress.
- Verifies number of documentation files is below Terraform Registry storage limits.
- Verifies all known data sources and resources have an associated documentation file (if `-providers-schema-json` is provided)
- Verifies no extraneous or incorrectly named documentation files exist (if `-providers-schema-json` is provided)
- Verifies each file in the documentation directories is valid.

The validity of files is checked with the following rules:
Expand Down
31 changes: 31 additions & 0 deletions check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
)

const (
ResourceTypeDataSource = "data source"
ResourceTypeResource = "resource"

// Terraform Registry Storage Limits
// https://www.terraform.io/docs/registry/providers/docs.html#storage-limits
RegistryMaximumNumberOfFiles = 1000
Expand Down Expand Up @@ -60,6 +63,34 @@ func (check *Check) Run(directories map[string][]string) error {
return err
}

if len(check.Options.SchemaDataSources) > 0 && false {
var dataSourceFiles []string

if files, ok := directories[RegistryDataSourcesDirectory]; ok {
dataSourceFiles = files
} else if files, ok := directories[LegacyDataSourcesDirectory]; ok {
dataSourceFiles = files
}

if err := ResourceFileMismatchCheck(check.Options.ProviderName, ResourceTypeDataSource, check.Options.SchemaDataSources, dataSourceFiles); err != nil {
return err
}
}

if len(check.Options.SchemaResources) > 0 {
var resourceFiles []string

if files, ok := directories[RegistryResourcesDirectory]; ok {
resourceFiles = files
} else if files, ok := directories[LegacyResourcesDirectory]; ok {
resourceFiles = files
}

if err := ResourceFileMismatchCheck(check.Options.ProviderName, ResourceTypeResource, check.Options.SchemaResources, resourceFiles); err != nil {
return err
}
}

var result *multierror.Error

if files, ok := directories[RegistryDataSourcesDirectory]; ok {
Expand Down
17 changes: 17 additions & 0 deletions check/file_extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,20 @@ func IsValidRegistryFileExtension(fileExtension string) bool {

return false
}

// TrimFileExtension removes file extensions including those with multiple periods.
func TrimFileExtension(path string) string {
filename := filepath.Base(path)

if filename == "." {
return ""
}

dotIndex := strings.IndexByte(filename, '.')

if dotIndex > 0 {
return filename[:dotIndex]
}

return filename
}
45 changes: 45 additions & 0 deletions check/file_extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,48 @@ func TestGetFileExtension(t *testing.T) {
})
}
}

func TestTrimFileExtension(t *testing.T) {
testCases := []struct {
Name string
Path string
Expect string
}{
{
Name: "empty path",
Path: "",
Expect: "",
},
{
Name: "filename with single extension",
Path: "file.md",
Expect: "file",
},
{
Name: "filename with multiple extensions",
Path: "file.html.markdown",
Expect: "file",
},
{
Name: "full path with single extensions",
Path: "docs/resource/thing.md",
Expect: "thing",
},
{
Name: "full path with multiple extensions",
Path: "website/docs/r/thing.html.markdown",
Expect: "thing",
},
}

for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
got := TrimFileExtension(testCase.Path)
want := testCase.Expect

if got != want {
t.Errorf("expected %s, got %s", want, got)
}
})
}
}
83 changes: 83 additions & 0 deletions check/file_mismatch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package check

import (
"fmt"
"sort"

"github.com/hashicorp/go-multierror"
tfjson "github.com/hashicorp/terraform-json"
)

func ResourceFileMismatchCheck(providerName string, resourceType string, schemaResources map[string]*tfjson.Schema, files []string) error {
var extraFiles []string
var missingFiles []string

for _, file := range files {
if fileHasResource(schemaResources, providerName, file) {
continue
}

extraFiles = append(extraFiles, file)
}

for _, resourceName := range resourceNames(schemaResources) {
if resourceHasFile(files, providerName, resourceName) {
continue
}

missingFiles = append(missingFiles, resourceName)
}

var result *multierror.Error

for _, extraFile := range extraFiles {
err := fmt.Errorf("matching %s for documentation file (%s) not found, file is extraneous or incorrectly named", resourceType, extraFile)
result = multierror.Append(result, err)
}

for _, missingFile := range missingFiles {
err := fmt.Errorf("missing documentation file for %s: %s", resourceType, missingFile)
result = multierror.Append(result, err)
}

return result.ErrorOrNil()
}

func fileHasResource(schemaResources map[string]*tfjson.Schema, providerName, file string) bool {
if _, ok := schemaResources[fileResourceName(providerName, file)]; ok {
return true
}

return false
}

func fileResourceName(providerName, fileName string) string {
resourceSuffix := TrimFileExtension(fileName)

return fmt.Sprintf("%s_%s", providerName, resourceSuffix)
}

func resourceHasFile(files []string, providerName, resourceName string) bool {
var found bool

for _, file := range files {
if fileResourceName(providerName, file) == resourceName {
found = true
break
}
}

return found
}

func resourceNames(resources map[string]*tfjson.Schema) []string {
names := make([]string, 0, len(resources))

for name := range resources {
names = append(names, name)
}

sort.Strings(names)

return names
}
Loading

0 comments on commit 93bdafc

Please sign in to comment.