mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 18:29:53 +00:00
Merge pull request #434 from croomes/handle-api-deprecations
Handle k8s api deprecations
This commit is contained in:
@@ -13,9 +13,13 @@ import (
|
||||
authorizationv1 "k8s.io/api/authorization/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
|
||||
apiextensionsv1beta1clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil/discovery"
|
||||
)
|
||||
|
||||
func ClusterResources(c *Collector, clusterResourcesCollector *troubleshootv1beta2.ClusterResources) (CollectorResult, error) {
|
||||
@@ -105,11 +109,7 @@ func ClusterResources(c *Collector, clusterResourcesCollector *troubleshootv1bet
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/storage-errors.json", marshalErrors(storageErrors))
|
||||
|
||||
// crds
|
||||
crdClient, err := apiextensionsv1beta1clientset.NewForConfig(c.ClientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customResourceDefinitions, crdErrors := crds(ctx, crdClient)
|
||||
customResourceDefinitions, crdErrors := crds(ctx, client, c.ClientConfig)
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/custom-resource-definitions.json", bytes.NewBuffer(customResourceDefinitions))
|
||||
output.SaveResult(c.BundlePath, "cluster-resources/custom-resource-definitions-errors.json", marshalErrors(crdErrors))
|
||||
|
||||
@@ -355,6 +355,41 @@ func cronJobs(ctx context.Context, client *kubernetes.Clientset, namespaces []st
|
||||
}
|
||||
|
||||
func ingress(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
ok, err := discovery.HasResource(client, "networking.k8s.io/v1", "Ingress")
|
||||
if err != nil {
|
||||
return nil, map[string]string{"": err.Error()}
|
||||
}
|
||||
if ok {
|
||||
return ingressV1(ctx, client, namespaces)
|
||||
}
|
||||
|
||||
return ingressV1beta(ctx, client, namespaces)
|
||||
}
|
||||
|
||||
func ingressV1(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
ingressByNamespace := make(map[string][]byte)
|
||||
errorsByNamespace := make(map[string]string)
|
||||
|
||||
for _, namespace := range namespaces {
|
||||
ingress, err := client.NetworkingV1().Ingresses(namespace).List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
errorsByNamespace[namespace] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(ingress.Items, "", " ")
|
||||
if err != nil {
|
||||
errorsByNamespace[namespace] = err.Error()
|
||||
continue
|
||||
}
|
||||
|
||||
ingressByNamespace[namespace+".json"] = b
|
||||
}
|
||||
|
||||
return ingressByNamespace, errorsByNamespace
|
||||
}
|
||||
|
||||
func ingressV1beta(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
|
||||
ingressByNamespace := make(map[string][]byte)
|
||||
errorsByNamespace := make(map[string]string)
|
||||
|
||||
@@ -378,6 +413,32 @@ func ingress(ctx context.Context, client *kubernetes.Clientset, namespaces []str
|
||||
}
|
||||
|
||||
func storageClasses(ctx context.Context, client *kubernetes.Clientset) ([]byte, []string) {
|
||||
ok, err := discovery.HasResource(client, "storage.k8s.io/v1", "StorageClass")
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
if ok {
|
||||
return storageClassesV1(ctx, client)
|
||||
}
|
||||
|
||||
return storageClassesV1beta(ctx, client)
|
||||
}
|
||||
|
||||
func storageClassesV1(ctx context.Context, client *kubernetes.Clientset) ([]byte, []string) {
|
||||
storageClasses, err := client.StorageV1().StorageClasses().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(storageClasses.Items, "", " ")
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func storageClassesV1beta(ctx context.Context, client *kubernetes.Clientset) ([]byte, []string) {
|
||||
storageClasses, err := client.StorageV1beta1().StorageClasses().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
@@ -391,7 +452,43 @@ func storageClasses(ctx context.Context, client *kubernetes.Clientset) ([]byte,
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func crds(ctx context.Context, client *apiextensionsv1beta1clientset.ApiextensionsV1beta1Client) ([]byte, []string) {
|
||||
func crds(ctx context.Context, client *kubernetes.Clientset, config *rest.Config) ([]byte, []string) {
|
||||
ok, err := discovery.HasResource(client, "apiextensions.k8s.io/v1", "CustomResourceDefinition")
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
if ok {
|
||||
return crdsV1(ctx, config)
|
||||
}
|
||||
|
||||
return crdsV1beta(ctx, config)
|
||||
}
|
||||
|
||||
func crdsV1(ctx context.Context, config *rest.Config) ([]byte, []string) {
|
||||
client, err := apiextensionsv1clientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
crds, err := client.CustomResourceDefinitions().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
b, err := json.MarshalIndent(crds.Items, "", " ")
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func crdsV1beta(ctx context.Context, config *rest.Config) ([]byte, []string) {
|
||||
client, err := apiextensionsv1beta1clientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
}
|
||||
|
||||
crds, err := client.CustomResourceDefinitions().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, []string{err.Error()}
|
||||
|
||||
25
pkg/k8sutil/discovery/discovery.go
Normal file
25
pkg/k8sutil/discovery/discovery.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
// HasResource takes an api version and a kind of a resource and checks if the resource
|
||||
// is supported by the k8s api server.
|
||||
func HasResource(dc discovery.DiscoveryInterface, apiVersion, kind string) (bool, error) {
|
||||
_, apiLists, err := dc.ServerGroupsAndResources()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// Compare the resource api version and kind and find the resource.
|
||||
for _, apiList := range apiLists {
|
||||
if apiList.GroupVersion == apiVersion {
|
||||
for _, r := range apiList.APIResources {
|
||||
if r.Kind == kind {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
80
pkg/k8sutil/discovery/discovery_test.go
Normal file
80
pkg/k8sutil/discovery/discovery_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
fakeclientset "k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func TestHasResource(t *testing.T) {
|
||||
testKind := "Foo"
|
||||
testKindGroupVersion := "v1"
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
apiResourceList []*metav1.APIResourceList
|
||||
wantResult bool
|
||||
}{
|
||||
{
|
||||
name: "empty api resource list",
|
||||
apiResourceList: []*metav1.APIResourceList{},
|
||||
wantResult: false,
|
||||
},
|
||||
{
|
||||
name: "have resource",
|
||||
apiResourceList: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "v1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{
|
||||
Kind: "Foo",
|
||||
},
|
||||
{
|
||||
Kind: "Bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantResult: true,
|
||||
},
|
||||
{
|
||||
name: "have resource but different version",
|
||||
apiResourceList: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "v2",
|
||||
APIResources: []metav1.APIResource{
|
||||
{
|
||||
Kind: "Foo",
|
||||
},
|
||||
{
|
||||
Kind: "Bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
client := fakeclientset.NewSimpleClientset()
|
||||
fakeDiscovery, ok := client.Discovery().(*fakediscovery.FakeDiscovery)
|
||||
if !ok {
|
||||
t.Fatalf("could not convert Discovery() to *FakeDiscovery")
|
||||
}
|
||||
fakeDiscovery.Resources = tc.apiResourceList
|
||||
|
||||
exists, err := HasResource(fakeDiscovery, testKindGroupVersion, testKind)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to check if resource exists: %v", err)
|
||||
}
|
||||
if exists != tc.wantResult {
|
||||
t.Errorf("unexpected result for HasResource:\n\t(WNT) %t\n\t(GOT) %t", tc.wantResult, exists)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user