github.com/argoproj/argo-cd/v3@v3.2.1/controller/hydrator_dependencies.go (about)

     1  package controller
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/argoproj/argo-cd/v3/controller/hydrator/types"
     8  	appv1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
     9  	"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
    10  	argoutil "github.com/argoproj/argo-cd/v3/util/argo"
    11  
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    14  )
    15  
    16  /**
    17  This file implements the hydrator.Dependencies interface for the ApplicationController.
    18  
    19  Hydration logic does not belong in this file. The methods here should be "bookkeeping" methods that keep hydration work
    20  in the hydrator and app controller work in the app controller. The only purpose of this file is to provide the hydrator
    21  safe, minimal access to certain app controller functionality to avoid duplicate code.
    22  */
    23  
    24  func (ctrl *ApplicationController) GetProcessableAppProj(app *appv1.Application) (*appv1.AppProject, error) {
    25  	return ctrl.getAppProj(app)
    26  }
    27  
    28  // GetProcessableApps returns a list of applications that are processable by the controller.
    29  func (ctrl *ApplicationController) GetProcessableApps() (*appv1.ApplicationList, error) {
    30  	// getAppList already filters out applications that are not processable by the controller.
    31  	return ctrl.getAppList(metav1.ListOptions{})
    32  }
    33  
    34  func (ctrl *ApplicationController) GetRepoObjs(ctx context.Context, origApp *appv1.Application, drySource appv1.ApplicationSource, revision string, project *appv1.AppProject) ([]*unstructured.Unstructured, *apiclient.ManifestResponse, error) {
    35  	drySources := []appv1.ApplicationSource{drySource}
    36  	dryRevisions := []string{revision}
    37  
    38  	appLabelKey, err := ctrl.settingsMgr.GetAppInstanceLabelKey()
    39  	if err != nil {
    40  		return nil, nil, fmt.Errorf("failed to get app instance label key: %w", err)
    41  	}
    42  
    43  	app := origApp.DeepCopy()
    44  	// Remove the manifest generate path annotation, because the feature will misbehave for apps using source hydrator.
    45  	// Setting this annotation causes GetRepoObjs to compare the dry source commit to the most recent synced commit. The
    46  	// problem is that the most recent synced commit is likely on the hydrated branch, not the dry branch. The
    47  	// comparison will throw an error and break hydration.
    48  	//
    49  	// The long-term solution will probably be to persist the synced _dry_ revision and use that for the comparison.
    50  	delete(app.Annotations, appv1.AnnotationKeyManifestGeneratePaths)
    51  
    52  	// FIXME: use cache and revision cache
    53  	objs, resp, _, err := ctrl.appStateManager.GetRepoObjs(ctx, app, drySources, appLabelKey, dryRevisions, true, true, false, project, false)
    54  	if err != nil {
    55  		return nil, nil, fmt.Errorf("failed to get repo objects: %w", err)
    56  	}
    57  	trackingMethod, err := ctrl.settingsMgr.GetTrackingMethod()
    58  	if err != nil {
    59  		return nil, nil, fmt.Errorf("failed to get tracking method: %w", err)
    60  	}
    61  	for _, obj := range objs {
    62  		if err := argoutil.NewResourceTracking().RemoveAppInstance(obj, trackingMethod); err != nil {
    63  			return nil, nil, fmt.Errorf("failed to remove the app instance value: %w", err)
    64  		}
    65  	}
    66  
    67  	if len(resp) != 1 {
    68  		return nil, nil, fmt.Errorf("expected one manifest response, got %d", len(resp))
    69  	}
    70  
    71  	return objs, resp[0], nil
    72  }
    73  
    74  func (ctrl *ApplicationController) GetWriteCredentials(ctx context.Context, repoURL string, project string) (*appv1.Repository, error) {
    75  	return ctrl.db.GetWriteRepository(ctx, repoURL, project)
    76  }
    77  
    78  func (ctrl *ApplicationController) RequestAppRefresh(appName string, appNamespace string) error {
    79  	// We request a refresh by setting the annotation instead of by adding it to the refresh queue, because there is no
    80  	// guarantee that the hydrator is running on the same controller shard as is processing the application.
    81  
    82  	// This function is called for each app after a hydrate operation is completed so that the app controller can pick
    83  	// up the newly-hydrated changes. So we set hydrate=false to avoid a hydrate loop.
    84  	_, err := argoutil.RefreshApp(ctrl.applicationClientset.ArgoprojV1alpha1().Applications(appNamespace), appName, appv1.RefreshTypeNormal, false)
    85  	if err != nil {
    86  		return fmt.Errorf("failed to request app refresh: %w", err)
    87  	}
    88  	return nil
    89  }
    90  
    91  func (ctrl *ApplicationController) PersistAppHydratorStatus(orig *appv1.Application, newStatus *appv1.SourceHydratorStatus) {
    92  	status := orig.Status.DeepCopy()
    93  	status.SourceHydrator = *newStatus
    94  	ctrl.persistAppStatus(orig, status)
    95  }
    96  
    97  func (ctrl *ApplicationController) AddHydrationQueueItem(key types.HydrationQueueKey) {
    98  	ctrl.hydrationQueue.AddRateLimited(key)
    99  }
   100  
   101  func (ctrl *ApplicationController) GetHydratorCommitMessageTemplate() (string, error) {
   102  	sourceHydratorCommitMessageKey, err := ctrl.settingsMgr.GetSourceHydratorCommitMessageTemplate()
   103  	if err != nil {
   104  		return "", fmt.Errorf("failed to get sourceHydrator commit message template key: %w", err)
   105  	}
   106  
   107  	return sourceHydratorCommitMessageKey, nil
   108  }