Skip to content

Commit

Permalink
feat(config): Make configuration mangement easier. Closes argoproj#2463
Browse files Browse the repository at this point in the history
  • Loading branch information
alexec committed Mar 23, 2020
1 parent f3df966 commit 33cd4f2
Show file tree
Hide file tree
Showing 43 changed files with 751 additions and 1,018 deletions.
28 changes: 10 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
14 changes: 0 additions & 14 deletions cmd/workflow-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions workflow/config/config.go → config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
File renamed without changes.
122 changes: 122 additions & 0 deletions config/controller.go
Original file line number Diff line number Diff line change
@@ -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)
}
42 changes: 42 additions & 0 deletions config/controller_test.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
3 changes: 1 addition & 2 deletions docs/configure-artifact-repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 33cd4f2

Please sign in to comment.