mirror of https://github.com/grafana/grafana
Aggregation: Support apidiscovery.k8s.io/v2 (#91938)
parent
675a58b680
commit
d6ce6aaf44
@ -0,0 +1,233 @@ |
||||
package apiserver |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"fmt" |
||||
"net/http" |
||||
"net/http/httptest" |
||||
"testing" |
||||
|
||||
"github.com/emicklei/go-restful/v3" |
||||
"github.com/stretchr/testify/require" |
||||
v2 "k8s.io/api/apidiscovery/v2" |
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||
"k8s.io/apiserver/pkg/endpoints/discovery/aggregated" |
||||
|
||||
aggregationv0alpha1api "github.com/grafana/grafana/pkg/aggregator/apis/aggregation/v0alpha1" |
||||
) |
||||
|
||||
func TestApisProxyHandler_Handle(t *testing.T) { |
||||
v1Discovery := metav1.APIGroup{ |
||||
Name: aggregationv0alpha1api.SchemeGroupVersion.Group, |
||||
Versions: []metav1.GroupVersionForDiscovery{ |
||||
{ |
||||
GroupVersion: aggregationv0alpha1api.SchemeGroupVersion.String(), |
||||
Version: aggregationv0alpha1api.SchemeGroupVersion.Version, |
||||
}, |
||||
}, |
||||
PreferredVersion: metav1.GroupVersionForDiscovery{ |
||||
GroupVersion: aggregationv0alpha1api.SchemeGroupVersion.String(), |
||||
Version: aggregationv0alpha1api.SchemeGroupVersion.Version, |
||||
}, |
||||
} |
||||
fakeGroup := metav1.APIGroup{ |
||||
Name: "foo.example.com", |
||||
Versions: []metav1.GroupVersionForDiscovery{ |
||||
{ |
||||
GroupVersion: "foo.example.com/v1", |
||||
Version: "v1", |
||||
}, |
||||
}, |
||||
PreferredVersion: metav1.GroupVersionForDiscovery{ |
||||
GroupVersion: "foo.example.com/v1", |
||||
Version: "v1", |
||||
}, |
||||
} |
||||
fakeGroupList := metav1.APIGroupList{ |
||||
TypeMeta: metav1.TypeMeta{ |
||||
Kind: "APIGroupList", |
||||
APIVersion: "v1", |
||||
}, |
||||
Groups: []metav1.APIGroup{fakeGroup}, |
||||
} |
||||
|
||||
rm := aggregated.NewResourceManager("apis") |
||||
v2GroupVersion := v2.APIVersionDiscovery{ |
||||
Version: "v0alpha1", |
||||
Resources: []v2.APIResourceDiscovery{ |
||||
{ |
||||
Resource: "dataplaneservices", |
||||
ResponseKind: &metav1.GroupVersionKind{ |
||||
Group: "aggregation.grafana.app", |
||||
Version: "v0alpha1", |
||||
Kind: "DataPlaneService", |
||||
}, |
||||
Scope: v2.ScopeCluster, |
||||
SingularResource: "dataplaneservice", |
||||
Verbs: []string{"list", "get", "create", "update", "delete", "patch", "watch"}, |
||||
}, |
||||
}, |
||||
Freshness: v2.DiscoveryFreshnessCurrent, |
||||
} |
||||
rm.AddGroupVersion("aggregation.grafana.app", v2GroupVersion) |
||||
|
||||
v2FakeGroupVersion := v2.APIVersionDiscovery{ |
||||
Version: "v1", |
||||
Resources: []v2.APIResourceDiscovery{ |
||||
{ |
||||
Resource: "foos", |
||||
ResponseKind: &metav1.GroupVersionKind{ |
||||
Group: "foo.example.com", |
||||
Version: "v1", |
||||
Kind: "Foo", |
||||
}, |
||||
Scope: v2.ScopeNamespace, |
||||
SingularResource: "foo", |
||||
Verbs: []string{"list"}, |
||||
}, |
||||
}, |
||||
Freshness: v2.DiscoveryFreshnessStale, |
||||
} |
||||
|
||||
fakeRm := aggregated.NewResourceManager("apis") |
||||
rm.AddGroupVersion("foo.example.com", v2FakeGroupVersion) |
||||
|
||||
delegationTarget := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
switch r.Header.Get("Accept") { |
||||
case "application/json": |
||||
err := json.NewEncoder(w).Encode(fakeGroupList) |
||||
require.NoError(t, err) |
||||
return |
||||
case "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json": |
||||
fakeRm.ServeHTTP(w, r) |
||||
return |
||||
default: |
||||
fmt.Printf("Accept: %s\n", r.Header.Get("Accept")) |
||||
http.Error(w, "Bad request", http.StatusBadRequest) |
||||
} |
||||
}) |
||||
|
||||
handler := newApisProxyHandler(delegationTarget) |
||||
|
||||
chain := &restful.FilterChain{ |
||||
Target: func(req *restful.Request, resp *restful.Response) { |
||||
switch req.Request.URL.Path { |
||||
case "/apis/aggregation.grafana.app/v0alpha1": |
||||
_, err := resp.ResponseWriter.Write([]byte("v0alpha1")) |
||||
require.NoError(t, err) |
||||
return |
||||
case "/apis": |
||||
switch req.Request.Header.Get("Accept") { |
||||
case "application/json": |
||||
err := json.NewEncoder(resp.ResponseWriter).Encode(&metav1.APIGroupList{ |
||||
TypeMeta: metav1.TypeMeta{ |
||||
Kind: "APIGroupList", |
||||
APIVersion: "v1", |
||||
}, |
||||
Groups: []metav1.APIGroup{v1Discovery}, |
||||
}) |
||||
require.NoError(t, err) |
||||
return |
||||
case "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json": |
||||
rm.ServeHTTP(resp.ResponseWriter, req.Request) |
||||
return |
||||
default: |
||||
fmt.Printf("Accept: %s\n", req.Request.Header.Get("Accept")) |
||||
http.Error(resp.ResponseWriter, "Bad request", http.StatusBadRequest) |
||||
} |
||||
|
||||
default: |
||||
http.Error(resp.ResponseWriter, "not found", http.StatusNotFound) |
||||
} |
||||
}, |
||||
} |
||||
|
||||
t.Run("should return the list of API groups in v1 format", func(t *testing.T) { |
||||
req := &restful.Request{ |
||||
Request: httptest.NewRequest(http.MethodGet, "/apis", nil), |
||||
} |
||||
req.Request.Header.Set("Accept", "application/json") |
||||
rec := httptest.NewRecorder() |
||||
resp := &restful.Response{ |
||||
ResponseWriter: rec, |
||||
} |
||||
|
||||
handler.handle(req, resp, chain) |
||||
require.Equal(t, http.StatusOK, resp.StatusCode()) |
||||
require.NoError(t, resp.Error()) |
||||
require.Equal(t, "application/json", resp.Header().Get("Content-Type")) |
||||
|
||||
expectedGroupList := metav1.APIGroupList{ |
||||
TypeMeta: metav1.TypeMeta{ |
||||
Kind: "APIGroupList", |
||||
APIVersion: "v1", |
||||
}, |
||||
Groups: append([]metav1.APIGroup{v1Discovery}, fakeGroupList.Groups...), |
||||
} |
||||
|
||||
actualGroupList := metav1.APIGroupList{} |
||||
err := json.NewDecoder(rec.Body).Decode(&actualGroupList) |
||||
require.NoError(t, err) |
||||
|
||||
require.Equal(t, expectedGroupList, actualGroupList) |
||||
}) |
||||
|
||||
t.Run("should return the list of API groups in v2 format", func(t *testing.T) { |
||||
req := &restful.Request{ |
||||
Request: httptest.NewRequest(http.MethodGet, "/apis", nil), |
||||
} |
||||
req.Request.Header.Set("Accept", "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,application/json") |
||||
rec := httptest.NewRecorder() |
||||
resp := &restful.Response{ |
||||
ResponseWriter: rec, |
||||
} |
||||
|
||||
handler.handle(req, resp, chain) |
||||
require.Equal(t, http.StatusOK, resp.StatusCode()) |
||||
require.Equal(t, "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList", resp.Header().Get("Content-Type")) |
||||
|
||||
expected := v2.APIGroupDiscoveryList{ |
||||
TypeMeta: metav1.TypeMeta{ |
||||
Kind: "APIGroupDiscoveryList", |
||||
APIVersion: v2.SchemeGroupVersion.String(), |
||||
}, |
||||
ListMeta: metav1.ListMeta{}, |
||||
Items: []v2.APIGroupDiscovery{ |
||||
{ |
||||
TypeMeta: metav1.TypeMeta{}, |
||||
ObjectMeta: metav1.ObjectMeta{ |
||||
Name: "aggregation.grafana.app", |
||||
}, |
||||
Versions: []v2.APIVersionDiscovery{v2GroupVersion}, |
||||
}, |
||||
{ |
||||
TypeMeta: metav1.TypeMeta{}, |
||||
ObjectMeta: metav1.ObjectMeta{ |
||||
Name: "foo.example.com", |
||||
}, |
||||
Versions: []v2.APIVersionDiscovery{v2FakeGroupVersion}, |
||||
}, |
||||
}, |
||||
} |
||||
|
||||
actual := v2.APIGroupDiscoveryList{} |
||||
err := json.NewDecoder(rec.Body).Decode(&actual) |
||||
require.NoError(t, err) |
||||
|
||||
require.Equal(t, expected, actual) |
||||
}) |
||||
|
||||
t.Run("should handle the request if the path is not /apis", func(t *testing.T) { |
||||
req := &restful.Request{ |
||||
Request: httptest.NewRequest(http.MethodGet, "/apis/aggregation.grafana.app/v0alpha1", nil), |
||||
} |
||||
rec := httptest.NewRecorder() |
||||
resp := &restful.Response{ |
||||
ResponseWriter: rec, |
||||
} |
||||
|
||||
handler.handle(req, resp, chain) |
||||
require.Equal(t, http.StatusOK, rec.Code) |
||||
require.Equal(t, "v0alpha1", rec.Body.String()) |
||||
}) |
||||
} |
||||
Loading…
Reference in new issue