diff --git a/Makefile b/Makefile index 3dc9bc5b5539..b9696acb0b18 100644 --- a/Makefile +++ b/Makefile @@ -230,19 +230,19 @@ dist/MANIFESTS_VERSION: echo $(MANIFESTS_VERSION) > dist/MANIFESTS_VERSION manifests/install.yaml: dist/MANIFESTS_VERSION $(MANIFESTS) - kustomize build manifests/cluster-install | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/install.yaml + kustomize build --load_restrictor=LoadRestrictionsNone manifests/cluster-install | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/install.yaml manifests/namespace-install.yaml: dist/MANIFESTS_VERSION $(MANIFESTS) - kustomize build manifests/namespace-install | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/namespace-install.yaml + kustomize build --load_restrictor=LoadRestrictionsNone manifests/namespace-install | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/namespace-install.yaml manifests/quick-start-no-db.yaml: dist/MANIFESTS_VERSION $(MANIFESTS) - kustomize build manifests/quick-start/no-db | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-no-db.yaml + kustomize build --load_restrictor=LoadRestrictionsNone manifests/quick-start/no-db | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-no-db.yaml manifests/quick-start-mysql.yaml: dist/MANIFESTS_VERSION $(MANIFESTS) - kustomize build manifests/quick-start/mysql | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-mysql.yaml + kustomize build --load_restrictor=LoadRestrictionsNone manifests/quick-start/mysql | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-mysql.yaml manifests/quick-start-postgres.yaml: dist/MANIFESTS_VERSION $(MANIFESTS) - kustomize build manifests/quick-start/postgres | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-postgres.yaml + kustomize build --load_restrictor=LoadRestrictionsNone manifests/quick-start/postgres | sed "s/:latest/:$(MANIFESTS_VERSION)/" | ./hack/auto-gen-msg.sh > manifests/quick-start-postgres.yaml # lint/test/etc @@ -271,7 +271,7 @@ endif test/e2e/manifests/postgres.yaml: $(MANIFESTS) $(E2E_MANIFESTS) # Create Postgres e2e manifests - kustomize build test/e2e/manifests/postgres | ./hack/auto-gen-msg.sh > test/e2e/manifests/postgres.yaml + kustomize build --load_restrictor=LoadRestrictionsNone test/e2e/manifests/postgres | ./hack/auto-gen-msg.sh > test/e2e/manifests/postgres.yaml dist/postgres.yaml: test/e2e/manifests/postgres.yaml # Create Postgres e2e manifests @@ -285,26 +285,18 @@ test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml: test/e2e/ test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml: cat test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml | ./hack/auto-gen-msg.sh > test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml -test/e2e/manifests/no-db.yaml: $(MANIFESTS) $(E2E_MANIFESTS) test/e2e/manifests/no-db/overlays/argo-server-deployment.yaml test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml +test/e2e/manifests/no-db.yaml: $(MANIFESTS) $(E2E_MANIFESTS) # Create no DB e2e manifests - kustomize build test/e2e/manifests/no-db | ./hack/auto-gen-msg.sh > test/e2e/manifests/no-db.yaml + kustomize build --load_restrictor=LoadRestrictionsNone test/e2e/manifests/no-db | ./hack/auto-gen-msg.sh > test/e2e/manifests/no-db.yaml dist/no-db.yaml: test/e2e/manifests/no-db.yaml # Create no DB e2e manifests # We additionlly disable ALWAY_OFFLOAD_NODE_STATUS cat test/e2e/manifests/no-db.yaml | sed 's/:latest/:$(VERSION)/' | sed 's/pns/$(E2E_EXECUTOR)/' | sed 's/"true"/"false"/' > dist/no-db.yaml -test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml: test/e2e/manifests/postgres/overlays/argo-server-deployment.yaml -test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml: - cat test/e2e/manifests/postgres/overlays/argo-server-deployment.yaml | ./hack/auto-gen-msg.sh > test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml - -test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml: test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml -test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml: - cat test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml | ./hack/auto-gen-msg.sh > test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml - -test/e2e/manifests/mysql.yaml: $(MANIFESTS) $(E2E_MANIFESTS) test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml +test/e2e/manifests/mysql.yaml: $(MANIFESTS) $(E2E_MANIFESTS) # Create MySQL e2e manifests - kustomize build test/e2e/manifests/mysql | ./hack/auto-gen-msg.sh > test/e2e/manifests/mysql.yaml + kustomize build --load_restrictor=LoadRestrictionsNone test/e2e/manifests/mysql | ./hack/auto-gen-msg.sh > test/e2e/manifests/mysql.yaml dist/mysql.yaml: test/e2e/manifests/mysql.yaml # Create MySQL e2e manifests diff --git a/cmd/workflow-controller/main.go b/cmd/workflow-controller/main.go index fcbada76662b..cca629066f44 100644 --- a/cmd/workflow-controller/main.go +++ b/cmd/workflow-controller/main.go @@ -78,20 +78,6 @@ func NewRootCommand() *cobra.Command { // start a controller on instances of our custom resource wfController := controller.NewWorkflowController(config, kubeclientset, wfclientset, namespace, managedNamespace, executorImage, executorImagePullPolicy, containerRuntimeExecutor, configMap) - err = wfController.ResyncConfig() - if err != nil { - return err - } - // TODO: following code will be updated in next major release to remove configmap - // setting for namespace installation mode. - if len(wfController.Config.Namespace) > 0 { - _, _ = fmt.Fprintf(os.Stderr, "\n------------------------ WARNING ------------------------\n") - _, _ = fmt.Fprintf(os.Stderr, "Namespaced installation with configmap setting is deprecated, \n") - _, _ = fmt.Fprintf(os.Stderr, "it will be removed in next major release. Instead please add \n") - _, _ = fmt.Fprintf(os.Stderr, "\"--namespaced\" to workflow-controller start args.\n") - _, _ = fmt.Fprintf(os.Stderr, "-----------------------------------------------------------------\n\n") - } - ctx, cancel := context.WithCancel(context.Background()) defer cancel() go wfController.Run(ctx, workflowWorkers, podWorkers) diff --git a/workflow/config/config.go b/config/config.go similarity index 98% rename from workflow/config/config.go rename to config/config.go index 3e8a742e808f..d2a76d3d3e7c 100644 --- a/workflow/config/config.go +++ b/config/config.go @@ -6,8 +6,8 @@ import ( wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" ) -// WorkflowControllerConfig contain the configuration settings for the workflow controller -type WorkflowControllerConfig struct { +// Config contain the configuration settings for the workflow controller +type Config struct { // ExecutorImage is the image name of the executor to use when running pods // DEPRECATED: use --executor-image flag to workflow-controller instead ExecutorImage string `json:"executorImage,omitempty"` diff --git a/workflow/config/config_test.go b/config/config_test.go similarity index 100% rename from workflow/config/config_test.go rename to config/config_test.go diff --git a/config/controller.go b/config/controller.go new file mode 100644 index 000000000000..2ad472640ead --- /dev/null +++ b/config/controller.go @@ -0,0 +1,122 @@ +package config + +import ( + "fmt" + "strings" + + apiv1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/cache" + + log "github.com/sirupsen/logrus" + "sigs.k8s.io/yaml" +) + +type Controller interface { + Run(stopCh <-chan struct{}, onChange func(config Config) error) + Get() (Config, error) +} + +type controller struct { + namespace string + // name of the config map + configMap string + kubeclientset kubernetes.Interface +} + +func NewController(namespace, name string, kubeclientset kubernetes.Interface) Controller { + log.WithField("name", name).Info("config map") + return &controller{ + namespace: namespace, + configMap: name, + kubeclientset: kubeclientset, + } +} + +func (cc *controller) updateConfig(cm *apiv1.ConfigMap, onChange func(config Config) error) error { + c, err := parseConfigMap(cm) + if err != nil { + return err + } + return onChange(c) +} + +func parseConfigMap(cm *apiv1.ConfigMap) (Config, error) { + // The key in the configmap to retrieve workflow configuration from. + // Content encoding is expected to be YAML. + var c Config + config, ok := cm.Data["config"] + if ok && len(cm.Data) != 1 { + return c, fmt.Errorf("if you have an item in your config map named 'config', you must only have one item") + } + if !ok { + for name, value := range cm.Data { + if strings.Contains(value, "\n") { + // this mucky code indents with two spaces + config = config + name + ":\n " + strings.Join(strings.Split(strings.Trim(value, "\n"), "\n"), "\n ") + "\n" + } else { + config = config + name + ": " + value + "\n" + } + } + } + return c, yaml.Unmarshal([]byte(config), &c) +} + +func (cc *controller) Run(stopCh <-chan struct{}, onChange func(config Config) error) { + restClient := cc.kubeclientset.CoreV1().RESTClient() + resource := "configmaps" + fieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", cc.configMap)) + listFunc := func(options metav1.ListOptions) (runtime.Object, error) { + options.FieldSelector = fieldSelector.String() + req := restClient.Get(). + Namespace(cc.namespace). + Resource(resource). + VersionedParams(&options, metav1.ParameterCodec) + return req.Do().Get() + } + watchFunc := func(options metav1.ListOptions) (watch.Interface, error) { + options.Watch = true + options.FieldSelector = fieldSelector.String() + req := restClient.Get(). + Namespace(cc.namespace). + Resource(resource). + VersionedParams(&options, metav1.ParameterCodec) + return req.Watch() + } + source := &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc} + _, controller := cache.NewInformer( + source, + &apiv1.ConfigMap{}, + 0, + cache.ResourceEventHandlerFuncs{ + UpdateFunc: func(old, new interface{}) { + oldCM := old.(*apiv1.ConfigMap) + newCM := new.(*apiv1.ConfigMap) + if oldCM.ResourceVersion == newCM.ResourceVersion { + return + } + if newCm, ok := new.(*apiv1.ConfigMap); ok { + log.Infof("Detected ConfigMap update.") + err := cc.updateConfig(newCm, onChange) + if err != nil { + log.Errorf("Update of config failed due to: %v", err) + } + } + }, + }) + controller.Run(stopCh) + log.Info("Watching config map updates") +} + +func (cc *controller) Get() (Config, error) { + cmClient := cc.kubeclientset.CoreV1().ConfigMaps(cc.namespace) + cm, err := cmClient.Get(cc.configMap, metav1.GetOptions{}) + if err != nil { + return Config{}, err + } + return parseConfigMap(cm) +} diff --git a/config/controller_test.go b/config/controller_test.go new file mode 100644 index 000000000000..2b379242d7e3 --- /dev/null +++ b/config/controller_test.go @@ -0,0 +1,42 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" + apiv1 "k8s.io/api/core/v1" +) + +func Test_parseConfigMap(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + _, err := parseConfigMap(&apiv1.ConfigMap{}) + assert.NoError(t, err) + }) + t.Run("Config", func(t *testing.T) { + c, err := parseConfigMap(&apiv1.ConfigMap{Data: map[string]string{"config": "containerRuntimeExecutor: pns"}}) + if assert.NoError(t, err) { + assert.Equal(t, "pns", c.ContainerRuntimeExecutor) + } + }) + t.Run("Complex", func(t *testing.T) { + c, err := parseConfigMap(&apiv1.ConfigMap{Data: map[string]string{"containerRuntimeExecutor": "pns", "artifactRepository": ` archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey`}}) + if assert.NoError(t, err) { + assert.Equal(t, "pns", c.ContainerRuntimeExecutor) + assert.NotEmpty(t, c.ArtifactRepository) + } + }) + t.Run("IgnoreGarbage", func(t *testing.T) { + _, err := parseConfigMap(&apiv1.ConfigMap{Data: map[string]string{"garbage": "garbage"}}) + assert.NoError(t, err) + }) +} diff --git a/docs/configure-artifact-repository.md b/docs/configure-artifact-repository.md index eb3e092d2997..de3ae009c557 100644 --- a/docs/configure-artifact-repository.md +++ b/docs/configure-artifact-repository.md @@ -110,8 +110,7 @@ Example: $ kubectl edit configmap workflow-controller-configmap -n argo # assumes argo was installed in the argo namespace ... data: - config: | - artifactRepository: + artifactRepository: | s3: bucket: my-bucket keyPrefix: prefix/in/bucket #optional diff --git a/docs/getting-started.md b/docs/getting-started.md index 8094bb7a6147..002cbb82890b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -128,8 +128,7 @@ kubectl edit cm -n argo workflow-controller-configmap Add the following: ```yaml data: - config: | - artifactRepository: + artifactRepository: | s3: bucket: my-bucket endpoint: argo-artifacts:9000 diff --git a/docs/workflow-controller-configmap.yaml b/docs/workflow-controller-configmap.yaml index e85e0cdb4d90..8ba7b1c52b31 100644 --- a/docs/workflow-controller-configmap.yaml +++ b/docs/workflow-controller-configmap.yaml @@ -4,174 +4,173 @@ kind: ConfigMap metadata: name: workflow-controller-configmap data: - config: | - # instanceID is a label selector to limit the controller's watch to a specific instance. It - # contains an arbitrary value that is carried forward into its pod labels, under the key - # workflows.argoproj.io/controller-instanceid, for the purposes of workflow segregation. This - # enables a controller to only receive workflow and pod events that it is interested about, - # in order to support multiple controllers in a single cluster, and ultimately allows the - # controller itself to be bundled as part of a higher level application. If omitted, the - # controller watches workflows and pods that *are not* labeled with an instance id. - instanceID: my-ci-controller - - # Parallelism limits the max total parallel workflows that can execute at the same time - # (available since Argo v2.3) - parallelism: 10 - - # uncomment flowing lines if workflow controller runs in a different k8s cluster with the - # workflow workloads, or needs to communicate with the k8s apiserver using an out-of-cluster - # kubeconfig secret - # kubeConfig: - # # name of the kubeconfig secret, may not be empty when kubeConfig specified - # secretName: kubeconfig-secret - # # key of the kubeconfig secret, may not be empty when kubeConfig specified - # secretKey: kubeconfig - # # mounting path of the kubeconfig secret, default to /kube/config - # mountPath: /kubeconfig/mount/path - # # volume name when mounting the secret, default to kubeconfig - # volumeName: kube-config-volume - - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + # instanceID is a label selector to limit the controller's watch to a specific instance. It + # contains an arbitrary value that is carried forward into its pod labels, under the key + # workflows.argoproj.io/controller-instanceid, for the purposes of workflow segregation. This + # enables a controller to only receive workflow and pod events that it is interested about, + # in order to support multiple controllers in a single cluster, and ultimately allows the + # controller itself to be bundled as part of a higher level application. If omitted, the + # controller watches workflows and pods that *are not* labeled with an instance id. + instanceID: my-ci-controller + + # Parallelism limits the max total parallel workflows that can execute at the same time + # (available since Argo v2.3) + parallelism: 10 + + # uncomment flowing lines if workflow controller runs in a different k8s cluster with the + # workflow workloads, or needs to communicate with the k8s apiserver using an out-of-cluster + # kubeconfig secret + # kubeConfig: + # # name of the kubeconfig secret, may not be empty when kubeConfig specified + # secretName: kubeconfig-secret + # # key of the kubeconfig secret, may not be empty when kubeConfig specified + # secretKey: kubeconfig + # # mounting path of the kubeconfig secret, default to /kube/config + # mountPath: /kubeconfig/mount/path + # # volume name when mounting the secret, default to kubeconfig + # volumeName: kube-config-volume + + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} featureFlags: # Enable resource duration resourcesDuration: false - # artifactRepository defines the default location to be used as the artifact repository for - # container artifacts. - artifactRepository: - # archiveLogs will archive the main container logs as an artifact - archiveLogs: true - - s3: - # Use the corresponding endpoint depending on your S3 provider: - # AWS: s3.amazonaws.com - # GCS: storage.googleapis.com - # Minio: my-minio-endpoint.default:9000 - endpoint: s3.amazonaws.com - bucket: my-bucket - region: us-west-2 - # insecure will disable TLS. Primarily used for minio installs not configured with TLS - insecure: false - # keyFormat is a format pattern to define how artifacts will be organized in a bucket. - # It can reference workflow metadata variables such as workflow.namespace, workflow.name, - # pod.name. Can also use strftime formating of workflow.creationTimestamp so that workflow - # artifacts can be organized by date. If omitted, will use `{{workflow.name}}/{{pod.name}}`, - # which has potential for have collisions. - # The following example pattern organizes workflow artifacts under a "my-artifacts" sub dir, - # then sub dirs for year, month, date and finally workflow name and pod. - # e.g.: my-artifacts/2018/08/23/my-workflow-abc123/my-workflow-abc123-1234567890 - keyFormat: "my-artifacts\ - /{{workflow.creationTimestamp.Y}}\ - /{{workflow.creationTimestamp.m}}\ - /{{workflow.creationTimestamp.d}}\ - /{{workflow.name}}\ - /{{pod.name}}" - # The actual secret object (in this example my-s3-credentials), should be created in every - # namespace where a workflow needs to store its artifacts to S3. If omitted, - # attempts to use IAM role to access the bucket (instead of accessKey/secretKey). - accessKeySecret: - name: my-s3-credentials - key: accessKey - secretKeySecret: - name: my-s3-credentials - key: secretKey - - # Specifies the container runtime interface to use (default: docker) - # must be one of: docker, kubelet, k8sapi, pns - containerRuntimeExecutor: docker - - # Specifies the location of docker.sock on the host for docker executor (default: /var/run/docker.sock) - # (available since Argo v2.4) - dockerSockPath: /var/someplace/else/docker.sock - - # kubelet port when using kubelet executor (default: 10250) - kubeletPort: 10250 - - # disable the TLS verification of the kubelet executor (default: false) - kubeletInsecure: false - - # executor controls how the init and wait container should be customized - # (available since Argo v2.3) - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 512Mi - # args & env allows command line arguments and environment variables to be appended to the - # executor container and is mainly used for development/debugging purposes. - args: - - --loglevel - - debug - - --gloglevel - - "6" - env: - # ARGO_TRACE enables some tracing information for debugging purposes. Currently it enables - # logging of S3 request/response payloads (including auth headers) - - name: ARGO_TRACE - value: "1" - - # metricsConfig controls the path and port for prometheus metrics - metricsConfig: - disableLegacy: false # Switch to "true" to disable legacy metrics. "false" by default - enabled: true - path: /metrics - port: 8080 - - # telemetryConfig controls the path and port for prometheus telemetry - telemetryConfig: - enabled: true - path: /telemetry - port: 8080 - - # enable persistence using postgres - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - # if true node status is only saved to the persistence DB to avoid the 1MB limit in etcd - nodeStatusOffLoad: false - # save completed workloads to the workflow archive - archive: false - # Optional name of the cluster I'm running in. This must be unique for your cluster. - clusterName: default - postgresql: - host: localhost - port: 5432 - database: postgres - tableName: argo_workflows - # the database secrets must be in the same namespace of the controller - userNameSecret: - name: argo-postgres-config - key: username - passwordSecret: - name: argo-postgres-config - key: password - - # Optional config for mysql: - # mysql: - # host: localhost - # port: 3306 - # database: argo - # tableName: argo_workflows - # userNameSecret: - # name: argo-mysql-config - # key: username - # passwordSecret: - # name: argo-mysql-config - # key: password - - # default workflow spec, follow the workflow spec, more info: https://github.com/argoproj/argo/blob/master/examples/README.md#the-structure-of-workflow-specs - workflowDefaults: - ttlStrategy: - secondsAfterCompletion: 10 + # artifactRepository defines the default location to be used as the artifact repository for + # container artifacts. + artifactRepository: | + # archiveLogs will archive the main container logs as an artifact + archiveLogs: true + + s3: + # Use the corresponding endpoint depending on your S3 provider: + # AWS: s3.amazonaws.com + # GCS: storage.googleapis.com + # Minio: my-minio-endpoint.default:9000 + endpoint: s3.amazonaws.com + bucket: my-bucket + region: us-west-2 + # insecure will disable TLS. Primarily used for minio installs not configured with TLS + insecure: false + # keyFormat is a format pattern to define how artifacts will be organized in a bucket. + # It can reference workflow metadata variables such as workflow.namespace, workflow.name, + # pod.name. Can also use strftime formating of workflow.creationTimestamp so that workflow + # artifacts can be organized by date. If omitted, will use `{{workflow.name}}/{{pod.name}}`, + # which has potential for have collisions. + # The following example pattern organizes workflow artifacts under a "my-artifacts" sub dir, + # then sub dirs for year, month, date and finally workflow name and pod. + # e.g.: my-artifacts/2018/08/23/my-workflow-abc123/my-workflow-abc123-1234567890 + keyFormat: "my-artifacts\ + /{{workflow.creationTimestamp.Y}}\ + /{{workflow.creationTimestamp.m}}\ + /{{workflow.creationTimestamp.d}}\ + /{{workflow.name}}\ + /{{pod.name}}" + # The actual secret object (in this example my-s3-credentials), should be created in every + # namespace where a workflow needs to store its artifacts to S3. If omitted, + # attempts to use IAM role to access the bucket (instead of accessKey/secretKey). + accessKeySecret: + name: my-s3-credentials + key: accessKey + secretKeySecret: + name: my-s3-credentials + key: secretKey + + # Specifies the container runtime interface to use (default: docker) + # must be one of: docker, kubelet, k8sapi, pns + containerRuntimeExecutor: docker + + # Specifies the location of docker.sock on the host for docker executor (default: /var/run/docker.sock) + # (available since Argo v2.4) + dockerSockPath: /var/someplace/else/docker.sock + + # kubelet port when using kubelet executor (default: 10250) + kubeletPort: 10250 + + # disable the TLS verification of the kubelet executor (default: false) + kubeletInsecure: false + + # executor controls how the init and wait container should be customized + # (available since Argo v2.3) + executor: | + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 0.1 + memory: 64Mi + limits: + cpu: 0.5 + memory: 512Mi + # args & env allows command line arguments and environment variables to be appended to the + # executor container and is mainly used for development/debugging purposes. + args: + - --loglevel + - debug + - --gloglevel + - "6" + env: + # ARGO_TRACE enables some tracing information for debugging purposes. Currently it enables + # logging of S3 request/response payloads (including auth headers) + - name: ARGO_TRACE + value: "1" + + # metricsConfig controls the path and port for prometheus metrics + metricsConfig: | + disableLegacy: false # Switch to "true" to disable legacy metrics. "false" by default + enabled: true + path: /metrics + port: 8080 + + # telemetryConfig controls the path and port for prometheus telemetry + telemetryConfig: | + enabled: true + path: /telemetry + port: 8080 + + # enable persistence using postgres + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + # if true node status is only saved to the persistence DB to avoid the 1MB limit in etcd + nodeStatusOffLoad: false + # save completed workloads to the workflow archive + archive: false + # Optional name of the cluster I'm running in. This must be unique for your cluster. + clusterName: default + postgresql: + host: localhost + port: 5432 + database: postgres + tableName: argo_workflows + # the database secrets must be in the same namespace of the controller + userNameSecret: + name: argo-postgres-config + key: username + passwordSecret: + name: argo-postgres-config + key: password + + # Optional config for mysql: + # mysql: + # host: localhost + # port: 3306 + # database: argo + # tableName: argo_workflows + # userNameSecret: + # name: argo-mysql-config + # key: username + # passwordSecret: + # name: argo-mysql-config + # key: password + + # default workflow spec, follow the workflow spec, more info: https://github.com/argoproj/argo/blob/master/examples/README.md#the-structure-of-workflow-specs + workflowDefaults: | + ttlStrategy: + secondsAfterCompletion: 10 diff --git a/manifests/quick-start-mysql.yaml b/manifests/quick-start-mysql.yaml index b236634c538b..dd14f89604a2 100644 --- a/manifests/quick-start-mysql.yaml +++ b/manifests/quick-start-mysql.yaml @@ -267,58 +267,48 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - mysql: - host: mysql - port: 3306 - database: argo - tableName: argo_workflows - userNameSecret: - name: argo-mysql-config - key: username - passwordSecret: - name: argo-mysql-config - key: password + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + mysql: + host: mysql + port: 3306 + database: argo + tableName: argo_workflows + userNameSecret: + name: argo-mysql-config + key: username + passwordSecret: + name: argo-mysql-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap diff --git a/manifests/quick-start-no-db.yaml b/manifests/quick-start-no-db.yaml index 6cb194fee26b..5ec45b361fed 100644 --- a/manifests/quick-start-no-db.yaml +++ b/manifests/quick-start-no-db.yaml @@ -267,41 +267,31 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 kind: ConfigMap metadata: name: workflow-controller-configmap diff --git a/manifests/quick-start-postgres.yaml b/manifests/quick-start-postgres.yaml index 966ae359ed5b..5934b9662a73 100644 --- a/manifests/quick-start-postgres.yaml +++ b/manifests/quick-start-postgres.yaml @@ -267,58 +267,48 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - postgresql: - host: postgres - port: 5432 - database: postgres - tableName: argo_workflows - userNameSecret: - name: argo-postgres-config - key: username - passwordSecret: - name: argo-postgres-config - key: password + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + postgresql: + host: postgres + port: 5432 + database: postgres + tableName: argo_workflows + userNameSecret: + name: argo-postgres-config + key: username + passwordSecret: + name: argo-postgres-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap diff --git a/manifests/quick-start/base/kustomization.yaml b/manifests/quick-start/base/kustomization.yaml index a480479381c8..d8ffccde395c 100644 --- a/manifests/quick-start/base/kustomization.yaml +++ b/manifests/quick-start/base/kustomization.yaml @@ -7,4 +7,7 @@ bases: resources: - workflow-role.yaml - - workflow-default-rolebinding.yaml \ No newline at end of file + - workflow-default-rolebinding.yaml + +patchesStrategicMerge: + - overlays/workflow-controller-configmap.yaml \ No newline at end of file diff --git a/manifests/quick-start/base/overlays/workflow-controller-configmap.yaml b/manifests/quick-start/base/overlays/workflow-controller-configmap.yaml new file mode 100644 index 000000000000..04965259d0d7 --- /dev/null +++ b/manifests/quick-start/base/overlays/workflow-controller-configmap.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +data: + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + featureFlags: | + resourcesDuration: true + metricsConfig: | + enabled: true + path: /metrics + port: 9090 + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} +kind: ConfigMap +metadata: + name: workflow-controller-configmap \ No newline at end of file diff --git a/manifests/quick-start/mysql/overlays/workflow-controller-configmap.yaml b/manifests/quick-start/mysql/overlays/workflow-controller-configmap.yaml index f644573b5584..2b22dbfe9018 100644 --- a/manifests/quick-start/mysql/overlays/workflow-controller-configmap.yaml +++ b/manifests/quick-start/mysql/overlays/workflow-controller-configmap.yaml @@ -1,57 +1,22 @@ apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - mysql: - host: mysql - port: 3306 - database: argo - tableName: argo_workflows - userNameSecret: - name: argo-mysql-config - key: username - passwordSecret: - name: argo-mysql-config - key: password + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + mysql: + host: mysql + port: 3306 + database: argo + tableName: argo_workflows + userNameSecret: + name: argo-mysql-config + key: username + passwordSecret: + name: argo-mysql-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap \ No newline at end of file diff --git a/manifests/quick-start/no-db/kustomization.yaml b/manifests/quick-start/no-db/kustomization.yaml index 76f15e3feea7..55050e0f488e 100644 --- a/manifests/quick-start/no-db/kustomization.yaml +++ b/manifests/quick-start/no-db/kustomization.yaml @@ -3,6 +3,3 @@ kind: Kustomization bases: - ../base - -patchesStrategicMerge: - - overlays/workflow-controller-configmap.yaml \ No newline at end of file diff --git a/manifests/quick-start/no-db/overlays/workflow-controller-configmap.yaml b/manifests/quick-start/no-db/overlays/workflow-controller-configmap.yaml deleted file mode 100644 index ce7afed8344e..000000000000 --- a/manifests/quick-start/no-db/overlays/workflow-controller-configmap.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true -kind: ConfigMap -metadata: - name: workflow-controller-configmap \ No newline at end of file diff --git a/manifests/quick-start/postgres/overlays/workflow-controller-configmap.yaml b/manifests/quick-start/postgres/overlays/workflow-controller-configmap.yaml index 9972cce3cb99..16ea1dae6684 100644 --- a/manifests/quick-start/postgres/overlays/workflow-controller-configmap.yaml +++ b/manifests/quick-start/postgres/overlays/workflow-controller-configmap.yaml @@ -1,57 +1,22 @@ apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - postgresql: - host: postgres - port: 5432 - database: postgres - tableName: argo_workflows - userNameSecret: - name: argo-postgres-config - key: username - passwordSecret: - name: argo-postgres-config - key: password + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + postgresql: + host: postgres + port: 5432 + database: postgres + tableName: argo_workflows + userNameSecret: + name: argo-postgres-config + key: username + passwordSecret: + name: argo-postgres-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap \ No newline at end of file diff --git a/persist/sqldb/sqldb.go b/persist/sqldb/sqldb.go index 200fbcaf16d5..1f8a83be98dc 100644 --- a/persist/sqldb/sqldb.go +++ b/persist/sqldb/sqldb.go @@ -9,9 +9,9 @@ import ( "upper.io/db.v3/mysql" "upper.io/db.v3/postgresql" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/errors" "github.com/argoproj/argo/util" - "github.com/argoproj/argo/workflow/config" ) // CreateDBSession creates the dB session diff --git a/server/apiserver/argoserver.go b/server/apiserver/argoserver.go index 58cf56a5d0ff..1dabbc29859d 100644 --- a/server/apiserver/argoserver.go +++ b/server/apiserver/argoserver.go @@ -13,16 +13,12 @@ import ( "github.com/soheilhy/cmux" "golang.org/x/net/context" "google.golang.org/grpc" - apiv1 "k8s.io/api/core/v1" - apiError "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - "sigs.k8s.io/yaml" "github.com/argoproj/argo" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/errors" "github.com/argoproj/argo/persist/sqldb" cronworkflowpkg "github.com/argoproj/argo/pkg/apiclient/cronworkflow" @@ -42,8 +38,6 @@ import ( "github.com/argoproj/argo/server/workflowtemplate" grpcutil "github.com/argoproj/argo/util/grpc" "github.com/argoproj/argo/util/json" - "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" ) const ( @@ -57,7 +51,7 @@ type argoServer struct { managedNamespace string kubeClientset *kubernetes.Clientset authenticator auth.Gatekeeper - configName string + configController config.Controller stopCh chan struct{} } @@ -80,7 +74,8 @@ func NewArgoServer(opts ArgoServerOpts) *argoServer { managedNamespace: opts.ManagedNamespace, kubeClientset: opts.KubeClientset, authenticator: auth.NewGatekeeper(opts.AuthMode, opts.WfClientSet, opts.KubeClientset, opts.RestConfig), - configName: opts.ConfigName, + configController: config.NewController(opts.Namespace, opts.ConfigName, opts.KubeClientset), + stopCh: make(chan struct{}), } } @@ -111,11 +106,11 @@ func (ao ArgoServerOpts) ValidateOpts() error { func (as *argoServer) Run(ctx context.Context, port int, browserOpenFunc func(string)) { log.WithField("version", argo.GetVersion()).Info("Starting Argo Server") - configMap, err := as.rsyncConfig() + + configMap, err := as.configController.Get() if err != nil { log.Fatal(err) } - as.restartOnConfigChange(ctx.Done()) var offloadRepo = sqldb.ExplosiveOffloadNodeStatusRepo var wfArchive = sqldb.NullWorkflowArchive persistence := configMap.Persistence @@ -160,6 +155,7 @@ func (as *argoServer) Run(ctx context.Context, port int, browserOpenFunc func(st httpL := tcpm.Match(cmux.HTTP1Fast()) grpcL := tcpm.Match(cmux.Any()) + go as.configController.Run(as.stopCh, as.restartOnConfigChange) go func() { as.checkServeErr("grpcServer", grpcServer.Serve(grpcL)) }() go func() { as.checkServeErr("httpServer", httpServer.Serve(httpL)) }() go func() { as.checkServeErr("tcpm", tcpm.Serve()) }() @@ -167,7 +163,6 @@ func (as *argoServer) Run(ctx context.Context, port int, browserOpenFunc func(st browserOpenFunc("http://localhost" + address) - as.stopCh = make(chan struct{}) <-as.stopCh } @@ -253,68 +248,13 @@ func mustRegisterGWHandler(register registerFunc, ctx context.Context, mux *runt } } -// ResyncConfig reloads the controller config from the configmap -func (as *argoServer) rsyncConfig() (*config.WorkflowControllerConfig, error) { - cm, err := as.kubeClientset.CoreV1().ConfigMaps(as.namespace). - Get(as.configName, metav1.GetOptions{}) - if err != nil { - if apiError.IsNotFound(err) { - return &config.WorkflowControllerConfig{}, nil - } - return nil, errors.InternalWrapError(err) - } - return as.updateConfig(cm) -} - // Unlike the controller, the server creates object based on the config map at init time, and will not pick-up on // changes unless we restart. // Instead of opting to re-write the server, instead we'll just listen for any old change and restart. -func (as *argoServer) restartOnConfigChange(stopCh <-chan struct{}) { - go func() { - main: - for { - log.Info("establishing configmap watch") - w, err := as.kubeClientset.CoreV1().ConfigMaps(as.namespace). - Watch(metav1.ListOptions{FieldSelector: "metadata.name=" + as.configName}) - if err != nil { - log.Fatalf("error establishing watch: %s", err) - } - log.Info("configmap watch established") - for { - select { - // normal exit, e.g. due to user interrupt - case <-stopCh: - return - case e, open := <-w.ResultChan(): - if !open { - // The channel is closed, reopen it - continue main - } - if e.Type == watch.Modified || e.Type == watch.Deleted { - log.WithField("eventType", e.Type).Info("config map event, exiting gracefully") - as.stopCh <- struct{}{} - return - } - } - } - } - }() -} - -func (as *argoServer) updateConfig(cm *apiv1.ConfigMap) (*config.WorkflowControllerConfig, error) { - - configStr, ok := cm.Data[common.WorkflowControllerConfigMapKey] - if !ok { - log.Warnf("ConfigMap '%s' does not have key '%s'", as.configName, common.WorkflowControllerConfigMapKey) - configStr = "" - } - var config config.WorkflowControllerConfig - log.Infof("Config Map: %s", configStr) - err := yaml.Unmarshal([]byte(configStr), &config) - if err != nil { - return nil, errors.InternalWrapError(err) - } - return &config, nil +func (as *argoServer) restartOnConfigChange(config.Config) error { + log.Info("config map event, exiting gracefully") + as.stopCh <- struct{}{} + return nil } // checkServeErr checks the error from a .Serve() call to decide if it was a graceful shutdown diff --git a/test/e2e/fixtures/persistence.go b/test/e2e/fixtures/persistence.go index 50fab718600f..07b95a33ce8c 100644 --- a/test/e2e/fixtures/persistence.go +++ b/test/e2e/fixtures/persistence.go @@ -1,13 +1,11 @@ package fixtures import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "sigs.k8s.io/yaml" "upper.io/db.v3/lib/sqlbuilder" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/persist/sqldb" - "github.com/argoproj/argo/workflow/config" ) type Persistence struct { @@ -17,12 +15,8 @@ type Persistence struct { } func newPersistence(kubeClient kubernetes.Interface) *Persistence { - cm, err := kubeClient.CoreV1().ConfigMaps(Namespace).Get("workflow-controller-configmap", metav1.GetOptions{}) - if err != nil { - panic(err) - } - wcConfig := &config.WorkflowControllerConfig{} - err = yaml.Unmarshal([]byte(cm.Data["config"]), wcConfig) + configController := config.NewController(Namespace, "workflow-controller-configmap", kubeClient) + wcConfig, err := configController.Get() if err != nil { panic(err) } diff --git a/test/e2e/manifests/postgres/overlays/argo-server-deployment.yaml b/test/e2e/manifests/mixins/argo-server-deployment.yaml similarity index 100% rename from test/e2e/manifests/postgres/overlays/argo-server-deployment.yaml rename to test/e2e/manifests/mixins/argo-server-deployment.yaml diff --git a/test/e2e/manifests/mixins/workflow-controller-configmap.yaml b/test/e2e/manifests/mixins/workflow-controller-configmap.yaml new file mode 100644 index 000000000000..b16bf2883d1b --- /dev/null +++ b/test/e2e/manifests/mixins/workflow-controller-configmap.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: workflow-controller-configmap +data: + containerRuntimeExecutor: pns + executor: | + imagePullPolicy: Never + resources: + requests: + cpu: 0.1 + memory: 64Mi + limits: + cpu: 0.5 + memory: 128Mi \ No newline at end of file diff --git a/test/e2e/manifests/mixins/workflow-controller-deployment.yaml b/test/e2e/manifests/mixins/workflow-controller-deployment.yaml new file mode 100644 index 000000000000..31070d649c10 --- /dev/null +++ b/test/e2e/manifests/mixins/workflow-controller-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: workflow-controller +spec: + template: + spec: + containers: + - name: workflow-controller + imagePullPolicy: Never + args: + - --executor-image + - argoproj/argoexec:latest + - --namespaced + - --loglevel + - debug + env: + # these are designed to force offloading on and make GC happen regularly so we shake out any bugs + - name: ALWAYS_OFFLOAD_NODE_STATUS + value: "true" + - name: OFFLOAD_NODE_STATUS_TTL + value: 30s + - name: WORKFLOW_GC_PERIOD + value: 30s + - name: UPPERIO_DB_DEBUG + value: "1" \ No newline at end of file diff --git a/test/e2e/manifests/mysql.yaml b/test/e2e/manifests/mysql.yaml index 17a528b0e543..6604fb227f8f 100644 --- a/test/e2e/manifests/mysql.yaml +++ b/test/e2e/manifests/mysql.yaml @@ -267,58 +267,58 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - mysql: - host: mysql - port: 3306 - database: argo - tableName: argo_workflows - userNameSecret: - name: argo-mysql-config - key: username - passwordSecret: - name: argo-mysql-config - key: password + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + containerRuntimeExecutor: pns + executor: | + imagePullPolicy: Never + resources: + requests: + cpu: 0.1 + memory: 64Mi + limits: + cpu: 0.5 + memory: 128Mi + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + mysql: + host: mysql + port: 3306 + database: argo + tableName: argo_workflows + userNameSecret: + name: argo-mysql-config + key: username + passwordSecret: + name: argo-mysql-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap @@ -494,17 +494,11 @@ spec: spec: containers: - args: - - --configmap - - workflow-controller-configmap - --executor-image - argoproj/argoexec:latest - --namespaced - --loglevel - debug - - --executor-image-pull-policy - - Never - - --container-runtime-executor - - pns command: - workflow-controller env: diff --git a/test/e2e/manifests/mysql/kustomization.yaml b/test/e2e/manifests/mysql/kustomization.yaml index f87bd1b832b4..cc4b5453c6b3 100644 --- a/test/e2e/manifests/mysql/kustomization.yaml +++ b/test/e2e/manifests/mysql/kustomization.yaml @@ -5,12 +5,6 @@ bases: - ../../../../manifests/quick-start/mysql patchesStrategicMerge: - - overlays/argo-server-deployment.yaml - -patchesJson6902: - - target: - version: v1 - group: apps - kind: Deployment - name: workflow-controller - path: overlays/workflow-controller-deployment.yaml + - ../mixins/argo-server-deployment.yaml + - ../mixins/workflow-controller-configmap.yaml + - ../mixins/workflow-controller-deployment.yaml diff --git a/test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml b/test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml deleted file mode 100644 index 5c699f7ad799..000000000000 --- a/test/e2e/manifests/mysql/overlays/argo-server-deployment.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# This is an auto-generated file. DO NOT EDIT -apiVersion: apps/v1 -kind: Deployment -metadata: - name: argo-server -spec: - template: - spec: - containers: - - name: argo-server - args: - - server - - --namespaced - - --auth-mode - - client - - --loglevel - - debug - imagePullPolicy: Never - env: - - name: ARGO_TOKEN - value: password - - name: UPPERIO_DB_DEBUG - value: "1" diff --git a/test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml b/test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml deleted file mode 100644 index db7cfe053fec..000000000000 --- a/test/e2e/manifests/mysql/overlays/workflow-controller-deployment.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# This is an auto-generated file. DO NOT EDIT -- op: replace - path: /spec/template/spec/containers/0/imagePullPolicy - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --loglevel -- op: add - path: /spec/template/spec/containers/0/args/- - value: debug -- op: add - path: /spec/template/spec/containers/0/args/- - value: --executor-image-pull-policy -- op: add - path: /spec/template/spec/containers/0/args/- - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --container-runtime-executor -- op: add - path: /spec/template/spec/containers/0/args/- - value: pns -- op: add - path: /spec/template/spec/containers/0/env - value: - # these are designed to force offloading on and make GC happen regularly so we shake out any bugs - - name: ALWAYS_OFFLOAD_NODE_STATUS - value: "true" - - name: OFFLOAD_NODE_STATUS_TTL - value: 30s - - name: WORKFLOW_GC_PERIOD - value: 30s - - name: UPPERIO_DB_DEBUG - value: "1" diff --git a/test/e2e/manifests/no-db.yaml b/test/e2e/manifests/no-db.yaml index 05a075e8aabf..14593383464a 100644 --- a/test/e2e/manifests/no-db.yaml +++ b/test/e2e/manifests/no-db.yaml @@ -267,41 +267,41 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + containerRuntimeExecutor: pns + executor: | + imagePullPolicy: Never + resources: + requests: + cpu: 0.1 + memory: 64Mi + limits: + cpu: 0.5 + memory: 128Mi + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 kind: ConfigMap metadata: name: workflow-controller-configmap @@ -409,17 +409,11 @@ spec: spec: containers: - args: - - --configmap - - workflow-controller-configmap - --executor-image - argoproj/argoexec:latest - --namespaced - --loglevel - debug - - --executor-image-pull-policy - - Never - - --container-runtime-executor - - pns command: - workflow-controller env: diff --git a/test/e2e/manifests/no-db/kustomization.yaml b/test/e2e/manifests/no-db/kustomization.yaml index 175074bedfcb..1c86142e6105 100644 --- a/test/e2e/manifests/no-db/kustomization.yaml +++ b/test/e2e/manifests/no-db/kustomization.yaml @@ -5,12 +5,6 @@ bases: - ../../../../manifests/quick-start/no-db patchesStrategicMerge: - - overlays/argo-server-deployment.yaml - -patchesJson6902: - - target: - version: v1 - group: apps - kind: Deployment - name: workflow-controller - path: overlays/workflow-controller-deployment.yaml \ No newline at end of file + - ../mixins/argo-server-deployment.yaml + - ../mixins/workflow-controller-configmap.yaml + - ../mixins/workflow-controller-deployment.yaml diff --git a/test/e2e/manifests/no-db/overlays/argo-server-deployment.yaml b/test/e2e/manifests/no-db/overlays/argo-server-deployment.yaml deleted file mode 100644 index 5c699f7ad799..000000000000 --- a/test/e2e/manifests/no-db/overlays/argo-server-deployment.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# This is an auto-generated file. DO NOT EDIT -apiVersion: apps/v1 -kind: Deployment -metadata: - name: argo-server -spec: - template: - spec: - containers: - - name: argo-server - args: - - server - - --namespaced - - --auth-mode - - client - - --loglevel - - debug - imagePullPolicy: Never - env: - - name: ARGO_TOKEN - value: password - - name: UPPERIO_DB_DEBUG - value: "1" diff --git a/test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml b/test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml deleted file mode 100644 index db7cfe053fec..000000000000 --- a/test/e2e/manifests/no-db/overlays/workflow-controller-deployment.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# This is an auto-generated file. DO NOT EDIT -- op: replace - path: /spec/template/spec/containers/0/imagePullPolicy - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --loglevel -- op: add - path: /spec/template/spec/containers/0/args/- - value: debug -- op: add - path: /spec/template/spec/containers/0/args/- - value: --executor-image-pull-policy -- op: add - path: /spec/template/spec/containers/0/args/- - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --container-runtime-executor -- op: add - path: /spec/template/spec/containers/0/args/- - value: pns -- op: add - path: /spec/template/spec/containers/0/env - value: - # these are designed to force offloading on and make GC happen regularly so we shake out any bugs - - name: ALWAYS_OFFLOAD_NODE_STATUS - value: "true" - - name: OFFLOAD_NODE_STATUS_TTL - value: 30s - - name: WORKFLOW_GC_PERIOD - value: 30s - - name: UPPERIO_DB_DEBUG - value: "1" diff --git a/test/e2e/manifests/postgres.yaml b/test/e2e/manifests/postgres.yaml index e976a556501f..f21a82cf57e7 100644 --- a/test/e2e/manifests/postgres.yaml +++ b/test/e2e/manifests/postgres.yaml @@ -267,58 +267,58 @@ subjects: --- apiVersion: v1 data: - config: | - executor: - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 0.1 - memory: 64Mi - limits: - cpu: 0.5 - memory: 128Mi - artifactRepository: - archiveLogs: true - s3: - bucket: my-bucket - endpoint: minio:9000 - insecure: true - accessKeySecret: - name: my-minio-cred - key: accesskey - secretKeySecret: - name: my-minio-cred - key: secretkey - metricsConfig: - enabled: true - path: /metrics - port: 9090 - links: - - name: Example Workflow Link - scope: workflow - url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} - - name: Example Pod Link - scope: pod - url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} - featureFlags: - resourcesDuration: true - persistence: - connectionPool: - maxIdleConns: 100 - maxOpenConns: 0 - nodeStatusOffLoad: true - archive: true - postgresql: - host: postgres - port: 5432 - database: postgres - tableName: argo_workflows - userNameSecret: - name: argo-postgres-config - key: username - passwordSecret: - name: argo-postgres-config - key: password + artifactRepository: | + archiveLogs: true + s3: + bucket: my-bucket + endpoint: minio:9000 + insecure: true + accessKeySecret: + name: my-minio-cred + key: accesskey + secretKeySecret: + name: my-minio-cred + key: secretkey + containerRuntimeExecutor: pns + executor: | + imagePullPolicy: Never + resources: + requests: + cpu: 0.1 + memory: 64Mi + limits: + cpu: 0.5 + memory: 128Mi + featureFlags: | + resourcesDuration: true + links: | + - name: Example Workflow Link + scope: workflow + url: http://logging-facility?namespace=${metadata.namespace}&workflowName=${metadata.name} + - name: Example Pod Link + scope: pod + url: http://logging-facility?namespace=${metadata.namespace}&podName=${metadata.name} + metricsConfig: | + enabled: true + path: /metrics + port: 9090 + persistence: | + connectionPool: + maxIdleConns: 100 + maxOpenConns: 0 + nodeStatusOffLoad: true + archive: true + postgresql: + host: postgres + port: 5432 + database: postgres + tableName: argo_workflows + userNameSecret: + name: argo-postgres-config + key: username + passwordSecret: + name: argo-postgres-config + key: password kind: ConfigMap metadata: name: workflow-controller-configmap @@ -486,17 +486,11 @@ spec: spec: containers: - args: - - --configmap - - workflow-controller-configmap - --executor-image - argoproj/argoexec:latest - --namespaced - --loglevel - debug - - --executor-image-pull-policy - - Never - - --container-runtime-executor - - pns command: - workflow-controller env: diff --git a/test/e2e/manifests/postgres/kustomization.yaml b/test/e2e/manifests/postgres/kustomization.yaml index a7775cfb6d7b..963fea890750 100644 --- a/test/e2e/manifests/postgres/kustomization.yaml +++ b/test/e2e/manifests/postgres/kustomization.yaml @@ -5,12 +5,6 @@ bases: - ../../../../manifests/quick-start/postgres patchesStrategicMerge: - - overlays/argo-server-deployment.yaml - -patchesJson6902: - - target: - version: v1 - group: apps - kind: Deployment - name: workflow-controller - path: overlays/workflow-controller-deployment.yaml \ No newline at end of file + - ../mixins/argo-server-deployment.yaml + - ../mixins/workflow-controller-configmap.yaml + - ../mixins/workflow-controller-deployment.yaml diff --git a/test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml b/test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml deleted file mode 100644 index 7a42b4d41bd0..000000000000 --- a/test/e2e/manifests/postgres/overlays/workflow-controller-deployment.yaml +++ /dev/null @@ -1,33 +0,0 @@ -- op: replace - path: /spec/template/spec/containers/0/imagePullPolicy - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --loglevel -- op: add - path: /spec/template/spec/containers/0/args/- - value: debug -- op: add - path: /spec/template/spec/containers/0/args/- - value: --executor-image-pull-policy -- op: add - path: /spec/template/spec/containers/0/args/- - value: Never -- op: add - path: /spec/template/spec/containers/0/args/- - value: --container-runtime-executor -- op: add - path: /spec/template/spec/containers/0/args/- - value: pns -- op: add - path: /spec/template/spec/containers/0/env - value: - # these are designed to force offloading on and make GC happen regularly so we shake out any bugs - - name: ALWAYS_OFFLOAD_NODE_STATUS - value: "true" - - name: OFFLOAD_NODE_STATUS_TTL - value: 30s - - name: WORKFLOW_GC_PERIOD - value: 30s - - name: UPPERIO_DB_DEBUG - value: "1" diff --git a/workflow/common/common.go b/workflow/common/common.go index 46deb4ae9c75..62773dab489e 100644 --- a/workflow/common/common.go +++ b/workflow/common/common.go @@ -7,10 +7,6 @@ import ( ) const ( - // WorkflowControllerConfigMapKey is the key in the configmap to retrieve workflow configuration from. - // Content encoding is expected to be YAML. - WorkflowControllerConfigMapKey = "config" - // DefaultArchivePattern is the default pattern when storing artifacts in an archive repository DefaultArchivePattern = "{{workflow.name}}/{{pod.name}}" diff --git a/workflow/controller/config_controller.go b/workflow/controller/config_controller.go index 3731bdcbc2c6..0ca3f22d142f 100644 --- a/workflow/controller/config_controller.go +++ b/workflow/controller/config_controller.go @@ -2,52 +2,28 @@ package controller import ( "context" - "fmt" + log "github.com/sirupsen/logrus" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" - - log "github.com/sirupsen/logrus" "sigs.k8s.io/yaml" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/errors" "github.com/argoproj/argo/persist/sqldb" - "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" ) -// ResyncConfig reloads the controller config from the configmap -func (wfc *WorkflowController) ResyncConfig() error { - cmClient := wfc.kubeclientset.CoreV1().ConfigMaps(wfc.namespace) - cm, err := cmClient.Get(wfc.configMap, metav1.GetOptions{}) - if err != nil { - return errors.InternalWrapError(err) - } - return wfc.updateConfig(cm) -} - -func (wfc *WorkflowController) updateConfig(cm *apiv1.ConfigMap) error { - configStr, ok := cm.Data[common.WorkflowControllerConfigMapKey] - if !ok { - log.Warnf("ConfigMap '%s' does not have key '%s'", wfc.configMap, common.WorkflowControllerConfigMapKey) - configStr = "" - } - var config config.WorkflowControllerConfig - err := yaml.Unmarshal([]byte(configStr), &config) +func (wfc *WorkflowController) updateConfig(config config.Config) error { + bytes, err := yaml.Marshal(config) if err != nil { - return errors.InternalWrapError(err) + return err } - log.Printf("workflow controller configuration from %s:\n%s", wfc.configMap, configStr) + log.Info("Configuration:\n" + string(bytes)) if wfc.cliExecutorImage == "" && config.ExecutorImage == "" { - return errors.Errorf(errors.CodeBadRequest, "ConfigMap '%s' does not have executorImage", wfc.configMap) + return errors.Errorf(errors.CodeBadRequest, "ConfigMap does not have executorImage") } wfc.Config = config - if wfc.session != nil { err := wfc.session.Close() if err != nil { @@ -112,68 +88,6 @@ func (wfc *WorkflowController) executorImagePullPolicy() apiv1.PullPolicy { } } -func (wfc *WorkflowController) watchControllerConfigMap(ctx context.Context) (cache.Controller, error) { - source := wfc.newControllerConfigMapWatch() - _, controller := cache.NewInformer( - source, - &apiv1.ConfigMap{}, - 0, - cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - if cm, ok := obj.(*apiv1.ConfigMap); ok { - log.Infof("Detected ConfigMap update. Updating the controller config.") - err := wfc.updateConfig(cm) - if err != nil { - log.Errorf("Update of config failed due to: %v", err) - } - } - }, - UpdateFunc: func(old, new interface{}) { - oldCM := old.(*apiv1.ConfigMap) - newCM := new.(*apiv1.ConfigMap) - if oldCM.ResourceVersion == newCM.ResourceVersion { - return - } - if newCm, ok := new.(*apiv1.ConfigMap); ok { - log.Infof("Detected ConfigMap update. Updating the controller config.") - err := wfc.updateConfig(newCm) - if err != nil { - log.Errorf("Update of config failed due to: %v", err) - } - } - }, - }) - - go controller.Run(ctx.Done()) - return controller, nil -} - -func (wfc *WorkflowController) newControllerConfigMapWatch() *cache.ListWatch { - c := wfc.kubeclientset.CoreV1().RESTClient() - resource := "configmaps" - name := wfc.configMap - fieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", name)) - - listFunc := func(options metav1.ListOptions) (runtime.Object, error) { - options.FieldSelector = fieldSelector.String() - req := c.Get(). - Namespace(wfc.namespace). - Resource(resource). - VersionedParams(&options, metav1.ParameterCodec) - return req.Do().Get() - } - watchFunc := func(options metav1.ListOptions) (watch.Interface, error) { - options.Watch = true - options.FieldSelector = fieldSelector.String() - req := c.Get(). - Namespace(wfc.namespace). - Resource(resource). - VersionedParams(&options, metav1.ParameterCodec) - return req.Watch() - } - return &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc} -} - func ReadConfigMapValue(clientset kubernetes.Interface, namespace string, name string, key string) (string, error) { cm, err := clientset.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{}) if err != nil { diff --git a/workflow/controller/controller.go b/workflow/controller/controller.go index 1fab8a926dfb..11d0067fa27f 100644 --- a/workflow/controller/controller.go +++ b/workflow/controller/controller.go @@ -29,13 +29,13 @@ import ( "upper.io/db.v3/lib/sqlbuilder" "github.com/argoproj/argo" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/persist/sqldb" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" wfclientset "github.com/argoproj/argo/pkg/client/clientset/versioned" wfextv "github.com/argoproj/argo/pkg/client/informers/externalversions" wfextvv1alpha1 "github.com/argoproj/argo/pkg/client/informers/externalversions/workflow/v1alpha1" "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" "github.com/argoproj/argo/workflow/cron" "github.com/argoproj/argo/workflow/metrics" "github.com/argoproj/argo/workflow/packer" @@ -49,11 +49,9 @@ type WorkflowController struct { namespace string managedNamespace string - // configMap is the name of the config map in which to derive configuration of the controller from - configMap string - + configController config.Controller // Config is the workflow controller's configuration - Config config.WorkflowControllerConfig + Config config.Config // cliExecutorImage is the executor image as specified from the command line cliExecutorImage string @@ -107,7 +105,6 @@ func NewWorkflowController( restConfig: restConfig, kubeclientset: kubeclientset, wfclientset: wfclientset, - configMap: configMap, namespace: namespace, managedNamespace: managedNamespace, cliExecutorImage: executorImage, @@ -115,6 +112,7 @@ func NewWorkflowController( containerRuntimeExecutor: containerRuntimeExecutor, wfQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), podQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), + configController: config.NewController(namespace, configMap, kubeclientset), completedPods: make(chan string, 512), gcPods: make(chan string, 512), Metrics: make(map[string]prometheus.Metric), @@ -167,11 +165,14 @@ func (wfc *WorkflowController) Run(ctx context.Context, wfWorkers, podWorkers in log.WithField("version", argo.GetVersion()).Info("Starting Workflow Controller") log.Infof("Workers: workflow: %d, pod: %d", wfWorkers, podWorkers) - log.Info("Watch Workflow controller config map updates") - _, err := wfc.watchControllerConfigMap(ctx) + + c, err := wfc.configController.Get() + if err != nil { + log.Fatalf("Failed to register watch for controller config map: %v", err) + } + err = wfc.updateConfig(c) if err != nil { - log.Errorf("Failed to register watch for controller config map: %v", err) - return + log.Fatalf("Failed to update config: %v", err) } wfc.incompleteWfInformer = util.NewWorkflowInformer(wfc.restConfig, wfc.GetManagedNamespace(), workflowResyncPeriod, wfc.incompleteWorkflowTweakListOptions) @@ -181,6 +182,7 @@ func (wfc *WorkflowController) Run(ctx context.Context, wfWorkers, podWorkers in wfc.addWorkflowInformerHandler() wfc.podInformer = wfc.newPodInformer() + go wfc.configController.Run(ctx.Done(), wfc.updateConfig) go wfc.incompleteWfInformer.Run(ctx.Done()) go wfc.completedWfInformer.Run(ctx.Done()) go wfc.wftmplInformer.Informer().Run(ctx.Done()) diff --git a/workflow/controller/controller_test.go b/workflow/controller/controller_test.go index 4243834f3ffe..99588870f8bf 100644 --- a/workflow/controller/controller_test.go +++ b/workflow/controller/controller_test.go @@ -16,11 +16,11 @@ import ( "k8s.io/client-go/util/workqueue" "sigs.k8s.io/yaml" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/persist/sqldb" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" fakewfclientset "github.com/argoproj/argo/pkg/client/clientset/versioned/fake" wfextv "github.com/argoproj/argo/pkg/client/informers/externalversions" - "github.com/argoproj/argo/workflow/config" ) var helloWorldWf = ` @@ -104,7 +104,7 @@ func newController() *WorkflowController { panic("Timed out waiting for caches to sync") } return &WorkflowController{ - Config: config.WorkflowControllerConfig{ + Config: config.Config{ ExecutorImage: "executor:latest", }, kubeclientset: fake.NewSimpleClientset(), @@ -128,7 +128,7 @@ func newControllerWithDefaults() *WorkflowController { } myBool := true return &WorkflowController{ - Config: config.WorkflowControllerConfig{ + Config: config.Config{ ExecutorImage: "executor:latest", DefautWorkflowSpec: &wfv1.WorkflowSpec{ HostNetwork: &myBool, @@ -156,7 +156,7 @@ func newControllerWithComplexDefaults() *WorkflowController { var ten int32 = 10 var seven int32 = 10 return &WorkflowController{ - Config: config.WorkflowControllerConfig{ + Config: config.Config{ ExecutorImage: "executor:latest", DefautWorkflowSpec: &wfv1.WorkflowSpec{ HostNetwork: &myBool, diff --git a/workflow/controller/operator.go b/workflow/controller/operator.go index 34a0dd77ef3c..b7cbebb4496d 100644 --- a/workflow/controller/operator.go +++ b/workflow/controller/operator.go @@ -29,6 +29,7 @@ import ( "k8s.io/utils/pointer" "sigs.k8s.io/yaml" + "github.com/argoproj/argo/config" "github.com/argoproj/argo/errors" "github.com/argoproj/argo/pkg/apis/workflow" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" @@ -37,7 +38,6 @@ import ( "github.com/argoproj/argo/util/resource" "github.com/argoproj/argo/util/retry" "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" "github.com/argoproj/argo/workflow/metrics" "github.com/argoproj/argo/workflow/packer" "github.com/argoproj/argo/workflow/templateresolution" diff --git a/workflow/controller/operator_test.go b/workflow/controller/operator_test.go index 5f726adbf388..70a2a063de23 100644 --- a/workflow/controller/operator_test.go +++ b/workflow/controller/operator_test.go @@ -13,10 +13,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" + "github.com/argoproj/argo/config" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" "github.com/argoproj/argo/test" "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" "github.com/argoproj/argo/workflow/util" ) diff --git a/workflow/controller/workflowpod_test.go b/workflow/controller/workflowpod_test.go index a78e8a074ea4..c5a88e61795c 100644 --- a/workflow/controller/workflowpod_test.go +++ b/workflow/controller/workflowpod_test.go @@ -12,10 +12,10 @@ import ( "k8s.io/utils/pointer" "sigs.k8s.io/yaml" + "github.com/argoproj/argo/config" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" "github.com/argoproj/argo/test/util" "github.com/argoproj/argo/workflow/common" - "github.com/argoproj/argo/workflow/config" ) func unmarshalTemplate(yamlStr string) *wfv1.Template { diff --git a/workflow/metrics/server.go b/workflow/metrics/server.go index a9d543ee964a..23fbc77a6061 100644 --- a/workflow/metrics/server.go +++ b/workflow/metrics/server.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "github.com/argoproj/argo/workflow/config" + "github.com/argoproj/argo/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp"