diff --git a/internal/backstage/backstage.go b/internal/backstage/backstage.go index e2261b67..ad3d8457 100644 --- a/internal/backstage/backstage.go +++ b/internal/backstage/backstage.go @@ -5,11 +5,13 @@ package backstage import ( "errors" + "fmt" "io" "io/fs" "os" "path/filepath" "sort" + "strconv" "strings" "time" @@ -167,6 +169,7 @@ func LoadCatalogInfo(r io.Reader) (*CatalogInfo, error) { if catalog.service != nil { var apiNames []string for _, apiName := range catalog.serviceComponent.Spec.ProvidesAPIs { + // Preserve manually added entries, things are are NOT vervet APIs if _, ok := vervetAPINames[apiName]; !ok { apiNames = append(apiNames, apiName) } @@ -178,7 +181,7 @@ func LoadCatalogInfo(r io.Reader) (*CatalogInfo, error) { // LoadVervetAPIs loads all the compiled versioned OpenAPI specs and adds them // to the catalog as API components. -func (c *CatalogInfo) LoadVervetAPIs(root, versions string, pivotDate time.Time) error { +func (c *CatalogInfo) LoadVervetAPIs(root, versions string, pivotDate time.Time, apiName string) error { root, err := filepath.Abs(root) if err != nil { return err @@ -202,10 +205,18 @@ func (c *CatalogInfo) LoadVervetAPIs(root, versions string, pivotDate time.Time) if err != nil { return err } - api, err := c.vervetAPI(doc, root, pivotDate) + api, err := c.vervetAPI(doc, root, pivotDate, apiName) if err != nil { return err } + if _, ok := apiUniqueNames[api.Metadata.Name]; ok { + return fmt.Errorf(` +there are multiple apis named %s, only one will be available on Backstage. +To resolve this error change the Name attribute in one of the spec files. +Note names may be truncated to fit the Backstage 63 character limit`, + api.Metadata.Name, + ) + } c.VervetAPIs = append(c.VervetAPIs, api) apiUniqueNames[api.Metadata.Name] = struct{}{} } @@ -252,7 +263,7 @@ func (c *CatalogInfo) LoadVervetAPIs(root, versions string, pivotDate time.Time) } // vervetAPI adds an OpenAPI spec document to the catalog. -func (c *CatalogInfo) vervetAPI(doc *vervet.Document, root string, pivotDate time.Time) (*API, error) { +func (c *CatalogInfo) vervetAPI(doc *vervet.Document, root string, pivotDate time.Time, apiName string) (*API, error) { version, err := doc.Version() if err != nil { return nil, err @@ -262,7 +273,10 @@ func (c *CatalogInfo) vervetAPI(doc *vervet.Document, root string, pivotDate tim return nil, err } - name := toBackstageName(doc.Info.Title) + "_" + version.DateString() + name_suffix := fmt.Sprintf("_%s_%s", toBackstageName(apiName), version.DateString()) + // Backstage names can only be a maximum of 63 characters + name_len := 63 - len(name_suffix) + name := fmt.Sprintf("%."+strconv.Itoa(name_len)+"s%s", toBackstageName(doc.Info.Title), name_suffix) title := doc.Info.Title + " " + version.DateString() labels := map[string]string{ snykApiVersionDate: version.DateString(), diff --git a/internal/backstage/backstage_test.go b/internal/backstage/backstage_test.go index 0c7afcd2..d84ba440 100644 --- a/internal/backstage/backstage_test.go +++ b/internal/backstage/backstage_test.go @@ -115,7 +115,7 @@ func TestLoadVersionsNoApis(t *testing.T) { catalog, err := LoadCatalogInfo(bytes.NewBufferString(catalogSrc)) c.Assert(err, qt.IsNil) versionsRoot := testdata.Path("output") - err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)) + err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC), "rest") c.Assert(err, qt.IsNil) var saveOutput bytes.Buffer @@ -123,16 +123,16 @@ func TestLoadVersionsNoApis(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(saveOutput.String(), qt.Equals, catalogSrc+` providesApis: - - Registry_2021-06-01_experimental - - Registry_2021-06-04_experimental - - Registry_2021-06-07_experimental - - Registry_2021-06-13_beta - - Registry_2021-06-13_experimental - - Registry_2021-08-20_experimental - - Registry_2023-06-01_experimental - - Registry_2023-06-02_experimental - - Registry_2023-06-03_experimental - - Registry_2024-10-15_ga + - Registry_rest_2021-06-01_experimental + - Registry_rest_2021-06-04_experimental + - Registry_rest_2021-06-07_experimental + - Registry_rest_2021-06-13_beta + - Registry_rest_2021-06-13_experimental + - Registry_rest_2021-08-20_experimental + - Registry_rest_2023-06-01_experimental + - Registry_rest_2023-06-02_experimental + - Registry_rest_2023-06-03_experimental + - Registry_rest_2024-10-15_ga --- `[1:]+string(vervetAPIs)) } @@ -148,7 +148,7 @@ func TestLoadVersionsSomeApis(t *testing.T) { `[1:])) c.Assert(err, qt.IsNil) versionsRoot := testdata.Path("output") - err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)) + err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC), "rest") c.Assert(err, qt.IsNil) var saveOutput bytes.Buffer @@ -156,16 +156,16 @@ func TestLoadVersionsSomeApis(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(saveOutput.String(), qt.Equals, catalogSrc+` providesApis: - - Registry_2021-06-01_experimental - - Registry_2021-06-04_experimental - - Registry_2021-06-07_experimental - - Registry_2021-06-13_beta - - Registry_2021-06-13_experimental - - Registry_2021-08-20_experimental - - Registry_2023-06-01_experimental - - Registry_2023-06-02_experimental - - Registry_2023-06-03_experimental - - Registry_2024-10-15_ga + - Registry_rest_2021-06-01_experimental + - Registry_rest_2021-06-04_experimental + - Registry_rest_2021-06-07_experimental + - Registry_rest_2021-06-13_beta + - Registry_rest_2021-06-13_experimental + - Registry_rest_2021-08-20_experimental + - Registry_rest_2023-06-01_experimental + - Registry_rest_2023-06-02_experimental + - Registry_rest_2023-06-03_experimental + - Registry_rest_2024-10-15_ga - someOtherApi --- `[1:]+string(vervetAPIs)) @@ -178,7 +178,7 @@ func TestDoesNotOutputStabilitiesAfterPivotDate(t *testing.T) { catalog, err := LoadCatalogInfo(bytes.NewBufferString(catalogSrc)) c.Assert(err, qt.IsNil) versionsRoot := testdata.Path("output") - err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)) + err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), "rest") c.Assert(err, qt.IsNil) var saveOutput bytes.Buffer @@ -186,16 +186,28 @@ func TestDoesNotOutputStabilitiesAfterPivotDate(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(saveOutput.String(), qt.Equals, catalogSrc+` providesApis: - - Registry_2021-06-01_experimental - - Registry_2021-06-04_experimental - - Registry_2021-06-07_experimental - - Registry_2021-06-13_beta - - Registry_2021-06-13_experimental - - Registry_2021-08-20_experimental - - Registry_2023-06-01 - - Registry_2023-06-02 - - Registry_2023-06-03 - - Registry_2024-10-15 + - Registry_rest_2021-06-01_experimental + - Registry_rest_2021-06-04_experimental + - Registry_rest_2021-06-07_experimental + - Registry_rest_2021-06-13_beta + - Registry_rest_2021-06-13_experimental + - Registry_rest_2021-08-20_experimental + - Registry_rest_2023-06-01 + - Registry_rest_2023-06-02 + - Registry_rest_2023-06-03 + - Registry_rest_2024-10-15 --- `[1:]+string(vervetAPIs)) } + +func TestWarnsAboutConflictingNames(t *testing.T) { + c := qt.New(t) + catalog, err := LoadCatalogInfo(bytes.NewBufferString(catalogSrc)) + c.Assert(err, qt.IsNil) + versionsRoot := testdata.Path("output") + err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), "rest") + c.Assert(err, qt.IsNil) + + err = catalog.LoadVervetAPIs(testdata.Path("."), versionsRoot, time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC), "rest") + c.Assert(err, qt.IsNotNil) +} diff --git a/internal/cmd/backstage.go b/internal/cmd/backstage.go index 0f832d51..cc54fb6c 100644 --- a/internal/cmd/backstage.go +++ b/internal/cmd/backstage.go @@ -194,7 +194,7 @@ func processCatalog(ctx *cli.Context, w io.Writer) error { for _, outputPath := range outputPaths { outputPath = filepath.Join(projectDir, outputPath) if matchPath(outputPath) { - if err := catalogInfo.LoadVervetAPIs(projectDir, outputPath, pivotDate.Date); err != nil { + if err := catalogInfo.LoadVervetAPIs(projectDir, outputPath, pivotDate.Date, apiName); err != nil { return err } break diff --git a/testdata/catalog-vervet-apis-with-pivot.yaml b/testdata/catalog-vervet-apis-with-pivot.yaml index 2eb5ea08..4bc2e043 100644 --- a/testdata/catalog-vervet-apis-with-pivot.yaml +++ b/testdata/catalog-vervet-apis-with-pivot.yaml @@ -2,7 +2,7 @@ apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-01_experimental + name: Registry_rest_2021-06-01_experimental title: Registry 2021-06-01 experimental annotations: api.snyk.io/generated-by: vervet @@ -25,7 +25,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-04_experimental + name: Registry_rest_2021-06-04_experimental title: Registry 2021-06-04 experimental annotations: api.snyk.io/generated-by: vervet @@ -48,7 +48,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-07_experimental + name: Registry_rest_2021-06-07_experimental title: Registry 2021-06-07 experimental annotations: api.snyk.io/generated-by: vervet @@ -71,7 +71,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-13_beta + name: Registry_rest_2021-06-13_beta title: Registry 2021-06-13 beta annotations: api.snyk.io/generated-by: vervet @@ -94,7 +94,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-13_experimental + name: Registry_rest_2021-06-13_experimental title: Registry 2021-06-13 experimental annotations: api.snyk.io/generated-by: vervet @@ -117,7 +117,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-08-20_experimental + name: Registry_rest_2021-08-20_experimental title: Registry 2021-08-20 experimental annotations: api.snyk.io/generated-by: vervet @@ -140,7 +140,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-01 + name: Registry_rest_2023-06-01 title: Registry 2023-06-01 annotations: api.snyk.io/generated-by: vervet @@ -159,7 +159,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-02 + name: Registry_rest_2023-06-02 title: Registry 2023-06-02 annotations: api.snyk.io/generated-by: vervet @@ -178,7 +178,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-03 + name: Registry_rest_2023-06-03 title: Registry 2023-06-03 annotations: api.snyk.io/generated-by: vervet @@ -197,7 +197,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2024-10-15 + name: Registry_rest_2024-10-15 title: Registry 2024-10-15 annotations: api.snyk.io/generated-by: vervet diff --git a/testdata/catalog-vervet-apis.yaml b/testdata/catalog-vervet-apis.yaml index ceaacf7c..92d2b1fa 100644 --- a/testdata/catalog-vervet-apis.yaml +++ b/testdata/catalog-vervet-apis.yaml @@ -2,7 +2,7 @@ apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-01_experimental + name: Registry_rest_2021-06-01_experimental title: Registry 2021-06-01 experimental annotations: api.snyk.io/generated-by: vervet @@ -25,7 +25,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-04_experimental + name: Registry_rest_2021-06-04_experimental title: Registry 2021-06-04 experimental annotations: api.snyk.io/generated-by: vervet @@ -48,7 +48,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-07_experimental + name: Registry_rest_2021-06-07_experimental title: Registry 2021-06-07 experimental annotations: api.snyk.io/generated-by: vervet @@ -71,7 +71,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-13_beta + name: Registry_rest_2021-06-13_beta title: Registry 2021-06-13 beta annotations: api.snyk.io/generated-by: vervet @@ -94,7 +94,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-06-13_experimental + name: Registry_rest_2021-06-13_experimental title: Registry 2021-06-13 experimental annotations: api.snyk.io/generated-by: vervet @@ -117,7 +117,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2021-08-20_experimental + name: Registry_rest_2021-08-20_experimental title: Registry 2021-08-20 experimental annotations: api.snyk.io/generated-by: vervet @@ -140,7 +140,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-01_experimental + name: Registry_rest_2023-06-01_experimental title: Registry 2023-06-01 experimental annotations: api.snyk.io/generated-by: vervet @@ -163,7 +163,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-02_experimental + name: Registry_rest_2023-06-02_experimental title: Registry 2023-06-02 experimental annotations: api.snyk.io/generated-by: vervet @@ -186,7 +186,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2023-06-03_experimental + name: Registry_rest_2023-06-03_experimental title: Registry 2023-06-03 experimental annotations: api.snyk.io/generated-by: vervet @@ -209,7 +209,7 @@ spec: apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: Registry_2024-10-15_ga + name: Registry_rest_2024-10-15_ga title: Registry 2024-10-15 ga annotations: api.snyk.io/generated-by: vervet