github.com/argoproj/argo-cd@v1.8.7/cmd/argocd-application-controller/commands/argocd_application_controller.go (about) 1 package commands 2 3 import ( 4 "context" 5 "math" 6 "time" 7 8 "github.com/argoproj/pkg/stats" 9 "github.com/go-redis/redis/v8" 10 log "github.com/sirupsen/logrus" 11 "github.com/spf13/cobra" 12 "k8s.io/client-go/kubernetes" 13 "k8s.io/client-go/tools/clientcmd" 14 15 "github.com/argoproj/argo-cd/common" 16 "github.com/argoproj/argo-cd/controller" 17 "github.com/argoproj/argo-cd/controller/sharding" 18 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" 19 appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned" 20 "github.com/argoproj/argo-cd/reposerver/apiclient" 21 cacheutil "github.com/argoproj/argo-cd/util/cache" 22 appstatecache "github.com/argoproj/argo-cd/util/cache/appstate" 23 "github.com/argoproj/argo-cd/util/cli" 24 "github.com/argoproj/argo-cd/util/env" 25 "github.com/argoproj/argo-cd/util/errors" 26 kubeutil "github.com/argoproj/argo-cd/util/kube" 27 "github.com/argoproj/argo-cd/util/settings" 28 ) 29 30 const ( 31 // CLIName is the name of the CLI 32 cliName = "argocd-application-controller" 33 // Default time in seconds for application resync period 34 defaultAppResyncPeriod = 180 35 ) 36 37 func NewCommand() *cobra.Command { 38 var ( 39 clientConfig clientcmd.ClientConfig 40 appResyncPeriod int64 41 repoServerAddress string 42 repoServerTimeoutSeconds int 43 selfHealTimeoutSeconds int 44 statusProcessors int 45 operationProcessors int 46 logFormat string 47 logLevel string 48 glogLevel int 49 metricsPort int 50 kubectlParallelismLimit int64 51 cacheSrc func() (*appstatecache.Cache, error) 52 redisClient *redis.Client 53 ) 54 var command = cobra.Command{ 55 Use: cliName, 56 Short: "Run ArgoCD Application Controller", 57 Long: "ArgoCD application controller is a Kubernetes controller that continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). This command runs Application Controller in the foreground. It can be configured by following options.", 58 DisableAutoGenTag: true, 59 RunE: func(c *cobra.Command, args []string) error { 60 cli.SetLogFormat(logFormat) 61 cli.SetLogLevel(logLevel) 62 cli.SetGLogLevel(glogLevel) 63 64 config, err := clientConfig.ClientConfig() 65 errors.CheckError(err) 66 errors.CheckError(v1alpha1.SetK8SConfigDefaults(config)) 67 68 kubeClient := kubernetes.NewForConfigOrDie(config) 69 appClient := appclientset.NewForConfigOrDie(config) 70 71 namespace, _, err := clientConfig.Namespace() 72 errors.CheckError(err) 73 74 resyncDuration := time.Duration(appResyncPeriod) * time.Second 75 repoClientset := apiclient.NewRepoServerClientset(repoServerAddress, repoServerTimeoutSeconds) 76 ctx, cancel := context.WithCancel(context.Background()) 77 defer cancel() 78 79 cache, err := cacheSrc() 80 errors.CheckError(err) 81 cache.Cache.SetClient(cacheutil.NewTwoLevelClient(cache.Cache.GetClient(), 10*time.Minute)) 82 83 settingsMgr := settings.NewSettingsManager(ctx, kubeClient, namespace) 84 kubectl := kubeutil.NewKubectl() 85 clusterFilter := getClusterFilter() 86 appController, err := controller.NewApplicationController( 87 namespace, 88 settingsMgr, 89 kubeClient, 90 appClient, 91 repoClientset, 92 cache, 93 kubectl, 94 resyncDuration, 95 time.Duration(selfHealTimeoutSeconds)*time.Second, 96 metricsPort, 97 kubectlParallelismLimit, 98 clusterFilter) 99 errors.CheckError(err) 100 cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer()) 101 102 vers := common.GetVersion() 103 log.Infof("Application Controller (version: %s, built: %s) starting (namespace: %s)", vers.Version, vers.BuildDate, namespace) 104 stats.RegisterStackDumper() 105 stats.StartStatsTicker(10 * time.Minute) 106 stats.RegisterHeapDumper("memprofile") 107 108 go appController.Run(ctx, statusProcessors, operationProcessors) 109 110 // Wait forever 111 select {} 112 }, 113 } 114 115 clientConfig = cli.AddKubectlFlagsToCmd(&command) 116 command.Flags().Int64Var(&appResyncPeriod, "app-resync", defaultAppResyncPeriod, "Time period in seconds for application resync.") 117 command.Flags().StringVar(&repoServerAddress, "repo-server", common.DefaultRepoServerAddr, "Repo server address.") 118 command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", 60, "Repo server RPC call timeout seconds.") 119 command.Flags().IntVar(&statusProcessors, "status-processors", 1, "Number of application status processors") 120 command.Flags().IntVar(&operationProcessors, "operation-processors", 1, "Number of application operation processors") 121 command.Flags().StringVar(&logFormat, "logformat", "text", "Set the logging format. One of: text|json") 122 command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error") 123 command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level") 124 command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDMetrics, "Start metrics server on given port") 125 command.Flags().IntVar(&selfHealTimeoutSeconds, "self-heal-timeout-seconds", 5, "Specifies timeout between application self heal attempts") 126 command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", 20, "Number of allowed concurrent kubectl fork/execs. Any value less the 1 means no limit.") 127 cacheSrc = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) { 128 redisClient = client 129 }) 130 return &command 131 } 132 133 func getClusterFilter() func(cluster *v1alpha1.Cluster) bool { 134 replicas := env.ParseNumFromEnv(common.EnvControllerReplicas, 0, 0, math.MaxInt32) 135 shard := env.ParseNumFromEnv(common.EnvControllerShard, -1, -math.MaxInt32, math.MaxInt32) 136 var clusterFilter func(cluster *v1alpha1.Cluster) bool 137 if replicas > 1 { 138 if shard < 0 { 139 var err error 140 shard, err = sharding.InferShard() 141 errors.CheckError(err) 142 } 143 log.Infof("Processing clusters from shard %d", shard) 144 clusterFilter = sharding.GetClusterFilter(replicas, shard) 145 } else { 146 log.Info("Processing all cluster shards") 147 } 148 return clusterFilter 149 }