Skip to content

Commit

Permalink
feat(cli): add cmd to preview generated apps of appsets (argoproj#10895
Browse files Browse the repository at this point in the history
…) (argoproj#16781)

* feat(cli): add cmd to preview generated apps

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* fix build

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* fix local proto gen

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* dry run client

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* fix: allow to run codegen outside GOPATH

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* clientgen

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* openapigen

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* remove ensure-gopath

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* fix tests and templatePatch

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* fix build

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* convert to interfaces

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>

* codegen

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* extract common code

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* use appset params in server

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* codegen

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* fix test build

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* unit tests

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* move test to new package

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* move to correct folders

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* fix build

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* review

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>

* lint

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* fix test

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* fix lint

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* auto generate mocks

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* better error handling

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* more docs

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* more docs

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

* lint

Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>

---------

Signed-off-by: Alexandre Gaudreault <alexandre.gaudreault@logmein.com>
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
  • Loading branch information
2 people authored and ggjulio committed Jul 21, 2024
1 parent 69eefa5 commit b51201a
Show file tree
Hide file tree
Showing 37 changed files with 1,755 additions and 1,128 deletions.
146 changes: 5 additions & 141 deletions applicationset/controllers/applicationset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"

"github.com/argoproj/argo-cd/v2/applicationset/controllers/template"
"github.com/argoproj/argo-cd/v2/applicationset/generators"
"github.com/argoproj/argo-cd/v2/applicationset/status"
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/util/db"
Expand Down Expand Up @@ -129,7 +131,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
// Log a warning if there are unrecognized generators
_ = utils.CheckInvalidGenerators(&applicationSetInfo)
// desiredApplications is the main list of all expected Applications from all generators in this appset.
desiredApplications, applicationSetReason, generatorsErr := r.generateApplications(logCtx, applicationSetInfo)
desiredApplications, applicationSetReason, generatorsErr := template.GenerateApplications(logCtx, applicationSetInfo, r.Generators, r.Renderer, r.Client)
if generatorsErr != nil {
_ = r.setApplicationSetStatusCondition(ctx,
&applicationSetInfo,
Expand Down Expand Up @@ -495,88 +497,6 @@ func (r *ApplicationSetReconciler) getMinRequeueAfter(applicationSetInfo *argov1
return res
}

func getTempApplication(applicationSetTemplate argov1alpha1.ApplicationSetTemplate) *argov1alpha1.Application {
var tmplApplication argov1alpha1.Application
tmplApplication.Annotations = applicationSetTemplate.Annotations
tmplApplication.Labels = applicationSetTemplate.Labels
tmplApplication.Namespace = applicationSetTemplate.Namespace
tmplApplication.Name = applicationSetTemplate.Name
tmplApplication.Spec = applicationSetTemplate.Spec
tmplApplication.Finalizers = applicationSetTemplate.Finalizers

return &tmplApplication
}

func (r *ApplicationSetReconciler) generateApplications(logCtx *log.Entry, applicationSetInfo argov1alpha1.ApplicationSet) ([]argov1alpha1.Application, argov1alpha1.ApplicationSetReasonType, error) {
var res []argov1alpha1.Application

var firstError error
var applicationSetReason argov1alpha1.ApplicationSetReasonType

for _, requestedGenerator := range applicationSetInfo.Spec.Generators {
t, err := generators.Transform(requestedGenerator, r.Generators, applicationSetInfo.Spec.Template, &applicationSetInfo, map[string]interface{}{}, r.Client)
if err != nil {
logCtx.WithError(err).WithField("generator", requestedGenerator).
Error("error generating application from params")
if firstError == nil {
firstError = err
applicationSetReason = argov1alpha1.ApplicationSetReasonApplicationParamsGenerationError
}
continue
}

for _, a := range t {
tmplApplication := getTempApplication(a.Template)

for _, p := range a.Params {
app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, p, applicationSetInfo.Spec.GoTemplate, applicationSetInfo.Spec.GoTemplateOptions)
if err != nil {
logCtx.WithError(err).WithField("params", a.Params).WithField("generator", requestedGenerator).
Error("error generating application from params")

if firstError == nil {
firstError = err
applicationSetReason = argov1alpha1.ApplicationSetReasonRenderTemplateParamsError
}
continue
}

if applicationSetInfo.Spec.TemplatePatch != nil {
patchedApplication, err := r.applyTemplatePatch(app, applicationSetInfo, p)
if err != nil {
log.WithError(err).WithField("params", a.Params).WithField("generator", requestedGenerator).
Error("error generating application from params")

if firstError == nil {
firstError = err
applicationSetReason = argov1alpha1.ApplicationSetReasonRenderTemplateParamsError
}
continue
}

app = patchedApplication
}

res = append(res, *app)
}
}

logCtx.WithField("generator", requestedGenerator).Infof("generated %d applications", len(res))
logCtx.WithField("generator", requestedGenerator).Debugf("apps from generator: %+v", res)
}

return res, applicationSetReason, firstError
}

func (r *ApplicationSetReconciler) applyTemplatePatch(app *argov1alpha1.Application, applicationSetInfo argov1alpha1.ApplicationSet, params map[string]interface{}) (*argov1alpha1.Application, error) {
replacedTemplate, err := r.Renderer.Replace(*applicationSetInfo.Spec.TemplatePatch, params, applicationSetInfo.Spec.GoTemplate, applicationSetInfo.Spec.GoTemplateOptions)
if err != nil {
return nil, fmt.Errorf("error replacing values in templatePatch: %w", err)
}

return applyTemplatePatch(app, replacedTemplate)
}

func ignoreNotAllowedNamespaces(namespaces []string) predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
Expand Down Expand Up @@ -650,10 +570,6 @@ func (r *ApplicationSetReconciler) createOrUpdateInCluster(ctx context.Context,
var firstError error
// Creates or updates the application in appList
for _, generatedApp := range desiredApplications {
// The app's namespace must be the same as the AppSet's namespace to preserve the appsets-in-any-namespace
// security boundary.
generatedApp.Namespace = applicationSet.Namespace

appLog := logCtx.WithFields(log.Fields{"app": generatedApp.QualifiedName()})

// Normalize to avoid fighting with the application controller.
Expand Down Expand Up @@ -1351,8 +1267,8 @@ func findApplicationStatusIndex(appStatuses []argov1alpha1.ApplicationSetApplica
}

func (r *ApplicationSetReconciler) updateResourcesStatus(ctx context.Context, logCtx *log.Entry, appset *argov1alpha1.ApplicationSet, apps []argov1alpha1.Application) error {
statusMap := getResourceStatusMap(appset)
statusMap = buildResourceStatus(statusMap, apps)
statusMap := status.GetResourceStatusMap(appset)
statusMap = status.BuildResourceStatus(statusMap, apps)

statuses := []argov1alpha1.ResourceStatus{}
for _, status := range statusMap {
Expand All @@ -1377,58 +1293,6 @@ func (r *ApplicationSetReconciler) updateResourcesStatus(ctx context.Context, lo
return nil
}

func buildResourceStatus(statusMap map[string]argov1alpha1.ResourceStatus, apps []argov1alpha1.Application) map[string]argov1alpha1.ResourceStatus {
appMap := map[string]argov1alpha1.Application{}
for _, app := range apps {
appCopy := app
appMap[app.Name] = app

gvk := app.GroupVersionKind()
// Create status if it does not exist
status, ok := statusMap[app.Name]
if !ok {
status = argov1alpha1.ResourceStatus{
Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind,
Name: app.Name,
Namespace: app.Namespace,
Status: app.Status.Sync.Status,
Health: &appCopy.Status.Health,
}
}

status.Group = gvk.Group
status.Version = gvk.Version
status.Kind = gvk.Kind
status.Name = app.Name
status.Namespace = app.Namespace
status.Status = app.Status.Sync.Status
status.Health = &appCopy.Status.Health

statusMap[app.Name] = status
}
cleanupDeletedApplicationStatuses(statusMap, appMap)

return statusMap
}

func getResourceStatusMap(appset *argov1alpha1.ApplicationSet) map[string]argov1alpha1.ResourceStatus {
statusMap := map[string]argov1alpha1.ResourceStatus{}
for _, status := range appset.Status.Resources {
statusMap[status.Name] = status
}
return statusMap
}

func cleanupDeletedApplicationStatuses(statusMap map[string]argov1alpha1.ResourceStatus, apps map[string]argov1alpha1.Application) {
for name := range statusMap {
if _, ok := apps[name]; !ok {
delete(statusMap, name)
}
}
}

// setApplicationSetApplicationStatus updates the ApplicationSet's status field
// with any new/changed Application statuses.
func (r *ApplicationSetReconciler) setAppSetApplicationStatus(ctx context.Context, logCtx *log.Entry, applicationSet *argov1alpha1.ApplicationSet, applicationStatuses []argov1alpha1.ApplicationSetApplicationStatus) error {
Expand Down
Loading

0 comments on commit b51201a

Please sign in to comment.