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 13, 2023
1 parent 826494a commit 029162e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +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`.

- Workload cluster Node yaml is now being collected during e2e tests to assist with troubleshooting test failures.
### Suggested changes for providers

- In order to reduce dependencies for API package consumers, CAPI has diverged from the default kubebuilder scheme builder. This new pattern may also be useful for reducing dependencies in provider API packages. For more information [see the implementers guide.](../implementers-guide/create_api.md#registering-apis-in-the-scheme)
18 changes: 15 additions & 3 deletions test/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ 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/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand Down Expand Up @@ -79,13 +80,24 @@ 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.DumpVersionAndKind{
{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Pod",
Namespace: metav1.NamespaceSystem,
},
{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Node",
},
},
})
}

Expand Down
68 changes: 38 additions & 30 deletions test/framework/alltypes_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ 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"
Expand Down Expand Up @@ -132,38 +131,47 @@ func DumpAllResources(ctx context.Context, input DumpAllResourcesInput) {
}
}

// DumpKubeSystemPodsForClusterInput is the input for DumpKubeSystemPodsForCluster.
type DumpKubeSystemPodsForClusterInput struct {
Lister Lister
LogPath string
Cluster *clusterv1.Cluster
// DumpVersionAndKind specifies a version and kind which will be dumped

Check failure on line 134 in test/framework/alltypes_helpers.go

View workflow job for this annotation

GitHub Actions / lint (test)

Comment should end in a period (godot)

Check failure on line 134 in test/framework/alltypes_helpers.go

View workflow job for this annotation

GitHub Actions / lint (test)

Comment should end in a period (godot)
type DumpVersionAndKind struct {
APIVersion string
Kind string
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 []DumpVersionAndKind
}

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.SetAPIVersion(resource.APIVersion)
resourceList.SetKind(resource.Kind)
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.Kind, klog.KObj(input.Cluster), listErr)
continue
}
for i := range resourceList.Items {
dumpObject(&resourceList.Items[i], input.LogPath)
}
}
}

Expand Down

0 comments on commit 029162e

Please sign in to comment.