this repo has no description
0
fork

Configure Feed

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

feat(controller): render and push all apps

Khue Doan 766e3baf 4e72cb46

+132 -65
+76
controller/activities/app.go
··· 1 + package activities 2 + 3 + import ( 4 + "bytes" 5 + "context" 6 + "fmt" 7 + "os" 8 + "os/exec" 9 + "path" 10 + "path/filepath" 11 + "strings" 12 + 13 + "go.temporal.io/sdk/activity" 14 + ) 15 + 16 + func PushRenderedApp(ctx context.Context, appsPath, namespace, app, cluster, registry string) (*PushResult, error) { 17 + logger := activity.GetLogger(ctx) 18 + 19 + tmpDir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s-", app, cluster)) 20 + if err != nil { 21 + logger.Error("failed to create temp dir", "error", err) 22 + return nil, err 23 + } 24 + defer os.RemoveAll(tmpDir) 25 + 26 + cmd := exec.CommandContext( 27 + ctx, 28 + "helm", "template", "--namespace", namespace, app, "oci://ghcr.io/bjw-s-labs/helm/app-template:4.1.1", "--values", path.Join(namespace, app, cluster+".yaml"), "--output-dir", tmpDir, 29 + ) 30 + cmd.Dir = appsPath 31 + 32 + var stdout, stderr bytes.Buffer 33 + cmd.Stdout = &stdout 34 + cmd.Stderr = &stderr 35 + 36 + logger.Info("running helm template", "cmd", cmd.String()) 37 + 38 + if err := cmd.Run(); err != nil { 39 + logger.Error("helm template failed", "error", err, "stderr", stderr.String()) 40 + return nil, err 41 + } 42 + 43 + outputPath, err := filepath.Abs(tmpDir) 44 + if err != nil { 45 + logger.Error("failed to get absolute path to rendered manifests", "error", err) 46 + return nil, err 47 + } 48 + 49 + imageRef := fmt.Sprintf("%s/%s/%s:%s", registry, namespace, app, cluster) 50 + result, err := PushManifests(ctx, outputPath, imageRef) 51 + if err != nil { 52 + logger.Error("failed to push manifests", "error", err) 53 + return nil, err 54 + } 55 + 56 + return result, nil 57 + } 58 + 59 + func DiscoverApps(ctx context.Context, appsDir string, cluster string) ([]string, error) { 60 + // TODO logs 61 + _ = activity.GetLogger(ctx) 62 + var matched []string 63 + err := filepath.Walk(appsDir, func(path string, info os.FileInfo, err error) error { 64 + if err != nil || info.IsDir() { 65 + return nil 66 + } 67 + if strings.HasSuffix(info.Name(), cluster+".yaml") { 68 + matched = append(matched, path) 69 + } 70 + return nil 71 + }) 72 + if err != nil { 73 + return nil, err 74 + } 75 + return matched, nil 76 + }
-47
controller/activities/oci.go
··· 4 4 "bytes" 5 5 "context" 6 6 "encoding/json" 7 - "fmt" 8 - "os" 9 7 "os/exec" 10 - "path" 11 - "path/filepath" 12 8 13 9 "go.temporal.io/sdk/activity" 14 10 ) ··· 45 41 46 42 return &result, nil 47 43 } 48 - 49 - func PushRenderedHelm(ctx context.Context, appsPath, namespace, app, cluster, registry string) (*PushResult, error) { 50 - logger := activity.GetLogger(ctx) 51 - 52 - tmpDir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s-", app, cluster)) 53 - if err != nil { 54 - logger.Error("failed to create temp dir", "error", err) 55 - return nil, err 56 - } 57 - defer os.RemoveAll(tmpDir) 58 - 59 - cmd := exec.CommandContext( 60 - ctx, 61 - "helm", "template", "--namespace", namespace, app, "oci://ghcr.io/bjw-s-labs/helm/app-template:4.1.1", "--values", path.Join(namespace, app, cluster+".yaml"), "--output-dir", tmpDir, 62 - ) 63 - cmd.Dir = appsPath 64 - 65 - var stdout, stderr bytes.Buffer 66 - cmd.Stdout = &stdout 67 - cmd.Stderr = &stderr 68 - 69 - logger.Info("running helm template", "cmd", cmd.String()) 70 - 71 - if err := cmd.Run(); err != nil { 72 - logger.Error("helm template failed", "error", err, "stderr", stderr.String()) 73 - return nil, err 74 - } 75 - 76 - outputPath, err := filepath.Abs(tmpDir) 77 - if err != nil { 78 - logger.Error("failed to get absolute path to rendered manifests", "error", err) 79 - return nil, err 80 - } 81 - 82 - imageRef := fmt.Sprintf("%s/%s/%s:%s", registry, namespace, app, cluster) 83 - result, err := PushManifests(ctx, outputPath, imageRef) 84 - if err != nil { 85 - logger.Error("failed to push manifests", "error", err) 86 - return nil, err 87 - } 88 - 89 - return result, nil 90 - }
+2 -1
controller/worker/main.go
··· 29 29 w.RegisterActivity(activities.PruneGraph) 30 30 w.RegisterActivity(activities.TerragruntApply) 31 31 w.RegisterActivity(activities.PushManifests) 32 - w.RegisterActivity(activities.PushRenderedHelm) 32 + w.RegisterActivity(activities.PushRenderedApp) 33 + w.RegisterActivity(activities.DiscoverApps) 33 34 34 35 w.RegisterWorkflow(workflows.Infra) 35 36 w.RegisterWorkflow(workflows.Platform)
+54 -17
controller/workflows/apps.go
··· 1 1 package workflows 2 2 3 3 import ( 4 + "path/filepath" 5 + "strings" 4 6 "time" 5 7 6 8 "cloudlab/controller/activities" ··· 20 22 logger := workflow.GetLogger(ctx) 21 23 logger.Info("Platform workflow started", "platform", input) 22 24 23 - var path string 25 + var repoPath string 24 26 if err := workflow.ExecuteActivity( 25 27 workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ 26 28 StartToCloseTimeout: 1 * time.Minute, 27 - RetryPolicy: &temporal.RetryPolicy{ 28 - MaximumAttempts: 3, 29 - }, 29 + RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 3}, 30 30 }), 31 31 activities.Clone, 32 32 input.Url, 33 33 input.Revision, 34 - ).Get(ctx, &path); err != nil { 34 + ).Get(ctx, &repoPath); err != nil { 35 35 return err 36 36 } 37 37 38 - var pushResult *activities.PushResult 38 + appsDir := repoPath + "/apps" 39 + 40 + // TODO this should be a separate activity 41 + var matchedPaths []string 39 42 if err := workflow.ExecuteActivity( 40 43 workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ 41 - StartToCloseTimeout: 5 * time.Minute, 42 - RetryPolicy: &temporal.RetryPolicy{ 43 - MaximumAttempts: 2, 44 - }, 44 + StartToCloseTimeout: 1 * time.Minute, 45 + RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 2}, 45 46 }), 46 - activities.PushRenderedHelm, 47 - // TODO loop through this 48 - path+"/apps", 49 - "khuedoan", 50 - "blog", 47 + activities.DiscoverApps, 48 + appsDir, 51 49 input.Cluster, 52 - input.Registry, 53 - ).Get(ctx, &pushResult); err != nil { 50 + ).Get(ctx, &matchedPaths); err != nil { 54 51 return err 55 52 } 53 + ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ 54 + StartToCloseTimeout: 5 * time.Minute, 55 + RetryPolicy: &temporal.RetryPolicy{MaximumAttempts: 2}, 56 + }) 56 57 58 + var futures []workflow.Future 59 + var results []activities.PushResult 60 + 61 + for _, yamlPath := range matchedPaths { 62 + parts := strings.Split(filepath.ToSlash(yamlPath), "/") 63 + if len(parts) < 4 { 64 + logger.Warn("Skipping invalid path", "path", yamlPath) 65 + continue 66 + } 67 + 68 + namespace := parts[len(parts)-3] 69 + app := parts[len(parts)-2] 70 + 71 + logger.Info("Dispatching PushRenderedHelm", "path", yamlPath, "namespace", namespace, "app", app) 72 + 73 + fut := workflow.ExecuteActivity( 74 + ctx, 75 + activities.PushRenderedApp, 76 + appsDir, 77 + namespace, 78 + app, 79 + input.Cluster, 80 + input.Registry, 81 + ) 82 + futures = append(futures, fut) 83 + } 84 + 85 + for _, fut := range futures { 86 + var result activities.PushResult 87 + if err := fut.Get(ctx, &result); err != nil { 88 + return err 89 + } 90 + results = append(results, result) 91 + } 92 + 93 + logger.Info("Finished pushing all matching apps", "count", len(results)) 57 94 return nil 58 95 }