Skip to content

Commit

Permalink
Fix report case sensitivity (#4433)
Browse files Browse the repository at this point in the history
* Add tests for desired behaviour

* Modify report to handle inconstencies

* Add missing t.Parallel() call
  • Loading branch information
theunrepentantgeek authored Nov 11, 2024
1 parent 1b3c4a9 commit 96937f1
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,15 @@ func (report *ResourceVersionsReport) summarize(definitions astmodel.TypeDefinit
name := rsrc.Name()
pkg := name.PackageReference()

defType := astmodel.MustBeResourceType(rsrc.Type())
armVersion := strings.Trim(defType.APIVersionEnumValue().Value, "\"")
item := report.createItem(name, defType.ARMType(), armVersion)

if astmodel.IsStoragePackageReference(pkg) {
// Skip storage versions - they're an implementation detail
continue
}

defType := astmodel.MustBeResourceType(rsrc.Type())
armVersion := strings.Trim(defType.APIVersionEnumValue().Value, "\"")
item := report.createItem(name, defType.ARMType(), armVersion)

report.addItem(item)
}

Expand Down Expand Up @@ -741,18 +741,45 @@ func (report *ResourceVersionsReport) writeFragment(name string, data any, buffe
return nil
}

// groupTitle returns the title to use for the given group, based on the first resource found in that group
type reportMetadataQuality int

const (
poor reportMetadataQuality = 10
good reportMetadataQuality = 20
better reportMetadataQuality = 30
best reportMetadataQuality = 40
)

// groupTitle returns metadata to use for the given group.
// group is the name of the group to generate metadata for.
// items is the set of items in the group.
// Some resource-providers (incl alertsmanagement) are inconsistent with letter casing, so we
// look for the best information we have.
func (report *ResourceVersionsReport) groupInfo(
group string,
items set.Set[ResourceVersionsReportResourceItem],
) *ResourceVersionsReportGroupInfo {
caser := cases.Title(language.English)
caser := cases.Title(language.English, cases.NoLower)
result := &ResourceVersionsReportGroupInfo{
Group: group,
Title: caser.String(group),
Provider: caser.String(group),
}
currentQuality := poor

saveCandidate := func(
title string,
provider string,
quality reportMetadataQuality,
) {
if quality > currentQuality {
result.Title = title
result.Provider = provider
currentQuality = quality
}
}

// Scan through available resources to find better values for Title & Provider
for item := range items {
if item.armType == "" {
// Didn't find a resource, keep looking
Expand All @@ -761,17 +788,27 @@ func (report *ResourceVersionsReport) groupInfo(

// Slice off the part before the first "/" to get the Provider name
parts := strings.Split(item.armType, "/")
if len(parts) == 0 {
// String doesn't look like a resource type, keep looking
continue
provider := parts[0]

const prefix = "Microsoft."
if strings.HasPrefix(provider, prefix) {
// If the provider starts with exactly "Microsoft." (with a case-sensitive check),
// that's our best bet for a properly cased provider name
saveCandidate(
strings.TrimPrefix(provider, prefix),
provider,
best)
} else if strings.HasPrefix(strings.ToLower(provider), strings.ToLower(prefix)) {
// If the provider starts with "Microsoft." (but doesn't match the case exactly),
// that's not so good, but better than the defaults
saveCandidate(
caser.String(provider[len(prefix):]),
caser.String(provider),
better)
} else {
// Just use what we have
saveCandidate(provider, provider, good)
}

// Store the provider name
result.Provider = parts[0]

// Remove the "Microsoft." prefix to make the title
result.Title = strings.TrimPrefix(result.Provider, "Microsoft.")
break
}

return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
. "github.com/onsi/gomega"
"github.com/sebdah/goldie/v2"

"github.com/Azure/azure-service-operator/v2/internal/set"
"github.com/Azure/azure-service-operator/v2/tools/generator/internal/astmodel"
"github.com/Azure/azure-service-operator/v2/tools/generator/internal/config"
"github.com/Azure/azure-service-operator/v2/tools/generator/internal/test"
Expand Down Expand Up @@ -95,3 +96,82 @@ func TestGolden_ReportAllResourceVersions(t *testing.T) {

gold.Assert(t, t.Name(), []byte(buffer.String()))
}

func TestResourceVersionsReportGroupInfo_GivenGroup_ReturnsExpectedResult(t *testing.T) {
t.Parallel()

storagePkg := test.MakeLocalPackageReference("storage", "v20230101")

storageAccount := ResourceVersionsReportResourceItem{
name: astmodel.MakeInternalTypeName(storagePkg, "StorageAccount"),
armType: "Microsoft.Storage/storageAccounts",
armVersion: "2023-01-01",
supportedFrom: "v2.0.0",
}

alertsManagementPkg := test.MakeLocalPackageReference("alertsmanagement", "v20210401")

smartDetector := ResourceVersionsReportResourceItem{
name: astmodel.MakeInternalTypeName(alertsManagementPkg, "SmartDetector"),
armType: "microsoft.alertsManagement/smartDetectorAlertRules",
armVersion: "2021-04-01",
supportedFrom: "v2.11.0",
}

prometheusRuleGroup := ResourceVersionsReportResourceItem{
name: astmodel.MakeInternalTypeName(alertsManagementPkg, "PrometheusRuleGroup"),
armType: "Microsoft.AlertsManagement/prometheusRuleGroups",
}

cases := map[string]struct {
group string
items set.Set[ResourceVersionsReportResourceItem]
expectedGroup string
expectedProvider string
expectedTitle string
}{
"StorageAccount": {
group: "storage",
items: set.Make(storageAccount),
expectedGroup: "storage",
expectedProvider: "Microsoft.Storage",
expectedTitle: "Storage",
},
"SmartDetector": {
group: "alertsmanagement",
items: set.Make(smartDetector),
expectedGroup: "alertsmanagement",
expectedProvider: "Microsoft.alertsManagement",
expectedTitle: "AlertsManagement",
},
"PrometheusRuleGroup": {
group: "alertsmanagement",
items: set.Make(prometheusRuleGroup),
expectedGroup: "alertsmanagement",
expectedProvider: "Microsoft.AlertsManagement",
expectedTitle: "AlertsManagement",
},
"Prefers Correct Case": {
group: "alertsmanagement",
items: set.Make(smartDetector, prometheusRuleGroup),
expectedGroup: "alertsmanagement",
expectedProvider: "Microsoft.AlertsManagement",
expectedTitle: "AlertsManagement",
},
}

for name, c := range cases {
t.Run(name, func(t *testing.T) {
t.Parallel()
g := NewGomegaWithT(t)

report := &ResourceVersionsReport{} // empty report

info := report.groupInfo(c.group, c.items)
g.Expect(info).ToNot(BeNil())
g.Expect(info.Group).To(Equal(c.expectedGroup))
g.Expect(info.Provider).To(Equal(c.expectedProvider))
g.Expect(info.Title).To(Equal(c.expectedTitle))
})
}
}

0 comments on commit 96937f1

Please # to comment.