...

Source file src/github.com/linkerd/linkerd2/jaeger/cmd/install.go

Documentation: github.com/linkerd/linkerd2/jaeger/cmd

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path"
     9  	"time"
    10  
    11  	"github.com/linkerd/linkerd2/jaeger/static"
    12  	"github.com/linkerd/linkerd2/pkg/charts"
    13  	partials "github.com/linkerd/linkerd2/pkg/charts/static"
    14  	pkgcmd "github.com/linkerd/linkerd2/pkg/cmd"
    15  	"github.com/linkerd/linkerd2/pkg/flags"
    16  	"github.com/linkerd/linkerd2/pkg/healthcheck"
    17  	"github.com/spf13/cobra"
    18  	"helm.sh/helm/v3/pkg/chart/loader"
    19  	"helm.sh/helm/v3/pkg/chartutil"
    20  	"helm.sh/helm/v3/pkg/cli/values"
    21  	"helm.sh/helm/v3/pkg/engine"
    22  )
    23  
    24  var (
    25  	// this doesn't include the namespace-metadata.* templates, which are Helm-only
    26  	templatesJaeger = []string{
    27  		"templates/namespace.yaml",
    28  		"templates/jaeger-injector.yaml",
    29  		"templates/jaeger-injector-policy.yaml",
    30  		"templates/rbac.yaml",
    31  		"templates/psp.yaml",
    32  		"templates/tracing.yaml",
    33  		"templates/tracing-policy.yaml",
    34  	}
    35  )
    36  
    37  func newCmdInstall() *cobra.Command {
    38  	var registry string
    39  	var cniEnabled bool
    40  	var skipChecks bool
    41  	var ignoreCluster bool
    42  	var wait time.Duration
    43  	var options values.Options
    44  
    45  	// If LINKERD_DOCKER_REGISTRY is not null, use it as default registry path.
    46  	// If --registry option is provided, it will override the env variable.
    47  	defaultDockerRegistry := pkgcmd.DefaultDockerRegistry
    48  	if regOverride := os.Getenv(flags.EnvOverrideDockerRegistry); regOverride != "" {
    49  		defaultDockerRegistry = regOverride
    50  	}
    51  
    52  	cmd := &cobra.Command{
    53  		Use:   "install [flags]",
    54  		Args:  cobra.NoArgs,
    55  		Short: "Output Kubernetes resources to install jaeger extension",
    56  		Long:  `Output Kubernetes resources to install jaeger extension.`,
    57  		Example: `  # Default install.
    58    linkerd jaeger install | kubectl apply -f -
    59    # Install Jaeger extension into a non-default namespace.
    60    linkerd jaeger install --namespace custom | kubectl apply -f -
    61  
    62  The installation can be configured by using the --set, --values, --set-string and --set-file flags.
    63  A full list of configurable values can be found at https://www.github.com/linkerd/linkerd2/tree/main/jaeger/charts/linkerd-jaeger/README.md
    64    `,
    65  		RunE: func(cmd *cobra.Command, args []string) error {
    66  			if !skipChecks && !ignoreCluster {
    67  				// Wait for the core control-plane to be up and running
    68  				hc := healthcheck.NewWithCoreChecks(&healthcheck.Options{
    69  					ControlPlaneNamespace: controlPlaneNamespace,
    70  					KubeConfig:            kubeconfigPath,
    71  					KubeContext:           kubeContext,
    72  					Impersonate:           impersonate,
    73  					ImpersonateGroup:      impersonateGroup,
    74  					APIAddr:               apiAddr,
    75  					RetryDeadline:         time.Now().Add(wait),
    76  				})
    77  				hc.RunWithExitOnError()
    78  				cniEnabled = hc.CNIEnabled
    79  			}
    80  
    81  			return install(os.Stdout, options, registry, cniEnabled)
    82  		},
    83  	}
    84  
    85  	cmd.Flags().StringVar(&registry, "registry", defaultDockerRegistry,
    86  		fmt.Sprintf("Docker registry to pull jaeger-webhook image from ($%s)", flags.EnvOverrideDockerRegistry))
    87  	cmd.Flags().BoolVar(&skipChecks, "skip-checks", false, `Skip checks for linkerd core control-plane existence`)
    88  	cmd.Flags().BoolVar(&ignoreCluster, "ignore-cluster", false,
    89  		"Ignore the current Kubernetes cluster when checking for existing cluster configuration (default false)")
    90  	cmd.Flags().DurationVar(&wait, "wait", 300*time.Second, "Wait for core control-plane components to be available")
    91  
    92  	flags.AddValueOptionsFlags(cmd.Flags(), &options)
    93  
    94  	return cmd
    95  }
    96  
    97  func install(w io.Writer, options values.Options, registry string, cniEnabled bool) error {
    98  
    99  	// Create values override
   100  	valuesOverrides, err := options.MergeValues(nil)
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	if cniEnabled {
   106  		valuesOverrides["cniEnabled"] = true
   107  	}
   108  
   109  	// TODO: Add any validation logic here
   110  
   111  	return render(w, valuesOverrides, registry)
   112  }
   113  
   114  func render(w io.Writer, valuesOverrides map[string]interface{}, registry string) error {
   115  
   116  	files := []*loader.BufferedFile{
   117  		{Name: chartutil.ChartfileName},
   118  		{Name: chartutil.ValuesfileName},
   119  	}
   120  
   121  	for _, template := range templatesJaeger {
   122  		files = append(files,
   123  			&loader.BufferedFile{Name: template},
   124  		)
   125  	}
   126  
   127  	var partialFiles []*loader.BufferedFile
   128  	for _, template := range charts.L5dPartials {
   129  		partialFiles = append(partialFiles,
   130  			&loader.BufferedFile{Name: template},
   131  		)
   132  	}
   133  
   134  	// Load all jaeger chart files into buffer
   135  	if err := charts.FilesReader(static.Templates, "linkerd-jaeger/", files); err != nil {
   136  		return err
   137  	}
   138  
   139  	// Load all partial chart files into buffer
   140  	if err := charts.FilesReader(partials.Templates, "", partialFiles); err != nil {
   141  		return err
   142  	}
   143  
   144  	// Create a Chart obj from the files
   145  	chart, err := loader.LoadFiles(append(files, partialFiles...))
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	vals, err := chartutil.CoalesceValues(chart, valuesOverrides)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	vals, err = charts.InsertVersionValues(vals)
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	regOrig := vals["webhook"].(map[string]interface{})["image"].(map[string]interface{})["name"].(string)
   161  
   162  	// registry variable can never be empty. The precedence are as:
   163  	// 1. --registry
   164  	// 2. EnvOverrideDockerRegistry
   165  	// 3. DefaultDockerRegistry
   166  	if registry != "" {
   167  		vals["webhook"].(map[string]interface{})["image"].(map[string]interface{})["name"] = pkgcmd.RegistryOverride(regOrig, registry)
   168  	}
   169  
   170  	fullValues := map[string]interface{}{
   171  		"Values": vals,
   172  		"Release": map[string]interface{}{
   173  			"Namespace": defaultJaegerNamespace,
   174  			"Service":   "CLI",
   175  		},
   176  	}
   177  
   178  	// Attach the final values into the `Values` field for rendering to work
   179  	renderedTemplates, err := engine.Render(chart, fullValues)
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	// Merge templates and inject
   185  	var buf bytes.Buffer
   186  	for _, tmpl := range chart.Templates {
   187  		t := path.Join(chart.Metadata.Name, tmpl.Name)
   188  		if _, err := buf.WriteString(renderedTemplates[t]); err != nil {
   189  			return err
   190  		}
   191  	}
   192  
   193  	_, err = w.Write(buf.Bytes())
   194  	return err
   195  }
   196  

View as plain text