Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2fab5b7
Clone repositor to new config service
Mar 19, 2018
de6acdb
Update configmap files
Mar 19, 2018
ee751c2
Update configmap
Mar 19, 2018
f7066f6
Don't make a service for this
Mar 19, 2018
3a25184
Add config map command-line flag
Mar 19, 2018
467205a
Add config map install step
Mar 19, 2018
63076f2
Add new secrets file
Mar 19, 2018
adb8a2d
Update secret retrieval
Mar 20, 2018
c278f49
Flesh out secret retrieval API
Mar 20, 2018
0e975ca
Update secret.go
Mar 20, 2018
d76096d
Create configmap/secret manipulation tools
Mar 20, 2018
2a8ead9
Slight tweaks to logic in util functions
Mar 20, 2018
95055b8
Add test for configmap code
Mar 20, 2018
c0bd7b9
Update configmap/secret tests and code
Mar 20, 2018
b9f54da
Update installation settings
Mar 20, 2018
b208bbf
Revert secret type field
Mar 20, 2018
a54a8ab
Fix subfield access
Mar 20, 2018
449ab9e
Update container command
Mar 20, 2018
ac0266d
Rm unnecessary newline
Mar 20, 2018
f306958
Quote configmap parameter
Mar 20, 2018
0a8b117
Update printouts from tests
Mar 20, 2018
5fa2f23
Rm unnecessary suffixes from util functions
Mar 20, 2018
bc535f4
Update comments to match method names
Mar 20, 2018
50a4bd1
Rm secret/configmap code for now
Mar 21, 2018
b2ad562
Rm spurious newline
Mar 21, 2018
d6112b0
Add config-map argument to argocd-server
Mar 21, 2018
037af32
Use Containers, not InitContainers, thanks @alexmt
Mar 21, 2018
26de1e7
Reintroduce config map reading
Mar 21, 2018
8e8ce2e
Rename wrapper into ConfigManager
Mar 21, 2018
83e4992
Rename configmap => configmanager
Mar 21, 2018
c4c1c14
Break ConfigManager invocation into two lines
Mar 21, 2018
922cd10
Privatize Clientset field
Mar 21, 2018
417fbc3
Support Listing config maps
Mar 21, 2018
fcae9e6
Simplify client manager instantiation
Mar 21, 2018
409e6ce
Update settings config
Mar 21, 2018
f4e2fa8
Add Secret management to ConfigManager
Mar 21, 2018
eb46fab
Address scoping concerns
Mar 22, 2018
c739946
Refactor config manager, thanks @alexmt
Mar 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/argocd-server/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func NewCommand() *cobra.Command {
clientConfig clientcmd.ClientConfig
staticAssetsDir string
repoServerAddress string
configMapName string
)
var command = &cobra.Command{
Use: cliName,
Expand All @@ -39,7 +40,7 @@ func NewCommand() *cobra.Command {
appclientset := appclientset.NewForConfigOrDie(config)
repoclientset := reposerver.NewRepositoryServerClientset(repoServerAddress)

argocd := server.NewServer(kubeclientset, appclientset, repoclientset, namespace, staticAssetsDir)
argocd := server.NewServer(kubeclientset, appclientset, repoclientset, namespace, staticAssetsDir, configMapName)
argocd.Run()
},
}
Expand All @@ -48,6 +49,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringVar(&staticAssetsDir, "staticassets", "", "Static assets directory path")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().StringVar(&repoServerAddress, "repo-server", "localhost:8081", "Repo server address.")
command.Flags().StringVar(&configMapName, "config-map", "", "Name of a Kubernetes config map to use.")
command.AddCommand(cli.NewVersionCmd(cliName))
return command
}
1 change: 1 addition & 0 deletions cmd/argocd/commands/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewInstallCommand() *cobra.Command {
}
command.Flags().BoolVar(&installOpts.Upgrade, "upgrade", false, "upgrade controller/ui deployments and configmap if already installed")
command.Flags().BoolVar(&installOpts.DryRun, "dry-run", false, "print the kubernetes manifests to stdout instead of installing")
command.Flags().StringVar(&installOpts.ConfigMap, "config-map", "", "apply settings from a Kubernetes config map")
command.Flags().StringVar(&installOpts.Namespace, "install-namespace", install.DefaultInstallNamespace, "install into a specific namespace")
command.Flags().StringVar(&installOpts.ControllerImage, "controller-image", install.DefaultControllerImage, "use a specified controller image")
command.Flags().StringVar(&installOpts.ServerImage, "server-image", install.DefaultServerImage, "use a specified api server image")
Expand Down
9 changes: 9 additions & 0 deletions install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package install
import (
"fmt"
"log"
"strconv"
"strings"

"github.com/argoproj/argo-cd/errors"
Expand Down Expand Up @@ -37,9 +38,11 @@ var (
DefaultRepoServerImage = imageNamespace + "/argocd-repo-server:" + imageTag
)

// InstallOptions stores a collection of installation settings.
type InstallOptions struct {
DryRun bool
Upgrade bool
ConfigMap string
Namespace string
ControllerImage string
UIImage string
Expand Down Expand Up @@ -150,6 +153,12 @@ func (i *Installer) InstallArgoCDServer() {
argoCDServerControllerDeployment.Spec.Template.Spec.InitContainers[0].ImagePullPolicy = apiv1.PullPolicy(i.ImagePullPolicy)
argoCDServerControllerDeployment.Spec.Template.Spec.Containers[0].Image = i.ServerImage
argoCDServerControllerDeployment.Spec.Template.Spec.Containers[0].ImagePullPolicy = apiv1.PullPolicy(i.ImagePullPolicy)
// Use a Kubernetes ConfigMap, if provided.
if i.InstallOptions.ConfigMap != "" {
configMap := strconv.Quote(i.InstallOptions.ConfigMap)
container := &argoCDServerControllerDeployment.Spec.Template.Spec.Containers[0]
container.Command = append(container.Command, "--config-map", configMap)
}
i.MustInstallResource(kube.MustToUnstructured(&argoCDServerServiceAccount))
i.MustInstallResource(kube.MustToUnstructured(&argoCDServerControllerRole))
i.MustInstallResource(kube.MustToUnstructured(&argoCDServerControllerRoleBinding))
Expand Down
30 changes: 29 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/argoproj/argo-cd/server/cluster"
"github.com/argoproj/argo-cd/server/repository"
"github.com/argoproj/argo-cd/server/version"
"github.com/argoproj/argo-cd/util"
grpc_util "github.com/argoproj/argo-cd/util/grpc"
jsonutil "github.com/argoproj/argo-cd/util/json"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
Expand All @@ -23,6 +24,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/soheilhy/cmux"
"google.golang.org/grpc"
apiv1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)

Expand All @@ -34,26 +36,52 @@ var (
endpoint = fmt.Sprintf("localhost:%d", port)
)

// ArgoCDServerSettings holds in-memory runtime configuration options.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed we will need to add more hardcoded parameters into settings structure (e.g. app resync timeout). These parameters are not specific to argocd server, so I would suggest to move settings struct definition into util package next to config manager

type ArgoCDServerSettings struct {
AdminPasswordSecretName string
}

func makeSettingsFromConfigMap(configMap *apiv1.ConfigMap) (settings ArgoCDServerSettings) {
const adminPasswordKeyName = "adminPasswordSecretName"
adminPasswordSecretName, ok := configMap.Data[adminPasswordKeyName]
if ok {
settings.AdminPasswordSecretName = adminPasswordSecretName
}
return
}

// ArgoCDServer is the API server for ArgoCD
type ArgoCDServer struct {
ns string
staticAssetsDir string
kubeclientset kubernetes.Interface
appclientset appclientset.Interface
repoclientset reposerver.Clientset
settings ArgoCDServerSettings
log *log.Entry
}

// NewServer returns a new instance of the ArgoCD API server
func NewServer(
kubeclientset kubernetes.Interface, appclientset appclientset.Interface, repoclientset reposerver.Clientset, namespace string, staticAssetsDir string) *ArgoCDServer {
kubeclientset kubernetes.Interface, appclientset appclientset.Interface, repoclientset reposerver.Clientset, namespace, staticAssetsDir, configMapName string) *ArgoCDServer {
var settings ArgoCDServerSettings
if configMapName != "" {
configManager := util.NewConfigManager(kubeclientset)
configMap, err := configManager.ReadConfigMap("default", configMapName)
if err != nil {
log.Warnf("Could not read config map with name \"%s\"; proceeding with default settings. Error: %v", configMapName, err)
} else {
settings = makeSettingsFromConfigMap(configMap)
}
}
return &ArgoCDServer{
ns: namespace,
kubeclientset: kubeclientset,
appclientset: appclientset,
repoclientset: repoclientset,
log: log.NewEntry(log.New()),
staticAssetsDir: staticAssetsDir,
settings: settings,
}
}

Expand Down
105 changes: 105 additions & 0 deletions util/configmanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package util

import (
"github.com/argoproj/argo-cd/common"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

apiv1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)

// ConfigManager holds config info for a new manager with which to access Kubernetes ConfigMaps.
type ConfigManager struct {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now argocd only need to read settings from config map and referenced secrets. We don't have use for create/update methods. I think ConfigManager should be responsible to deserialize Argo CD settings structure from config/secrets. E.g. now it needs only one public method GetSettings which encapsulate settings deserialization:

type ConfigManager struct {
   clientset kubernetes.Interface
   configMapName string
}

func (mgr *ConfigManager) GetSettings() ArgoCDSettigns {
   ....
}

clientset kubernetes.Interface
}

// NewConfigManager generates a new ConfigManager pointer and returns it
func NewConfigManager(clientset kubernetes.Interface) (mgr *ConfigManager) {
mgr = &ConfigManager{clientset}
return
}

// ListConfigMaps returns a list of existing config maps.
func (mgr *ConfigManager) ListConfigMaps(namespace string) (configMaps *apiv1.ConfigMapList, err error) {
configMaps, err = mgr.clientset.CoreV1().ConfigMaps(namespace).List(metav1.ListOptions{})
return
}

// CreateConfigMap stores a new config map in Kubernetes.
func (mgr *ConfigManager) CreateConfigMap(namespace, name string, value map[string]string) (configMap *apiv1.ConfigMap, err error) {
newConfigMap := &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: value,
}
configMap, err = mgr.clientset.CoreV1().ConfigMaps(namespace).Create(newConfigMap)
return
}

// ReadConfigMap retrieves a config map from Kubernetes.
func (mgr *ConfigManager) ReadConfigMap(namespace, name string) (configMap *apiv1.ConfigMap, err error) {
configMap, err = mgr.clientset.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
return
}

// UpdateConfigMap overwrite-updates an existing config map in Kubernetes. This overwrite is in contrast to the merge-update done for secrets.
func (mgr *ConfigManager) UpdateConfigMap(namespace, name string, value map[string]string) (configMap *apiv1.ConfigMap, err error) {
existingConfigMap, err := mgr.ReadConfigMap(namespace, name)
if err == nil {
existingConfigMap.Data = value
configMap, err = mgr.clientset.CoreV1().ConfigMaps(namespace).Update(existingConfigMap)
}
return
}

// DeleteConfigMap removes a config map from Kubernetes.
func (mgr *ConfigManager) DeleteConfigMap(namespace, name string) (err error) {
err = mgr.clientset.CoreV1().ConfigMaps(namespace).Delete(name, &metav1.DeleteOptions{})
return
}

// ListSecrets returns a list of existing config maps.
func (mgr *ConfigManager) ListSecrets(namespace string) (secrets *apiv1.SecretList, err error) {
secrets, err = mgr.clientset.CoreV1().Secrets(namespace).List(metav1.ListOptions{})
return
}

// CreateSecret stores a new secret in Kubernetes. Set secretType to "" for no label.
func (mgr *ConfigManager) CreateSecret(namespace, name string, value map[string]string, secretType string) (secret *apiv1.Secret, err error) {
labels := make(map[string]string)
if secretType != "" {
labels[common.LabelKeySecretType] = secretType
}
newSecret := &apiv1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
},
}
newSecret.StringData = value
secret, err = mgr.clientset.CoreV1().Secrets(namespace).Create(newSecret)
return
}

// Read retrieves a secret from Kubernetes.
func (mgr *ConfigManager) ReadSecret(namespace, name string) (secret *apiv1.Secret, err error) {
secret, err = mgr.clientset.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{})
return
}

// UpdateSecret merge-updates an existing secret in Kubernetes. This merge-update is in contrast to the overwrite-update done for config maps.
func (mgr *ConfigManager) UpdateSecret(namespace, name string, value map[string]string) (secret *apiv1.Secret, err error) {
existingSecret, err := mgr.ReadSecret(namespace, name)
if err == nil {
existingSecret.StringData = value
secret, err = mgr.clientset.CoreV1().Secrets(namespace).Update(existingSecret)
}
return
}

// DeleteSecret removes a secret from Kubernetes.
func (mgr *ConfigManager) DeleteSecret(namespace, name string) (err error) {
err = mgr.clientset.CoreV1().Secrets(namespace).Delete(name, &metav1.DeleteOptions{})
return
}
Loading