Skip to content

Commit

Permalink
Add spec.min, spec.max to categories endpoint (#1059)
Browse files Browse the repository at this point in the history
Add spec.min and spec.max query parameters as part of the
categories endpoint.
  • Loading branch information
mrodm authored Jul 27, 2023
1 parent d009793 commit 4e84d23
Show file tree
Hide file tree
Showing 10 changed files with 435 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Add new query parameter "capabilities" in search endpoint [#1054](https://github.com/elastic/package-registry/pull/1054)
* Add new query parameter "capabilities" in categories endpoint [#1061](https://github.com/elastic/package-registry/pull/1061))
* Add new query parameters "spec.min" and "spec.max" in search endpoint [#1058](https://github.com/elastic/package-registry/pull/1058)
* Add new query parameters "spec.min" and "spec.max" in categories endpoint [#1059](https://github.com/elastic/package-registry/pull/1059)

### Deprecated

Expand Down
14 changes: 14 additions & 0 deletions categories.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,20 @@ func newCategoriesFilterFromQuery(query url.Values) (*packages.Filter, error) {
filter.Capabilities = strings.Split(v, ",")
}

if v := query.Get("spec.min"); v != "" {
filter.SpecMin, err = getSpecVersion(v)
if err != nil {
return nil, fmt.Errorf("invalid 'spec.min' version: %w", err)
}
}

if v := query.Get("spec.max"); v != "" {
filter.SpecMax, err = getSpecVersion(v)
if err != nil {
return nil, fmt.Errorf("invalid 'spec.max' version: %w", err)
}
}

return &filter, nil
}

Expand Down
223 changes: 223 additions & 0 deletions categories_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package main

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/elastic/package-registry/packages"
"github.com/elastic/package-registry/proxymode"
)

func TestCategoriesWithProxyMode(t *testing.T) {
webServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
response := `[
{
"id": "custom",
"title": "Custom",
"count": 10
},
{
"id": "custom_logs",
"title": "Custom Logs",
"count": 3,
"parent_id": "custom",
"parent_title": "Custom"
}
]`
w.Header().Set("Content-Type", "application/json")
fmt.Fprintln(w, response)
}))
defer webServer.Close()

indexerProxy := packages.NewFileSystemIndexer(testLogger, "./testdata/second_package_path")
err := indexerProxy.Init(context.Background())
require.NoError(t, err)

proxyMode, err := proxymode.NewProxyMode(
testLogger,
proxymode.ProxyOptions{
Enabled: true,
ProxyTo: webServer.URL,
},
)
require.NoError(t, err)

categoriesWithProxyHandler := categoriesHandlerWithProxyMode(testLogger, indexerProxy, proxyMode, testCacheTime)

tests := []struct {
endpoint string
path string
file string
handler func(w http.ResponseWriter, r *http.Request)
}{
{"/categories", "/categories", "categories-proxy.json", categoriesWithProxyHandler},
{"/categories?kibana.version=6.5.0", "/categories", "categories-proxy-kibana-filter.json", categoriesWithProxyHandler},
}

for _, test := range tests {
t.Run(test.endpoint, func(t *testing.T) {
runEndpoint(t, test.endpoint, test.path, test.file, test.handler)
})
}
}

func TestGetCategories(t *testing.T) {
filterTestPackages := []filterCategoryTestPackage{
{
Name: "mypackage",
Version: "1.0.0",
Categories: []string{
"observability",
"network",
},
},
{
Name: "foo",
Version: "1.1.0",
Categories: []string{
"observability",
"security",
},
PolicyTemplateCategories: [][]string{
[]string{
"network",
},
},
},
{
Name: "web",
Version: "2.0.0-rc2",
Categories: []string{
"web",
},
PolicyTemplateCategories: [][]string{
[]string{
"security",
},
[]string{
"other",
},
},
},
{
Name: "redisenterprise",
Version: "1.1.0",
},
}

pkgs := buildFilterTestPackages(filterTestPackages)

cases := []struct {
Title string
IncludePolicyTemplates bool
Expected map[string]*packages.Category
}{
{
Title: "All categories without policy templates",
IncludePolicyTemplates: false,
Expected: map[string]*packages.Category{
"network": &packages.Category{
Id: "network",
Title: "network",
Count: 1,
},
"observability": &packages.Category{
Id: "observability",
Title: "observability",
Count: 2,
},
"security": &packages.Category{
Id: "security",
Title: "security",
Count: 1,
},
"web": &packages.Category{
Id: "web",
Title: "web",
Count: 1,
},
},
},
{
Title: "All categories including policies",
IncludePolicyTemplates: true,
Expected: map[string]*packages.Category{
"network": &packages.Category{
Id: "network",
Title: "network",
Count: 3,
},
"observability": &packages.Category{
Id: "observability",
Title: "observability",
Count: 3,
},
"security": &packages.Category{
Id: "security",
Title: "security",
Count: 4,
},
"web": &packages.Category{
Id: "web",
Title: "web",
Count: 3,
},
"other": &packages.Category{
Id: "other",
Title: "other",
Count: 2,
},
},
},
}

for _, c := range cases {
t.Run(c.Title, func(t *testing.T) {
result := getCategories(context.Background(), pkgs, c.IncludePolicyTemplates)
assert.Equal(t, c.Expected, result)
})
}
}

