hack/loadtest/util/help.go (206 lines of code) (raw):
package util
import (
"context"
"fmt"
"os"
"strconv"
"strings"
prometheusClient "github.com/prometheus/client_model/go"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
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/util/yaml"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"go.goms.io/fleet/apis/placement/v1beta1"
)
type ClusterNames []string
func (i *ClusterNames) String() string {
return "member cluster names: " + strings.Join(*i, ",")
}
func (i *ClusterNames) Set(value string) error {
*i = append(*i, value)
return nil
}
func printMetricFamily(mf *prometheusClient.MetricFamily) {
results := mf.GetName() + " (sec): "
for _, m := range mf.GetMetric() {
for _, q := range m.GetSummary().GetQuantile() {
results += fmt.Sprintf("[Quantile %v: %v] ", q.GetQuantile(), q.GetValue())
}
}
klog.Info(results)
}
// applyObjectFromManifest apply an object from manifest
func applyObjectFromManifest(ctx context.Context, hubClient client.Client, namespaceName string, relativeFilePath string) error {
obj, err := readObjFromFile(relativeFilePath, namespaceName)
if err != nil {
return err
}
return hubClient.Create(ctx, obj)
}
// deleteObjectFromManifest delete an object from manifest
func deleteObjectFromManifest(ctx context.Context, hubClient client.Client, namespaceName string, relativeFilePath string) error {
obj, err := readObjFromFile(relativeFilePath, namespaceName)
if err != nil {
return err
}
return hubClient.Delete(ctx, obj)
}
// readObjFromFile returns a runtime object decoded from the file
func readObjFromFile(relativeFilePath string, namespaceName string) (*unstructured.Unstructured, error) {
// Read files, create manifest
rawByte, err := os.ReadFile(relativeFilePath)
if err != nil {
return nil, err
}
json, err := yaml.ToJSON(rawByte)
if err != nil {
return nil, err
}
obj := &unstructured.Unstructured{}
err = obj.UnmarshalJSON(json)
if err != nil {
return nil, err
}
if len(namespaceName) != 0 {
obj.SetNamespace(namespaceName)
}
return obj, nil
}
func ApplyClusterScopeManifests(ctx context.Context, hubClient client.Client) error {
if err := applyObjectFromManifest(ctx, hubClient, "", "test/manifests/test_testresources_crd.yaml"); err != nil {
if !apierrors.IsAlreadyExists(err) {
return err
}
}
if err := applyObjectFromManifest(ctx, hubClient, "", "hack/loadtest/manifests/test_clusterrole.yaml"); err != nil {
if !apierrors.IsAlreadyExists(err) {
return err
}
}
return nil
}
// applyTestManifests creates the test manifests in the hub cluster under a namespace
func applyTestManifests(ctx context.Context, hubClient client.Client, namespaceName string) error {
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespaceName,
Labels: map[string]string{
labelKey: namespaceName,
},
},
}
if err := hubClient.Create(ctx, ns); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test_pdb.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-secret.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-service.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "test/manifests/test-resource.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap-2.yaml"); err != nil {
return err
}
if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-role.yaml"); err != nil {
return err
}
return applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-rolebinding.yaml")
}
// deleteTestManifests deletes the test manifests in the hub cluster under a namespace
func deleteTestManifests(ctx context.Context, hubClient client.Client, namespaceName string) error {
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test_pdb.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-secret.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-service.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "test/manifests/test-resource.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap-2.yaml"); err != nil {
return err
}
if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-role.yaml"); err != nil {
return err
}
return deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-rolebinding.yaml")
}
func deleteNamespace(ctx context.Context, hubClient client.Client, namespaceName string) error {
klog.InfoS("delete the namespace", "namespace", namespaceName)
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespaceName,
},
}
return hubClient.Delete(ctx, ns)
}
func CleanupAll(hubClient client.Client) error {
var crps v1beta1.ClusterResourcePlacementList
if err := hubClient.List(context.Background(), &crps); err != nil {
klog.ErrorS(err, "failed to list namespace")
return err
}
for index := range crps.Items {
if err := hubClient.Delete(context.Background(), &crps.Items[index]); err != nil {
klog.ErrorS(err, "failed to delete crp", "crp", crps.Items[index].Name)
}
}
var namespaces corev1.NamespaceList
if err := hubClient.List(context.Background(), &namespaces); err != nil {
klog.ErrorS(err, "failed to list namespace")
return err
}
for index := range namespaces.Items {
if strings.HasPrefix(namespaces.Items[index].Name, nsPrefix) {
if err := hubClient.Delete(context.Background(), &namespaces.Items[index]); err != nil {
klog.ErrorS(err, "failed to delete namespace", "namespace", namespaces.Items[index].Name)
}
}
}
return nil
}
func getFleetSize(crp v1beta1.ClusterResourcePlacement, clusterNames ClusterNames) (string, ClusterNames, error) {
for _, status := range crp.Status.PlacementStatuses {
if err := clusterNames.Set(status.ClusterName); err != nil {
klog.ErrorS(err, "Failed to set clusterNames.")
return "", nil, err
}
}
return strconv.Itoa(len(clusterNames)), clusterNames, nil
}
func createCRP(crp *v1beta1.ClusterResourcePlacement, crpFile string, crpName string, nsName string, useTestResources bool) error {
obj, err := readObjFromFile(fmt.Sprintf("hack/loadtest/%s", crpFile), nsName)
if err != nil {
klog.ErrorS(err, "Failed to read object from file.")
return err
}
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, crp)
if err != nil {
return err
}
crp.Name = crpName
if useTestResources {
crp.Spec.ResourceSelectors = append(crp.Spec.ResourceSelectors, v1beta1.ClusterResourceSelector{
Group: "",
Version: "v1",
Kind: "Namespace",
LabelSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{labelKey: nsName},
},
})
}
return nil
}