Skip to content

Commit

Permalink
Implement application controller installer (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmt committed Feb 23, 2018
1 parent f4a854d commit af83297
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 133 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ controller:

.PHONY: controller-image
controller-image:
docker build --build-arg BINARY=argocd-application-controller --build-arg MAKE_TARGET=controller -t $(IMAGE_PREFIX)argocd-controller:$(IMAGE_TAG) -f Dockerfile-argocd .
@if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argocd-controller:$(IMAGE_TAG) ; fi
docker build --build-arg BINARY=argocd-application-controller --build-arg MAKE_TARGET=controller -t $(IMAGE_PREFIX)argocd-application-controller:$(IMAGE_TAG) -f Dockerfile-argocd .
@if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argocd-application-controller:$(IMAGE_TAG) ; fi

.PHONY: lint
lint:
Expand Down
18 changes: 0 additions & 18 deletions cmd/argocd/commands/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"log"
"os"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
Expand All @@ -13,13 +12,6 @@ const (
cliName = "argocd"
)

var (
// Parts of the image for installation
// These values may be overridden by the link flags during build
//imageNamespace = "argoproj"
//imageTag = "latest"
)

// GetKubeConfig creates new kubernetes client config using specified config path and config overrides variables
func GetKubeConfig(configPath string, overrides clientcmd.ConfigOverrides) *rest.Config {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
Expand All @@ -33,13 +25,3 @@ func GetKubeConfig(configPath string, overrides clientcmd.ConfigOverrides) *rest
}
return restConfig
}

// GetKubeClient creates new kubernetes client using specified config path and config overrides variables
func GetKubeClient(configPath string, overrides clientcmd.ConfigOverrides) *kubernetes.Clientset {
restConfig := GetKubeConfig(configPath, overrides)
clientset, err := kubernetes.NewForConfig(restConfig)
if err != nil {
log.Fatal(err)
}
return clientset
}
135 changes: 22 additions & 113 deletions cmd/argocd/commands/install.go
Original file line number Diff line number Diff line change
@@ -1,135 +1,44 @@
package commands

import (
"fmt"
"time"

"github.com/argoproj/argo-cd/pkg/apis/application"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/common"
"github.com/spf13/cobra"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)

// InstallFlags has all the required parameters for installing Argo CD.
type InstallFlags struct {
DryRun bool // --dry-run
}
var (
// These values may be overridden by the link flags during build
// (e.g. imageTag will use the official release tag on tagged builds)
imageNamespace = "argoproj"
imageTag = "latest"

// These are the default image names which `argo install` uses during install
DefaultControllerImage = imageNamespace + "/argocd-application-controller:" + imageTag
)

// NewInstallCommand returns a new instance of `argocd install` command
func NewInstallCommand(globalArgs *globalFlags) *cobra.Command {
var (
installArgs InstallFlags
installParams common.InstallParameters
)
var command = &cobra.Command{
Use: "install",
Short: "Install the argocd components",
Long: "Install the argocd components",
Run: func(c *cobra.Command, args []string) {
extensionsClient := apiextensionsclient.NewForConfigOrDie(GetKubeConfig(globalArgs.kubeConfigPath, globalArgs.kubeConfigOverrides))
installAppCRD(extensionsClient, installArgs)
installClusterCRD(extensionsClient, installArgs)
conf := GetKubeConfig(globalArgs.kubeConfigPath, globalArgs.kubeConfigOverrides)
extensionsClient := apiextensionsclient.NewForConfigOrDie(conf)
kubeClient := kubernetes.NewForConfigOrDie(conf)
common.NewInstaller(extensionsClient, kubeClient).Install(installParams)
},
}
command.Flags().BoolVar(&installArgs.DryRun, "dry-run", false, "print the kubernetes manifests to stdout instead of installing")
command.Flags().BoolVar(&installParams.Upgrade, "upgrade", false, "upgrade controller/ui deployments and configmap if already installed")
command.Flags().BoolVar(&installParams.DryRun, "dry-run", false, "print the kubernetes manifests to stdout instead of installing")
command.Flags().StringVar(&installParams.Namespace, "install-namespace", common.DefaultControllerNamespace, "install into a specific Namespace")
command.Flags().StringVar(&installParams.ControllerName, "controller-name", common.DefaultControllerDeploymentName, "name of controller deployment")
command.Flags().StringVar(&installParams.ControllerImage, "controller-image", DefaultControllerImage, "use a specified controller image")
command.Flags().StringVar(&installParams.ServiceAccount, "service-account", "", "use a specified service account for the workflow-controller deployment")

return command
}

