Implement api server installer (#15)

This commit is contained in:
Alexander Matyushentsev 2018-02-28 20:48:43 -08:00 committed by GitHub
parent 7009c133f4
commit 336b0775fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 21 deletions

View file

@ -14,9 +14,10 @@ import (
// NewCommand returns a new instance of an argocd command
func NewCommand() *cobra.Command {
var (
logLevel string
configMap string
kubeConfig string
logLevel string
configMap string
kubeConfig string
staticAssetsDir string
)
var command = &cobra.Command{
Use: cliName,
@ -32,12 +33,13 @@ func NewCommand() *cobra.Command {
kubeclientset := kubernetes.NewForConfigOrDie(config)
appclientset := appclientset.NewForConfigOrDie(config)
argocd := server.NewServer(kubeclientset, appclientset)
argocd := server.NewServer(kubeclientset, appclientset, staticAssetsDir)
argocd.Run()
},
}
command.Flags().StringVar(&kubeConfig, "kubeconfig", "", "Kubernetes config (used when running outside of cluster)")
command.Flags().StringVar(&staticAssetsDir, "staticassets", "", "Static assets directory path")
command.Flags().StringVar(&configMap, "configmap", defaultArgoCDConfigMap, "Name of K8s configmap to retrieve argocd configuration")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.AddCommand(cli.NewVersionCmd(cliName))

View file

@ -19,6 +19,8 @@ var (
// These are the default image names which `argo install` uses during install
DefaultControllerImage = imageNamespace + "/argocd-application-controller:" + imageTag
DefaultUiImage = imageNamespace + "/argocd-ui:" + imageTag
DefaultServerImage = imageNamespace + "/argocd-server:" + imageTag
)
// NewInstallCommand returns a new instance of `argocd install` command
@ -45,6 +47,9 @@ func NewInstallCommand() *cobra.Command {
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.ServerName, "server-name", common.DefaultServerDeploymentName, "name of api server deployment")
command.Flags().StringVar(&installParams.ServerImage, "server-image", DefaultServerImage, "use a specified api server image")
command.Flags().StringVar(&installParams.UiImage, "ui-image", DefaultUiImage, "use a specified ui image")
command.Flags().StringVar(&installParams.ServiceAccount, "service-account", "", "use a specified service account for the workflow-controller deployment")
clientConfig = addKubectlFlagsToCmd(command)
return command

View file

@ -16,6 +16,9 @@ const (
// DefaultControllerDeploymentName is the default deployment name of the application controller
DefaultControllerDeploymentName = "application-controller"
// DefaultServerDeploymentName is the default deployment name of the api server
DefaultServerDeploymentName = "argocd-server"
// DefaultControllerNamespace is the default namespace where the application controller is installed
DefaultControllerNamespace = "kube-system"
)

View file

@ -22,6 +22,10 @@ import (
"k8s.io/client-go/rest"
)
const (
StaticFilesVolumeName = "static-files"
)
// InstallParameters has all the required parameters for installing ArgoCD.
type InstallParameters struct {
Upgrade bool
@ -29,8 +33,11 @@ type InstallParameters struct {
Namespace string
ControllerName string
ControllerImage string
ServerName string
UiImage string
ServerImage string
ServiceAccount string
SkipController bool
CrdOnly bool
}
// Installer allows to install ArgoCD resources.
@ -42,8 +49,9 @@ type Installer struct {
// Install performs installation
func (installer *Installer) Install(parameters InstallParameters) {
installer.installAppCRD(parameters.DryRun)
if !parameters.SkipController {
if !parameters.CrdOnly {
installer.installController(parameters)
installer.installServer(parameters)
}
}
@ -143,9 +151,10 @@ func (installer *Installer) installController(args InstallParameters) {
ServiceAccountName: args.ServiceAccount,
Containers: []apiv1.Container{
{
Name: args.ControllerName,
Image: args.ControllerImage,
Command: []string{"argocd-application-controller"},
Name: args.ControllerName,
Image: args.ControllerImage,
ImagePullPolicy: apiv1.PullIfNotPresent,
Command: []string{"/argocd-application-controller"},
},
},
},
@ -155,6 +164,71 @@ func (installer *Installer) installController(args InstallParameters) {
installer.createDeploymentHelper(&controllerDeployment, args)
}
func (installer *Installer) installServer(args InstallParameters) {
serverDeployment := appsv1beta2.Deployment{
TypeMeta: metav1.TypeMeta{
APIVersion: "apps/v1beta2",
Kind: "Deployment",
},
ObjectMeta: metav1.ObjectMeta{
Name: args.ServerName,
Namespace: args.Namespace,
},
Spec: appsv1beta2.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": args.ServerName,
},
},
Template: apiv1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": args.ServerName,
},
},
Spec: apiv1.PodSpec{
ServiceAccountName: args.ServiceAccount,
Containers: []apiv1.Container{
{
Name: args.ServerName,
Image: args.ServerImage,
Command: []string{"/argocd-server", "--staticassets", "/shared/app"},
ImagePullPolicy: apiv1.PullIfNotPresent,
VolumeMounts: []apiv1.VolumeMount{
{
Name: StaticFilesVolumeName,
MountPath: "/shared",
},
},
},
{
Name: args.ServerName + "-ui",
Image: args.UiImage,
ImagePullPolicy: apiv1.PullIfNotPresent,
Command: []string{"sh", "-c", "cp -r /app /shared && tail -f /dev/null"},
VolumeMounts: []apiv1.VolumeMount{
{
Name: StaticFilesVolumeName,
MountPath: "/shared",
},
},
},
},
Volumes: []apiv1.Volume{
{
Name: StaticFilesVolumeName,
VolumeSource: apiv1.VolumeSource{
EmptyDir: &apiv1.EmptyDirVolumeSource{},
},
},
},
},
},
},
}
installer.createDeploymentHelper(&serverDeployment, args)
}
// createDeploymentHelper is helper to create or update an existing deployment (if --upgrade was supplied)
func (installer *Installer) createDeploymentHelper(deployment *appsv1beta2.Deployment, args InstallParameters) {
depClient := installer.clientset.AppsV1beta2().Deployments(args.Namespace)

View file

@ -6,6 +6,8 @@ import (
"net"
"net/http"
"strings"
argocd "github.com/argoproj/argo-cd"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/server/application"
@ -33,19 +35,21 @@ var (
// ArgoCDServer is the API server for ArgoCD
type ArgoCDServer struct {
ns string
kubeclientset kubernetes.Interface
appclientset appclientset.Interface
log *log.Entry
ns string
staticAssetsDir string
kubeclientset kubernetes.Interface
appclientset appclientset.Interface
log *log.Entry
}
// NewServer returns a new instance of the ArgoCD API server
func NewServer(kubeclientset kubernetes.Interface, appclientset appclientset.Interface) *ArgoCDServer {
func NewServer(kubeclientset kubernetes.Interface, appclientset appclientset.Interface, staticAssetsDir string) *ArgoCDServer {
return &ArgoCDServer{
ns: "default",
kubeclientset: kubeclientset,
appclientset: appclientset,
log: log.NewEntry(log.New()),
ns: "default",
kubeclientset: kubeclientset,
appclientset: appclientset,
log: log.NewEntry(log.New()),
staticAssetsDir: staticAssetsDir,
}
}
@ -94,12 +98,33 @@ func (a *ArgoCDServer) Run() {
// we use our own Marshaler
gwMuxOpts := runtime.WithMarshalerOption(runtime.MIMEWildcard, new(jsonutil.JSONMarshaler))
gwmux := runtime.NewServeMux(gwMuxOpts)
mux.Handle("/", gwmux)
mux.Handle("/api/", gwmux)
dOpts := []grpc.DialOption{grpc.WithInsecure()}
mustRegisterGWHandler(version.RegisterVersionServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
mustRegisterGWHandler(cluster.RegisterClusterServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
mustRegisterGWHandler(application.RegisterApplicationServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
mustRegisterGWHandler(repository.RegisterRepositoryServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
if a.staticAssetsDir != "" {
mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
acceptHtml := false
for _, acceptType := range strings.Split(request.Header.Get("Accept"), ",") {
if acceptType == "text/html" || acceptType == "html" {
acceptHtml = true
break
}
}
fileRequest := request.URL.Path != "/index.html" && strings.Contains(request.URL.Path, ".")
// serve index.html for non file requests to support HTML5 History API
if acceptHtml && !fileRequest && (request.Method == "GET" || request.Method == "HEAD") {
http.ServeFile(writer, request, a.staticAssetsDir+"/index.html")
} else {
http.ServeFile(writer, request, a.staticAssetsDir+request.URL.Path)
}
})
}
httpS := &http.Server{
Addr: endpoint,
Handler: mux,

View file

@ -52,8 +52,8 @@ func createNamespace(kubeClient *kubernetes.Clientset) (string, error) {
func (f *Fixture) setup() error {
common.NewInstaller(f.ExtensionsClient, f.KubeClient).Install(common.InstallParameters{
DryRun: false,
SkipController: true,
DryRun: false,
CrdOnly: true,
})
return nil
}