From 7b83cacd4babf5d444786db8866467a925ecb11f Mon Sep 17 00:00:00 2001 From: Sri Vignesh Date: Thu, 2 Apr 2026 13:06:06 +0530 Subject: [PATCH] Multicluster workaround Signed-off-by: Sri Vignesh --- pkg/config/config.go | 5 ++++ pkg/oc/oc.go | 71 ++++++++++++++++++++++++++++++++++++++++++-- pkg/pac/pac.go | 39 +++++++++++++++++++++++- 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 69c16e22..2b565fbc 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -116,6 +116,11 @@ var TektonInstallersetNamePrefixes [34]string = [34]string{ var PrefixesOfDefaultPipelines [9]string = [9]string{"buildah", "s2i-dotnet", "s2i-go", "s2i-java", "s2i-nodejs", "s2i-perl", "s2i-php", "s2i-python", "s2i-ruby"} +var ( + HubKubeconfig = os.Getenv("HUB_KUBECONFIG") + SpokeKubeconfig = os.Getenv("SPOKE_KUBECONFIG") +) + // Flags holds the command line flags or defaults for settings in the user's environment. // See EnvironmentFlags for a list of supported fields // Todo: change initialization of falgs when required by parsing them or from environment variable diff --git a/pkg/oc/oc.go b/pkg/oc/oc.go index bd98fa97..f051fd50 100644 --- a/pkg/oc/oc.go +++ b/pkg/oc/oc.go @@ -36,9 +36,56 @@ func Delete(path_dir, namespace string) { log.Printf("output: %s\n", cmd.MustSuccedIncreasedTimeout(time.Second*300, "oc", "delete", "-f", config.Path(path_dir), "-n", namespace).Stdout()) } -// CreateNewProject Helps you to create new project +// CreateNewProject creates a new project on the local cluster, and also +// mirrors the project + a Kueue LocalQueue on hub and spoke clusters when +// HUB_KUBECONFIG / SPOKE_KUBECONFIG environment variables are set. func CreateNewProject(ns string) { log.Printf("output: %s\n", cmd.MustSucceed("oc", "new-project", ns).Stdout()) + setupRemoteClusters(ns) +} + +func setupRemoteClusters(ns string) { + for _, kc := range []struct { + name string + kubeconfig string + }{ + {"hub", config.HubKubeconfig}, + {"spoke", config.SpokeKubeconfig}, + } { + if kc.kubeconfig == "" { + continue + } + log.Printf("Setting up project %q on %s cluster", ns, kc.name) + createProjectOnRemoteCluster(ns, kc.kubeconfig, kc.name) + createLocalQueueOnRemoteCluster(ns, kc.kubeconfig, kc.name) + } +} + +func createProjectOnRemoteCluster(ns, kubeconfig, clusterName string) { + result := cmd.Run("oc", "new-project", ns, "--kubeconfig", kubeconfig) + if result.ExitCode != 0 { + log.Printf("Warning: failed to create project %q on %s cluster: %s", ns, clusterName, result.Stderr()) + return + } + log.Printf("Created project %q on %s cluster", ns, clusterName) +} + +func createLocalQueueOnRemoteCluster(ns, kubeconfig, clusterName string) { + localQueueYAML := fmt.Sprintf(`apiVersion: kueue.x-k8s.io/v1beta2 +kind: LocalQueue +metadata: + name: pipelines-queue + namespace: %s +spec: + clusterQueue: cluster-queue`, ns) + + result := cmd.Run("bash", "-c", + fmt.Sprintf("echo '%s' | oc apply --kubeconfig %s -f -", localQueueYAML, kubeconfig)) + if result.ExitCode != 0 { + log.Printf("Warning: failed to create LocalQueue in %q on %s cluster: %s", ns, clusterName, result.Stderr()) + return + } + log.Printf("Created LocalQueue 'pipelines-queue' in %q on %s cluster", ns, clusterName) } // DeleteProject Helps you to delete new project @@ -48,6 +95,26 @@ func DeleteProject(ns string) { func DeleteProjectIgnoreErors(ns string) { log.Printf("output: %s\n", cmd.Run("oc", "delete", "project", ns).Stdout()) + cleanupRemoteClusters(ns) +} + +func cleanupRemoteClusters(ns string) { + for _, kc := range []struct { + name string + kubeconfig string + }{ + {"hub", config.HubKubeconfig}, + {"spoke", config.SpokeKubeconfig}, + } { + if kc.kubeconfig == "" { + continue + } + log.Printf("Deleting project %q on %s cluster", ns, kc.name) + result := cmd.Run("oc", "delete", "project", ns, "--kubeconfig", kc.kubeconfig) + if result.ExitCode != 0 { + log.Printf("Warning: failed to delete project %q on %s cluster: %s", ns, kc.name, result.Stderr()) + } + } } func LinkSecretToSA(secretname, sa, namespace string) { @@ -172,4 +239,4 @@ func CopySecret(secretName string, sourceNamespace string, destNamespace string) cmdOutput := cmd.MustSucceed("bash", "-c", fmt.Sprintf(`echo '%s' | jq 'del(.metadata["namespace", "creationTimestamp", "resourceVersion", "selfLink", "uid", "annotations"]) | .data |= with_entries(if .key == "github-auth-key" then .key = "token" else . end)'`, secretJson)).Stdout() cmd.MustSucceed("bash", "-c", fmt.Sprintf(`echo '%s' | kubectl apply -n %s -f -`, cmdOutput, destNamespace)) log.Printf("Successfully copied secret %s from %s to %s", secretName, sourceNamespace, destNamespace) -} \ No newline at end of file +} diff --git a/pkg/pac/pac.go b/pkg/pac/pac.go index 5a40de04..35df768c 100644 --- a/pkg/pac/pac.go +++ b/pkg/pac/pac.go @@ -373,7 +373,44 @@ func generatePipelineRun(eventType, branch, fileName string) error { if err := pacgenerate.Generate(opts, true); err != nil { return fmt.Errorf("failed to generate PipelineRun: %v", err) } - return nil + return shortenPipelineRunName(fileName, eventType) +} + +// shortenPipelineRunName replaces the long auto-generated PipelineRun name +// (e.g. "release-tests-fork-12345678-pull-request") with a compact name +// like "pac-pull-request". Only the top-level metadata.name is replaced. +func shortenPipelineRunName(fileName, eventType string) error { + data, err := os.ReadFile(filepath.Clean(fileName)) + if err != nil { + return fmt.Errorf("failed to read generated file: %v", err) + } + + shortName := "pac-" + strings.ReplaceAll(eventType, "_", "-") + + var content map[string]any + if err := yaml.Unmarshal(data, &content); err != nil { + return fmt.Errorf("failed to parse generated YAML: %v", err) + } + + if meta, ok := content["metadata"].(map[any]any); ok { + meta["name"] = shortName + } + + if spec, ok := content["spec"].(map[any]any); ok { + taskRunTemplate, ok := spec["taskRunTemplate"].(map[any]any) + if !ok { + taskRunTemplate = map[any]any{} + spec["taskRunTemplate"] = taskRunTemplate + } + taskRunTemplate["serviceAccountName"] = "pipeline" + } + + out, err := yaml.Marshal(content) + if err != nil { + return fmt.Errorf("failed to marshal YAML: %v", err) + } + + return os.WriteFile(fileName, out, 0o600) } // Validate generated yaml file from pac generate cmd