this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at toolbox-bootstrap 131 lines 3.4 kB view raw
1package cmd 2 3import ( 4 "context" 5 "fmt" 6 "os/exec" 7 "path/filepath" 8 "strings" 9 "time" 10 11 "github.com/charmbracelet/log" 12 "github.com/spf13/cobra" 13 14 "github.com/khuedoan/cloudlab/toolbox/internal/cluster" 15) 16 17const ( 18 registryNamespace = "registry" 19 registryService = "svc/registry" 20 registryPort = 5000 21 gitopsRepository = "platform" 22 gitopsTag = "latest" 23 fluxNamespace = "flux-system" 24 fluxSource = "platform" 25 fluxKustomization = "platform" 26) 27 28var ( 29 gitopsPath string 30) 31 32func init() { 33 gitopsCmd.Flags().StringVar(&gitopsPath, "path", "", "Path to the manifest bundle to publish") 34 _ = gitopsCmd.MarkFlagRequired("path") 35} 36 37var gitopsCmd = &cobra.Command{ 38 Use: "gitops", 39 Short: "Proxy the in-cluster registry and push the GitOps manifests artifact", 40 PreRunE: func(cmd *cobra.Command, args []string) error { 41 if err := validateClusterFlags(); err != nil { 42 return err 43 } 44 if _, err := exec.LookPath("flux"); err != nil { 45 return fmt.Errorf("find flux CLI: %w", err) 46 } 47 return nil 48 }, 49 RunE: runGitopsPush, 50} 51 52func runGitopsPush(cmd *cobra.Command, args []string) error { 53 manifestPath, err := filepath.Abs(gitopsPath) 54 if err != nil { 55 return fmt.Errorf("resolve path %q: %w", gitopsPath, err) 56 } 57 58 connectCtx, cancel := context.WithTimeout(cmd.Context(), connectTimeout) 59 defer cancel() 60 61 hostAddr, err := cluster.LoadHost(hostsFile, host) 62 if err != nil { 63 return fmt.Errorf("load host: %w", err) 64 } 65 66 conn, err := cluster.Connect(cluster.SSHConfig{ 67 Host: hostAddr, 68 User: sshUser, 69 KeyPath: sshKey, 70 KnownHostsPath: sshKnownHosts, 71 Timeout: connectTimeout, 72 }) 73 if err != nil { 74 return fmt.Errorf("connect to cluster: %w", err) 75 } 76 defer conn.Close() 77 78 tunnel, err := conn.Forward(connectCtx, cluster.ServiceConfig{ 79 Namespace: registryNamespace, 80 Name: registryService, 81 Port: registryPort, 82 }) 83 if err != nil { 84 return fmt.Errorf("forward registry: %w", err) 85 } 86 87 artifactURL := fmt.Sprintf("oci://%s/%s:%s", tunnel.LocalAddr, gitopsRepository, gitopsTag) 88 args = []string{ 89 "push", 90 "artifact", 91 artifactURL, 92 "--path", manifestPath, 93 "--insecure-registry", 94 } 95 96 log.Infof("pushing %s from %s", artifactURL, manifestPath) 97 98 output, err := fluxOutput(cmd.Context(), args...) 99 if err != nil { 100 return fmt.Errorf("push artifact: %w\n%s", err, strings.TrimSpace(string(output))) 101 } 102 103 if trimmed := strings.TrimSpace(string(output)); trimmed != "" { 104 log.Info(trimmed) 105 } 106 107 requestedAt := time.Now().UTC().Format(time.RFC3339Nano) 108 log.Infof("triggering Flux sync for %s/%s", fluxNamespace, fluxKustomization) 109 110 output, err = conn.RunCommandContext( 111 cmd.Context(), 112 fmt.Sprintf( 113 "kubectl annotate --overwrite -n %s ocirepository.source.toolkit.fluxcd.io/%s reconcile.fluxcd.io/requestedAt=%q && kubectl annotate --overwrite -n %s kustomization.kustomize.toolkit.fluxcd.io/%s reconcile.fluxcd.io/requestedAt=%q", 114 fluxNamespace, fluxSource, requestedAt, 115 fluxNamespace, fluxKustomization, requestedAt, 116 ), 117 ) 118 if err != nil { 119 return fmt.Errorf("trigger flux sync: %w", err) 120 } 121 122 if trimmed := strings.TrimSpace(string(output)); trimmed != "" { 123 log.Info(trimmed) 124 } 125 126 return nil 127} 128func fluxOutput(ctx context.Context, args ...string) ([]byte, error) { 129 fluxCmd := exec.CommandContext(ctx, "flux", args...) 130 return fluxCmd.CombinedOutput() 131}