type filterCategoryTestPackage struct {
Name string
Version string
Categories []string
PolicyTemplateCategories [][]string
}

func (p filterCategoryTestPackage) Build() *packages.Package {
var build packages.Package
build.Name = p.Name
build.Version = p.Version
build.Categories = p.Categories

if p.PolicyTemplateCategories != nil {
for _, categories := range p.PolicyTemplateCategories {
p := packages.PolicyTemplate{
Categories: categories,
}
build.PolicyTemplates = append(build.PolicyTemplates, p)
}
}

return &build
}

func buildFilterTestPackages(testPackages []filterCategoryTestPackage) packages.Packages {
packages := make(packages.Packages, len(testPackages))
for i, p := range testPackages {
packages[i] = p.Build()
}
return packages
}
5 changes: 5 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ func TestEndpoints(t *testing.T) {
{"/categories?prerelease=true&kibana.version=6.5.2", "/categories", "categories-prerelease-kibana652.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?include_policy_templates=true", "/categories", "categories-include-policy-templates.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?include_policy_templates=foo", "/categories", "categories-include-policy-templates-error.txt", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?capabilities=observability,security&prerelease=true", "/categories", "categories-prerelease-capabilities-observability-security.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?capabilities=none&prerelease=true", "/categories", "categories-prerelease-capabilities-none.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?spec.min=1.1&spec.max=2.10&prerelease=true", "/categories", "categories-spec-min-1.1.0-max-2.10.0.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?spec.max=2.10&prerelease=true", "/categories", "categories-spec-max-2.10.0.json", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/categories?spec.max=2.10.1&prerelease=true", "/categories", "categories-spec-max-error.txt", categoriesHandler(testLogger, indexer, testCacheTime)},
{"/search?kibana.version=6.5.2", "/search", "search-kibana652.json", searchHandler(testLogger, indexer, testCacheTime)},
{"/search?kibana.version=7.2.1", "/search", "search-kibana721.json", searchHandler(testLogger, indexer, testCacheTime)},
{"/search?kibana.version=8.0.0", "/search", "search-kibana800.json", searchHandler(testLogger, indexer, testCacheTime)},
Expand Down
71 changes: 0 additions & 71 deletions proxy_mode_test.go

This file was deleted.

58 changes: 58 additions & 0 deletions testdata/generated/categories-prerelease-capabilities-none.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"id": "aws",
"title": "AWS",
"count": 2
},
{
"id": "azure",
"title": "Azure",
"count": 2
},
{
"id": "cloud",
"title": "Cloud",
"count": 1
},
{
"id": "containers",
"title": "Containers",
"count": 1
},
{
"id": "crm",
"title": "CRM",
"count": 2
},
{
"id": "custom",
"title": "Custom",
"count": 15
},
{
"id": "datastore",
"title": "Database",
"count": 3
},
{
"id": "message_queue",
"title": "Message Broker",
"count": 1,
"parent_id": "observability",
"parent_title": "Observability"
},
{
"id": "monitoring",
"title": "Monitoring",
"count": 3,
"parent_id": "observability",
"parent_title": "Observability"
},
{
"id": "web",
"title": "Web Server",
"count": 3,
"parent_id": "observability",
"parent_title": "Observability"
}
]
Loading

0 comments on commit 4e84d23

Please sign in to comment.