mirror of https://github.com/linkerd/linkerd2.git
150 lines
5.4 KiB
Go
150 lines
5.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"regexp"
|
|
"text/template"
|
|
|
|
"github.com/runconduit/conduit/cli/install"
|
|
"github.com/runconduit/conduit/pkg/k8s"
|
|
uuid "github.com/satori/go.uuid"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
type installConfig struct {
|
|
Namespace string
|
|
ControllerImage string
|
|
WebImage string
|
|
PrometheusImage string
|
|
GrafanaImage string
|
|
ControllerReplicas uint
|
|
WebReplicas uint
|
|
PrometheusReplicas uint
|
|
ImagePullPolicy string
|
|
UUID string
|
|
CliVersion string
|
|
ControllerLogLevel string
|
|
ControllerComponentLabel string
|
|
CreatedByAnnotation string
|
|
ProxyAPIPort uint
|
|
EnableTLS bool
|
|
}
|
|
|
|
type installOptions struct {
|
|
dockerRegistry string
|
|
controllerReplicas uint
|
|
webReplicas uint
|
|
prometheusReplicas uint
|
|
controllerLogLevel string
|
|
enableTLS bool
|
|
*proxyConfigOptions
|
|
}
|
|
|
|
func newInstallOptions() *installOptions {
|
|
return &installOptions{
|
|
dockerRegistry: "gcr.io/runconduit",
|
|
controllerReplicas: 1,
|
|
webReplicas: 1,
|
|
prometheusReplicas: 1,
|
|
controllerLogLevel: "info",
|
|
enableTLS: false,
|
|
proxyConfigOptions: newProxyConfigOptions(),
|
|
}
|
|
}
|
|
|
|
func newCmdInstall() *cobra.Command {
|
|
options := newInstallOptions()
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "install [flags]",
|
|
Short: "Output Kubernetes configs to install Conduit",
|
|
Long: "Output Kubernetes configs to install Conduit.",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config, err := validateAndBuildConfig(options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return render(*config, os.Stdout, options)
|
|
},
|
|
}
|
|
|
|
addProxyConfigFlags(cmd, options.proxyConfigOptions)
|
|
cmd.PersistentFlags().StringVar(&options.dockerRegistry, "registry", options.dockerRegistry, "Docker registry to pull images from")
|
|
cmd.PersistentFlags().UintVar(&options.controllerReplicas, "controller-replicas", options.controllerReplicas, "Replicas of the controller to deploy")
|
|
cmd.PersistentFlags().UintVar(&options.webReplicas, "web-replicas", options.webReplicas, "Replicas of the web server to deploy")
|
|
cmd.PersistentFlags().UintVar(&options.prometheusReplicas, "prometheus-replicas", options.prometheusReplicas, "Replicas of prometheus to deploy")
|
|
cmd.PersistentFlags().StringVar(&options.controllerLogLevel, "controller-log-level", options.controllerLogLevel, "Log level for the controller and web components")
|
|
cmd.PersistentFlags().BoolVar(&options.enableTLS, "enable-tls", options.enableTLS, "Enable TLS connections among pods in the service mesh")
|
|
cmd.PersistentFlags().MarkHidden("enable-tls")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func validateAndBuildConfig(options *installOptions) (*installConfig, error) {
|
|
if err := validate(options); err != nil {
|
|
return nil, err
|
|
}
|
|
return &installConfig{
|
|
Namespace: controlPlaneNamespace,
|
|
ControllerImage: fmt.Sprintf("%s/controller:%s", options.dockerRegistry, options.conduitVersion),
|
|
WebImage: fmt.Sprintf("%s/web:%s", options.dockerRegistry, options.conduitVersion),
|
|
PrometheusImage: "prom/prometheus:v2.2.1",
|
|
GrafanaImage: fmt.Sprintf("%s/grafana:%s", options.dockerRegistry, options.conduitVersion),
|
|
ControllerReplicas: options.controllerReplicas,
|
|
WebReplicas: options.webReplicas,
|
|
PrometheusReplicas: options.prometheusReplicas,
|
|
ImagePullPolicy: options.imagePullPolicy,
|
|
UUID: uuid.NewV4().String(),
|
|
CliVersion: k8s.CreatedByAnnotationValue(),
|
|
ControllerLogLevel: options.controllerLogLevel,
|
|
ControllerComponentLabel: k8s.ControllerComponentLabel,
|
|
CreatedByAnnotation: k8s.CreatedByAnnotation,
|
|
ProxyAPIPort: options.proxyAPIPort,
|
|
EnableTLS: options.enableTLS,
|
|
}, nil
|
|
}
|
|
|
|
func render(config installConfig, w io.Writer, options *installOptions) error {
|
|
template, err := template.New("conduit").Parse(install.Template)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf := &bytes.Buffer{}
|
|
err = template.Execute(buf, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
injectOptions := newInjectOptions()
|
|
injectOptions.proxyConfigOptions = options.proxyConfigOptions
|
|
return InjectYAML(buf, w, injectOptions)
|
|
}
|
|
|
|
var alphaNumDash = regexp.MustCompile("^[a-zA-Z0-9-]+$")
|
|
var alphaNumDashDot = regexp.MustCompile("^[\\.a-zA-Z0-9-]+$")
|
|
var alphaNumDashDotSlash = regexp.MustCompile("^[\\./a-zA-Z0-9-]+$")
|
|
|
|
func validate(options *installOptions) error {
|
|
// These regexs are not as strict as they could be, but are a quick and dirty
|
|
// sanity check against illegal characters.
|
|
if !alphaNumDash.MatchString(controlPlaneNamespace) {
|
|
return fmt.Errorf("%s is not a valid namespace", controlPlaneNamespace)
|
|
}
|
|
if !alphaNumDashDot.MatchString(options.conduitVersion) {
|
|
return fmt.Errorf("%s is not a valid version", options.conduitVersion)
|
|
}
|
|
if !alphaNumDashDotSlash.MatchString(options.dockerRegistry) {
|
|
return fmt.Errorf("%s is not a valid Docker registry", options.dockerRegistry)
|
|
}
|
|
if options.imagePullPolicy != "Always" && options.imagePullPolicy != "IfNotPresent" && options.imagePullPolicy != "Never" {
|
|
return fmt.Errorf("--image-pull-policy must be one of: Always, IfNotPresent, Never")
|
|
}
|
|
if _, err := log.ParseLevel(options.controllerLogLevel); err != nil {
|
|
return fmt.Errorf("--controller-log-level must be one of: panic, fatal, error, warn, info, debug")
|
|
}
|
|
return nil
|
|
}
|