Skip to content

Commit

Permalink
extend test/framework to collect workload cluster nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
rvanderp3 committed Sep 14, 2023
1 parent ba786da commit 8d91fd7
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ maintainers of providers and consumers of our Go API.
### Other
- `clusterctl move` can be blocked temporarily by a provider when an object to be moved is annotated with `clusterctl.cluster.x-k8s.io/block-move`.
- `mdbook releaselink` has been changed to require a `repo` tag when used in markdown files for generating a book with `mdbook`.
- framework.DumpKubeSystemPodsForCluster was renamed to framework.DumpResourcesForCluster to facilitate the gathering of additional workload cluster resources. Pods in kube-system and Nodes are gathered from workload clusters.

### Suggested changes for providers

Expand Down
23 changes: 20 additions & 3 deletions test/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
. "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega/types"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand Down Expand Up @@ -79,13 +81,28 @@ func dumpSpecResourcesAndCleanup(ctx context.Context, specName string, clusterPr
LogPath: filepath.Join(artifactFolder, "clusters", clusterProxy.GetName(), "resources"),
})

// If the cluster still exists, dump kube-system pods of the workload cluster before deleting the cluster.
// If the cluster still exists, dump kube-system pods and nodes of the workload cluster before deleting the cluster.
if err := clusterProxy.GetClient().Get(ctx, client.ObjectKeyFromObject(cluster), &clusterv1.Cluster{}); err == nil {
Byf("Dumping kube-system Pods of Cluster %s", klog.KObj(cluster))
framework.DumpKubeSystemPodsForCluster(ctx, framework.DumpKubeSystemPodsForClusterInput{
Byf("Dumping kube-system Pods and Nodes of Cluster %s", klog.KObj(cluster))
framework.DumpResourcesForCluster(ctx, framework.DumpResourcesForClusterInput{
Lister: clusterProxy.GetWorkloadCluster(ctx, cluster.Namespace, cluster.Name).GetClient(),
Cluster: cluster,
LogPath: filepath.Join(artifactFolder, "clusters", cluster.Name, "resources"),
Resources: []framework.DumpNamespaceAndGVK{
{
GVK: schema.GroupVersionKind{
Version: corev1.SchemeGroupVersion.Version,
Kind: "Pod",
},
Namespace: metav1.NamespaceSystem,
},
{
GVK: schema.GroupVersionKind{
Version: corev1.SchemeGroupVersion.Version,
Kind: "Node",
},
},
},
})
}

Expand Down
67 changes: 37 additions & 30 deletions test/framework/alltypes_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -132,38 +132,45 @@ func DumpAllResources(ctx context.Context, input DumpAllResourcesInput) {
}
}

// DumpKubeSystemPodsForClusterInput is the input for DumpKubeSystemPodsForCluster.
type DumpKubeSystemPodsForClusterInput struct {
Lister Lister
LogPath string
Cluster *clusterv1.Cluster
// DumpNamespaceAndGVK specifies a GVK and namespace to be dumped.
type DumpNamespaceAndGVK struct {
GVK schema.GroupVersionKind
Namespace string
}

// DumpKubeSystemPodsForCluster dumps kube-system Pods to YAML.
func DumpKubeSystemPodsForCluster(ctx context.Context, input DumpKubeSystemPodsForClusterInput) {
Expect(ctx).NotTo(BeNil(), "ctx is required for DumpAllResources")
Expect(input.Lister).NotTo(BeNil(), "input.Lister is required for DumpAllResources")
Expect(input.Cluster).NotTo(BeNil(), "input.Cluster is required for DumpAllResources")

// Note: We intentionally retrieve Pods as Unstructured because we need the Pods as Unstructured for dumpObject.
podList := new(unstructured.UnstructuredList)
podList.SetAPIVersion(corev1.SchemeGroupVersion.String())
podList.SetKind("Pod")
var listErr error
_ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) {
if listErr = input.Lister.List(ctx, podList, client.InNamespace(metav1.NamespaceSystem)); listErr != nil {
return false, nil //nolint:nilerr
}
return true, nil
})
if listErr != nil {
// NB. we are treating failures in collecting kube-system pods as a non-blocking operation (best effort)
fmt.Printf("Failed to list Pods in kube-system for Cluster %s: %v\n", klog.KObj(input.Cluster), listErr)
return
}
// DumpResourcesForClusterInput is the input for DumpResourcesForClusterInput.
type DumpResourcesForClusterInput struct {
Lister Lister
LogPath string
Cluster *clusterv1.Cluster
Resources []DumpNamespaceAndGVK
}

for i := range podList.Items {
dumpObject(&podList.Items[i], input.LogPath)
// DumpResourcesForCluster dumps specified resources to yaml.
func DumpResourcesForCluster(ctx context.Context, input DumpResourcesForClusterInput) {
Expect(ctx).NotTo(BeNil(), "ctx is required for DumpResourcesForCluster")
Expect(input.Lister).NotTo(BeNil(), "input.Lister is required for DumpResourcesForCluster")
Expect(input.Cluster).NotTo(BeNil(), "input.Cluster is required for DumpResourcesForCluster")

for _, resource := range input.Resources {
// Note: We intentionally retrieve resources as Unstructured because we need the resources as Unstructured for dumpObject.
resourceList := new(unstructured.UnstructuredList)
resourceList.SetGroupVersionKind(resource.GVK)
var listErr error
_ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) {
if listErr = input.Lister.List(ctx, resourceList, client.InNamespace(resource.Namespace)); listErr != nil {
return false, nil //nolint:nilerr
}
return true, nil
})
if listErr != nil {
// NB. we are treating failures in collecting resources as a non-blocking operation (best effort)
fmt.Printf("Failed to list %s for Cluster %s: %v\n", resource.GVK.Kind, klog.KObj(input.Cluster), listErr)
continue
}
for i := range resourceList.Items {
dumpObject(&resourceList.Items[i], input.LogPath)
}
}
}

Expand Down

0 comments on commit 8d91fd7

Please sign in to comment.