Skip to content

Commit

Permalink
support virtual apps
Browse files Browse the repository at this point in the history
  • Loading branch information
djeebus committed Dec 18, 2023
1 parent b82fbf1 commit eeb7551
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 35 deletions.
22 changes: 12 additions & 10 deletions pkg/argo_client/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/zapier/kubechecks/telemetry"
)

func GetManifestsLocal(ctx context.Context, name string, tempRepoDir string, changedAppFilePath string) ([]string, error) {
func GetManifestsLocal(ctx context.Context, name string, tempRepoDir string, changedAppFilePath string, app *argoappv1.Application) ([]string, error) {
ctx, span := otel.Tracer("Kubechecks").Start(ctx, "GetManifestsLocal")
defer span.End()

Expand All @@ -45,16 +45,18 @@ func GetManifestsLocal(ctx context.Context, name string, tempRepoDir string, cha

log.Debug().Str("name", name).Msg("generating diff for application...")

appName := name
app, err := appClient.Get(ctx, &application.ApplicationQuery{
Name: &appName,
})
if err != nil {
telemetry.SetError(span, err, "Argo Get App")
getManifestsFailed.WithLabelValues(name).Inc()
return nil, errors.Wrap(err, "failed to get application")
if app == nil {
appName := name
app, err := appClient.Get(ctx, &application.ApplicationQuery{
Name: &appName,
})
if err != nil {
telemetry.SetError(span, err, "Argo Get App")
getManifestsFailed.WithLabelValues(name).Inc()
return nil, errors.Wrap(err, "failed to get application")
}
log.Trace().Msgf("Argo App: %+v", app)
}
log.Trace().Msgf("Argo App: %+v", app)

cluster, err := clusterIf.Get(ctx, &cluster.ClusterQuery{Name: app.Spec.Destination.Name, Server: app.Spec.Destination.Server})
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions pkg/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ changedFilePath should be the root of the changed folder
from https://github.com/argoproj/argo-cd/blob/d3ff9757c460ae1a6a11e1231251b5d27aadcdd1/cmd/argocd/commands/app.go#L879
*/
func GetDiff(ctx context.Context, name string, manifests []string, addApp func(name, path string)) (pkg.CheckResult, string, error) {
func GetDiff(ctx context.Context, name string, manifests []string, app *argoappv1.Application, addApp func(*argoappv1.Application)) (pkg.CheckResult, string, error) {
ctx, span := otel.Tracer("Kubechecks").Start(ctx, "Diff")
defer span.End()

Expand All @@ -62,7 +62,7 @@ func GetDiff(ctx context.Context, name string, manifests []string, addApp func(n
var err error

appName := name
app, err := appClient.Get(ctx, &application.ApplicationQuery{
app, err = appClient.Get(ctx, &application.ApplicationQuery{
Name: &appName,
})
if err != nil {
Expand Down Expand Up @@ -152,7 +152,7 @@ func GetDiff(ctx context.Context, name string, manifests []string, addApp func(n
case item.live == nil:
added++
if app, ok := isApp(item, diffRes.PredictedLive); ok {
addApp(app.Name, app.Spec.GetSource().Path)
addApp(app)
}
case diffRes.Modified:
modified++
Expand Down
50 changes: 28 additions & 22 deletions pkg/events/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync/atomic"
"time"

argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -44,6 +45,7 @@ type CheckEvent struct {

cfg *config.ServerConfig

createdApps map[string]*argoappv1.Application
addedAppsSet map[string]struct{}
appChannel chan appStruct
doneChannel chan bool
Expand All @@ -53,9 +55,10 @@ var inFlight int32

func NewCheckEvent(repo *repo.Repo, client pkg.Client, cfg *config.ServerConfig) *CheckEvent {
ce := &CheckEvent{
cfg: cfg,
client: client,
repo: repo,
cfg: cfg,
client: client,
createdApps: make(map[string]*argoappv1.Application),
repo: repo,
}

ce.logger = log.Logger.With().Str("repo", repo.Name).Int("event_id", repo.CheckID).Logger()
Expand Down Expand Up @@ -267,9 +270,9 @@ func (ce *CheckEvent) ProcessApps(ctx context.Context) {
ce.CommitStatus(ctx, pkg.StateSuccess)
}

func (ce *CheckEvent) queueApp(name, path string) {
func (ce *CheckEvent) queueApp(appName, path string) {
a := appStruct{
name: name,
name: appName,
dir: path,
}

Expand Down Expand Up @@ -309,9 +312,9 @@ func (ce *CheckEvent) appWorkers(ctx context.Context, workerID int) {
// It takes a context (ctx), application name (app), directory (dir) as input and returns an error if any check fails.
// The processing is performed concurrently using Go routines and error groups. Any check results are sent through
// the returnChan. The function also manages the inFlight atomic counter to track active processing routines.
func (ce *CheckEvent) processApp(ctx context.Context, app, dir string) bool {
func (ce *CheckEvent) processApp(ctx context.Context, appName, dir string) bool {
ctx, span := otel.Tracer("Kubechecks").Start(ctx, "processApp", trace.WithAttributes(
attribute.String("app", app),
attribute.String("app", appName),
attribute.String("dir", dir),
))
defer span.End()
Expand All @@ -320,24 +323,24 @@ func (ce *CheckEvent) processApp(ctx context.Context, app, dir string) bool {
defer atomic.AddInt32(&inFlight, -1)

start := time.Now()
ce.logger.Info().Str("app", app).Msg("Adding new app")
ce.logger.Info().Str("app", appName).Msg("Adding new app")
// Build a new section for this app in the parent comment
ce.vcsNote.AddNewApp(ctx, app)
ce.vcsNote.AddNewApp(ctx, appName)

ce.logger.Debug().Msgf("Getting manifests for app: %s with code at %s/%s", app, ce.TempWorkingDir, dir)
manifests, err := argo_client.GetManifestsLocal(ctx, app, ce.TempWorkingDir, dir)
ce.logger.Debug().Msgf("Getting manifests for app: %s with code at %s/%s", appName, ce.TempWorkingDir, dir)
manifests, err := argo_client.GetManifestsLocal(ctx, appName, ce.TempWorkingDir, dir, ce.createdApps[appName])
if err != nil {
ce.logger.Error().Err(err).Msgf("Unable to get manifests for %s in %s", app, dir)
ce.logger.Error().Err(err).Msgf("Unable to get manifests for %s in %s", appName, dir)
cr := pkg.CheckResult{State: pkg.StateError, Summary: "Unable to get manifests", Details: fmt.Sprintf("```\n%s\n```", ce.cleanupGetManifestsError(err))}
ce.vcsNote.AddToAppMessage(ctx, app, cr)
ce.vcsNote.AddToAppMessage(ctx, appName, cr)
return false
}

// Argo diff logic wants unformatted manifests but everything else wants them as YAML, so we prepare both
formattedManifests := argo_client.FormatManifestsYAML(manifests)
ce.logger.Trace().Msgf("Manifests:\n%+v\n", formattedManifests)

k8sVersion, err := argo_client.GetArgoClient().GetKubernetesVersionByApplicationName(ctx, app)
k8sVersion, err := argo_client.GetArgoClient().GetKubernetesVersionByApplicationName(ctx, appName)
if err != nil {
ce.logger.Error().Err(err).Msg("Error retrieving the Kubernetes version")
k8sVersion = viper.GetString("fallback-k8s-version")
Expand All @@ -348,16 +351,19 @@ func (ce *CheckEvent) processApp(ctx context.Context, app, dir string) bool {

var wg sync.WaitGroup

run := ce.createRunner(span, ctx, app, &wg)
run := ce.createRunner(span, ctx, appName, &wg)

run("validating app against schema", ce.validateSchemas(ctx, app, k8sVersion, ce.TempWorkingDir, formattedManifests))
run("generating diff for app", ce.generateDiff(ctx, app, manifests, ce.queueApp))
run("validating app against schema", ce.validateSchemas(ctx, appName, k8sVersion, ce.TempWorkingDir, formattedManifests))
run("generating diff for app", ce.generateDiff(ctx, appName, manifests, func(app *argoappv1.Application) {
ce.createdApps[app.Name] = app
ce.queueApp(app.Name, app.Spec.GetSource().Path)
}))

if viper.GetBool("enable-conftest") {
run("validation policy", ce.validatePolicy(ctx, app))
run("validation policy", ce.validatePolicy(ctx, appName))
}

run("running pre-upgrade check", ce.runPreupgradeCheck(ctx, app, k8sVersion, formattedManifests))
run("running pre-upgrade check", ce.runPreupgradeCheck(ctx, appName, k8sVersion, formattedManifests))

wg.Wait()

Expand Down Expand Up @@ -441,14 +447,14 @@ func (ce *CheckEvent) validatePolicy(ctx context.Context, app string) func() (pk
}
}

func (ce *CheckEvent) generateDiff(ctx context.Context, app string, manifests []string, addApp func(name, path string)) func() (pkg.CheckResult, error) {
func (ce *CheckEvent) generateDiff(ctx context.Context, appName string, manifests []string, addApp func(app *argoappv1.Application)) func() (pkg.CheckResult, error) {
return func() (pkg.CheckResult, error) {
cr, rawDiff, err := diff.GetDiff(ctx, app, manifests, addApp)
cr, rawDiff, err := diff.GetDiff(ctx, appName, manifests, ce.createdApps[appName], addApp)
if err != nil {
return pkg.CheckResult{}, err
}

diff.AIDiffSummary(ctx, ce.vcsNote, app, manifests, rawDiff)
diff.AIDiffSummary(ctx, ce.vcsNote, appName, manifests, rawDiff)

return cr, nil
}
Expand Down

0 comments on commit eeb7551

Please sign in to comment.