func installAppCRD(extensionsClient *apiextensionsclient.Clientset, args InstallFlags) {
applicationCRD := apiextensionsv1beta1.CustomResourceDefinition{
TypeMeta: metav1.TypeMeta{
APIVersion: "apiextensions.k8s.io/v1alpha1",
Kind: "CustomResourceDefinition",
},
ObjectMeta: metav1.ObjectMeta{
Name: application.ApplicationFullName,
},
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
Group: application.Group,
Version: appv1.SchemeGroupVersion.Version,
Scope: apiextensionsv1beta1.NamespaceScoped,
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
Plural: application.ApplicationPlural,
Kind: application.ApplicationKind,
ShortNames: []string{application.ApplicationShortName},
},
},
}
createCRDHelper(extensionsClient, &applicationCRD, args.DryRun)
}

func installClusterCRD(extensionsClient *apiextensionsclient.Clientset, args InstallFlags) {
clusterCRD := apiextensionsv1beta1.CustomResourceDefinition{
TypeMeta: metav1.TypeMeta{
APIVersion: "apiextensions.k8s.io/v1alpha1",
Kind: "CustomResourceDefinition",
},
ObjectMeta: metav1.ObjectMeta{
Name: application.ClusterFullName,
},
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
Group: application.Group,
Version: appv1.SchemeGroupVersion.Version,
Scope: apiextensionsv1beta1.NamespaceScoped,
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
Plural: application.ClusterPlural,
Kind: application.ClusterKind,
ShortNames: []string{application.ClusterShortName},
},
},
}
createCRDHelper(extensionsClient, &clusterCRD, args.DryRun)
}

func createCRDHelper(extensionsClient *apiextensionsclient.Clientset, crd *apiextensionsv1beta1.CustomResourceDefinition, dryRun bool) {
if dryRun {
printYAML(crd)
return
}
_, err := extensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)
if err != nil {
if !apierr.IsAlreadyExists(err) {
log.Fatalf("Failed to create CustomResourceDefinition: %v", err)
}
fmt.Printf("CustomResourceDefinition '%s' already exists\n", crd.ObjectMeta.Name)
} else {
fmt.Printf("CustomResourceDefinition '%s' created", crd.ObjectMeta.Name)
}
// wait for CRD being established
err = wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) {
getCrd, err := extensionsClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.ObjectMeta.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
for _, cond := range getCrd.Status.Conditions {
switch cond.Type {
case apiextensionsv1beta1.Established:
if cond.Status == apiextensionsv1beta1.ConditionTrue {
return true, err
}
case apiextensionsv1beta1.NamesAccepted:
if cond.Status == apiextensionsv1beta1.ConditionFalse {
log.Errorf("Name conflict: %v", cond.Reason)
}
}
}
return false, err
})
if err != nil {
log.Fatalf("Failed to wait for CustomResourceDefinition: %v", err)
}
}

func printYAML(obj interface{}) {
objBytes, err := yaml.Marshal(obj)
if err != nil {
log.Fatalf("Failed to marshal %v", obj)
}
fmt.Printf("---\n%s\n", string(objBytes))
}
4 changes: 4 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const (

// SecretTypeRepository indicates the data type which argocd stores as a k8s secret
SecretTypeRepository = "repository"
// DefaultControllerDeploymentName is the default deployment name of the applicaiton controller
DefaultControllerDeploymentName = "application-controller"
// DefaultControllerNamespace is the default namespace where the applicaiton controller is installed
DefaultControllerNamespace = "kube-system"
)

var (
Expand Down
Loading

0 comments on commit af83297

Please sign in to comment.