Commit 4401c814 authored by Maciej Szulik's avatar Maciej Szulik

Read resources from all versions for finalization and gc

If the same resource exists in more then one version, only the preferred version one will be returned.
parent 4dd17995
...@@ -213,9 +213,11 @@ func (d *DiscoveryClient) serverPreferredResources(namespaced bool) ([]unversion ...@@ -213,9 +213,11 @@ func (d *DiscoveryClient) serverPreferredResources(namespaced bool) ([]unversion
const maxRetries = 2 const maxRetries = 2
var failedGroups map[unversioned.GroupVersion]error var failedGroups map[unversioned.GroupVersion]error
var results []unversioned.GroupVersionResource var results []unversioned.GroupVersionResource
var resources map[unversioned.GroupResource]string
RetrieveGroups: RetrieveGroups:
for i := 0; i < maxRetries; i++ { for i := 0; i < maxRetries; i++ {
results = []unversioned.GroupVersionResource{} results = []unversioned.GroupVersionResource{}
resources = map[unversioned.GroupResource]string{}
failedGroups = make(map[unversioned.GroupVersion]error) failedGroups = make(map[unversioned.GroupVersion]error)
serverGroupList, err := d.ServerGroups() serverGroupList, err := d.ServerGroups()
if err != nil { if err != nil {
...@@ -223,25 +225,40 @@ RetrieveGroups: ...@@ -223,25 +225,40 @@ RetrieveGroups:
} }
for _, apiGroup := range serverGroupList.Groups { for _, apiGroup := range serverGroupList.Groups {
preferredVersion := apiGroup.PreferredVersion versions := apiGroup.Versions
groupVersion := unversioned.GroupVersion{Group: apiGroup.Name, Version: preferredVersion.Version} for _, version := range versions {
apiResourceList, err := d.ServerResourcesForGroupVersion(preferredVersion.GroupVersion) groupVersion := unversioned.GroupVersion{Group: apiGroup.Name, Version: version.Version}
if err != nil { apiResourceList, err := d.ServerResourcesForGroupVersion(version.GroupVersion)
if i < maxRetries-1 { if err != nil {
continue RetrieveGroups if i < maxRetries-1 {
} continue RetrieveGroups
failedGroups[groupVersion] = err }
continue failedGroups[groupVersion] = err
}
for _, apiResource := range apiResourceList.APIResources {
// ignore the root scoped resources if "namespaced" is true.
if namespaced && !apiResource.Namespaced {
continue continue
} }
if strings.Contains(apiResource.Name, "/") { for _, apiResource := range apiResourceList.APIResources {
continue // ignore the root scoped resources if "namespaced" is true.
if namespaced && !apiResource.Namespaced {
continue
}
if strings.Contains(apiResource.Name, "/") {
continue
}
gvr := groupVersion.WithResource(apiResource.Name)
if _, ok := resources[gvr.GroupResource()]; ok {
if gvr.Version != apiGroup.PreferredVersion.Version {
continue
}
// remove previous entry, because it will be replaced with a preferred one
for i := range results {
if results[i].GroupResource() == gvr.GroupResource() {
results = append(results[:i], results[i+1:]...)
}
}
}
resources[gvr.GroupResource()] = gvr.Version
results = append(results, gvr)
} }
results = append(results, groupVersion.WithResource(apiResource.Name))
} }
} }
if len(failedGroups) == 0 { if len(failedGroups) == 0 {
......
...@@ -321,7 +321,7 @@ func TestGetSwaggerSchemaFail(t *testing.T) { ...@@ -321,7 +321,7 @@ func TestGetSwaggerSchemaFail(t *testing.T) {
} }
} }
func TestGetServerPreferredResources(t *testing.T) { func TestServerPreferredResources(t *testing.T) {
stable := unversioned.APIResourceList{ stable := unversioned.APIResourceList{
GroupVersion: "v1", GroupVersion: "v1",
APIResources: []unversioned.APIResource{ APIResources: []unversioned.APIResource{
...@@ -330,14 +330,6 @@ func TestGetServerPreferredResources(t *testing.T) { ...@@ -330,14 +330,6 @@ func TestGetServerPreferredResources(t *testing.T) {
{Name: "namespaces", Namespaced: false, Kind: "Namespace"}, {Name: "namespaces", Namespaced: false, Kind: "Namespace"},
}, },
} }
/*beta := unversioned.APIResourceList{
GroupVersion: "extensions/v1",
APIResources: []unversioned.APIResource{
{Name: "deployments", Namespaced: true, Kind: "Deployment"},
{Name: "ingresses", Namespaced: true, Kind: "Ingress"},
{Name: "jobs", Namespaced: true, Kind: "Job"},
},
}*/
tests := []struct { tests := []struct {
resourcesList *unversioned.APIResourceList resourcesList *unversioned.APIResourceList
response func(w http.ResponseWriter, req *http.Request) response func(w http.ResponseWriter, req *http.Request)
...@@ -427,9 +419,6 @@ func TestGetServerPreferredResources(t *testing.T) { ...@@ -427,9 +419,6 @@ func TestGetServerPreferredResources(t *testing.T) {
w.Write(output) w.Write(output)
}, },
}, },
/*{
resourcesList: &stable,
},*/
} }
for _, test := range tests { for _, test := range tests {
server := httptest.NewServer(http.HandlerFunc(test.response)) server := httptest.NewServer(http.HandlerFunc(test.response))
...@@ -455,7 +444,7 @@ func TestGetServerPreferredResources(t *testing.T) { ...@@ -455,7 +444,7 @@ func TestGetServerPreferredResources(t *testing.T) {
} }
} }
func TestGetServerPreferredResourcesRetries(t *testing.T) { func TestServerPreferredResourcesRetries(t *testing.T) {
stable := unversioned.APIResourceList{ stable := unversioned.APIResourceList{
GroupVersion: "v1", GroupVersion: "v1",
APIResources: []unversioned.APIResource{ APIResources: []unversioned.APIResource{
...@@ -553,3 +542,173 @@ func TestGetServerPreferredResourcesRetries(t *testing.T) { ...@@ -553,3 +542,173 @@ func TestGetServerPreferredResourcesRetries(t *testing.T) {
server.Close() server.Close()
} }
} }
func TestServerPreferredNamespacedResources(t *testing.T) {
stable := unversioned.APIResourceList{
GroupVersion: "v1",
APIResources: []unversioned.APIResource{
{Name: "pods", Namespaced: true, Kind: "Pod"},
{Name: "services", Namespaced: true, Kind: "Service"},
{Name: "namespaces", Namespaced: false, Kind: "Namespace"},
},
}
batchv1 := unversioned.APIResourceList{
GroupVersion: "batch/v1",
APIResources: []unversioned.APIResource{
{Name: "jobs", Namespaced: true, Kind: "Job"},
},
}
batchv2alpha1 := unversioned.APIResourceList{
GroupVersion: "batch/v2alpha1",
APIResources: []unversioned.APIResource{
{Name: "jobs", Namespaced: true, Kind: "Job"},
{Name: "cronjobs", Namespaced: true, Kind: "CronJob"},
},
}
batchv3alpha1 := unversioned.APIResourceList{
GroupVersion: "batch/v3alpha1",
APIResources: []unversioned.APIResource{
{Name: "jobs", Namespaced: true, Kind: "Job"},
{Name: "cronjobs", Namespaced: true, Kind: "CronJob"},
},
}
tests := []struct {
response func(w http.ResponseWriter, req *http.Request)
expected []unversioned.GroupVersionResource
}{
{
response: func(w http.ResponseWriter, req *http.Request) {
var list interface{}
switch req.URL.Path {
case "/api/v1":
list = &stable
case "/api":
list = &unversioned.APIVersions{
Versions: []string{
"v1",
},
}
default:
t.Logf("unexpected request: %s", req.URL.Path)
w.WriteHeader(http.StatusNotFound)
return
}
output, err := json.Marshal(list)
if err != nil {
t.Errorf("unexpected encoding error: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(output)
},
expected: []unversioned.GroupVersionResource{
{Group: "", Version: "v1", Resource: "pods"},
{Group: "", Version: "v1", Resource: "services"},
},
},
{
response: func(w http.ResponseWriter, req *http.Request) {
var list interface{}
switch req.URL.Path {
case "/apis":
list = &unversioned.APIGroupList{
Groups: []unversioned.APIGroup{
{
Name: "batch",
Versions: []unversioned.GroupVersionForDiscovery{
{GroupVersion: "batch/v1", Version: "v1"},
{GroupVersion: "batch/v2alpha1", Version: "v2alpha1"},
{GroupVersion: "batch/v3alpha1", Version: "v3alpha1"},
},
PreferredVersion: unversioned.GroupVersionForDiscovery{GroupVersion: "batch/v1", Version: "v1"},
},
},
}
case "/apis/batch/v1":
list = &batchv1
case "/apis/batch/v2alpha1":
list = &batchv2alpha1
case "/apis/batch/v3alpha1":
list = &batchv3alpha1
default:
t.Logf("unexpected request: %s", req.URL.Path)
w.WriteHeader(http.StatusNotFound)
return
}
output, err := json.Marshal(list)
if err != nil {
t.Errorf("unexpected encoding error: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(output)
},
expected: []unversioned.GroupVersionResource{
{Group: "batch", Version: "v1", Resource: "jobs"},
{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"},
},
},
{
response: func(w http.ResponseWriter, req *http.Request) {
var list interface{}
switch req.URL.Path {
case "/apis":
list = &unversioned.APIGroupList{
Groups: []unversioned.APIGroup{
{
Name: "batch",
Versions: []unversioned.GroupVersionForDiscovery{
{GroupVersion: "batch/v1", Version: "v1"},
{GroupVersion: "batch/v2alpha1", Version: "v2alpha1"},
{GroupVersion: "batch/v3alpha1", Version: "v3alpha1"},
},
PreferredVersion: unversioned.GroupVersionForDiscovery{GroupVersion: "batch/v2alpha", Version: "v2alpha1"},
},
},
}
case "/apis/batch/v1":
list = &batchv1
case "/apis/batch/v2alpha1":
list = &batchv2alpha1
case "/apis/batch/v3alpha1":
list = &batchv3alpha1
default:
t.Logf("unexpected request: %s", req.URL.Path)
w.WriteHeader(http.StatusNotFound)
return
}
output, err := json.Marshal(list)
if err != nil {
t.Errorf("unexpected encoding error: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(output)
},
expected: []unversioned.GroupVersionResource{
{Group: "batch", Version: "v2alpha1", Resource: "jobs"},
{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"},
},
},
}
for _, test := range tests {
server := httptest.NewServer(http.HandlerFunc(test.response))
defer server.Close()
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
got, err := client.ServerPreferredNamespacedResources()
if err != nil {
t.Errorf("unexpected error: %v", err)
continue
}
// we need deterministic order and since during processing in ServerPreferredNamespacedResources
// a map comes into play the result needs sorting
if !reflect.DeepEqual(got, test.expected) {
t.Errorf("expected:\n%v\ngot:\n%v\n", test.expected, got)
}
server.Close()
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment