mirror of https://github.com/linkerd/linkerd2.git
refactor: Split CRD and control-plane installation (#8401)
We currently have singular `install` and `render` functions, each of which takes a `crds` bool that completely alters the behavior of the function. This change splits this behavior into distinct functions so we have `installCRDs`/`renderCRDs` and `installControlPlane`/ `renderControlPlane`. Signed-off-by: Oliver Gould <ver@buoyant.io>
This commit is contained in:
parent
fb44badf33
commit
4f3c374bb7
|
@ -261,7 +261,7 @@ func renderInstallManifest(ctx context.Context) (*charts.Values, string, error)
|
|||
}
|
||||
|
||||
var b strings.Builder
|
||||
err = install(ctx, k8sAPI, &b, values, []flag.Flag{}, false, valuespkg.Options{})
|
||||
err = installControlPlane(ctx, k8sAPI, &b, values, []flag.Flag{}, valuespkg.Options{})
|
||||
if err != nil {
|
||||
return values, "", err
|
||||
}
|
||||
|
|
|
@ -128,13 +128,19 @@ A full list of configurable values can be found at https://www.github.com/linker
|
|||
}
|
||||
}
|
||||
}
|
||||
err = install(cmd.Context(), k8sAPI, os.Stdout, values, flags, crds, options)
|
||||
if crds && err != nil {
|
||||
|
||||
if crds {
|
||||
if err = installCRDs(cmd.Context(), k8sAPI, os.Stdout, values, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "Rendering Linkerd CRDs...")
|
||||
fmt.Fprintln(os.Stderr, "Next, run `linkerd install | kubectl apply -f -` to install the control plane.")
|
||||
fmt.Fprintln(os.Stderr)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
||||
return installControlPlane(cmd.Context(), k8sAPI, os.Stdout, values, flags, options)
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -150,12 +156,49 @@ A full list of configurable values can be found at https://www.github.com/linker
|
|||
return cmd
|
||||
}
|
||||
|
||||
func install(ctx context.Context, k8sAPI *k8s.KubernetesAPI, w io.Writer, values *l5dcharts.Values, flags []flag.Flag, crds bool, options valuespkg.Options) error {
|
||||
func checkNoConfig(ctx context.Context, k8sAPI *k8s.KubernetesAPI) error {
|
||||
if k8sAPI == nil {
|
||||
// When `ingoreCluster` is set, there is no k8sAPI.
|
||||
return nil
|
||||
}
|
||||
|
||||
// We just want to check if `linkerd-configmap` exists
|
||||
_, err := k8sAPI.CoreV1().ConfigMaps(controlPlaneNamespace).Get(ctx, k8s.ConfigConfigMapName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
fmt.Fprintf(os.Stderr, errMsgLinkerdConfigResourceConflict, controlPlaneNamespace, "ConfigMap/linkerd-config already exists")
|
||||
os.Exit(1)
|
||||
}
|
||||
if !kerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func installCRDs(ctx context.Context, k8sAPI *k8s.KubernetesAPI, w io.Writer, values *l5dcharts.Values, options valuespkg.Options) error {
|
||||
if err := checkNoConfig(ctx, k8sAPI); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create values override
|
||||
valuesOverrides, err := options.MergeValues(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return renderCRDs(w, values, valuesOverrides)
|
||||
}
|
||||
|
||||
func installControlPlane(ctx context.Context, k8sAPI *k8s.KubernetesAPI, w io.Writer, values *l5dcharts.Values, flags []flag.Flag, options valuespkg.Options) error {
|
||||
err := flag.ApplySetFlags(values, flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkNoConfig(ctx, k8sAPI); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create values override
|
||||
valuesOverrides, err := options.MergeValues(nil)
|
||||
if err != nil {
|
||||
|
@ -192,7 +235,7 @@ func install(ctx context.Context, k8sAPI *k8s.KubernetesAPI, w io.Writer, values
|
|||
return err
|
||||
}
|
||||
|
||||
return render(w, values, crds, valuesOverrides)
|
||||
return renderControlPlane(w, values, valuesOverrides)
|
||||
}
|
||||
|
||||
func isRunAsRoot(values map[string]interface{}) bool {
|
||||
|
@ -206,64 +249,32 @@ func isRunAsRoot(values map[string]interface{}) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func render(w io.Writer, values *l5dcharts.Values, crds bool, valuesOverrides map[string]interface{}) error {
|
||||
|
||||
crdFiles := []*loader.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
}
|
||||
cpFiles := []*loader.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
}
|
||||
|
||||
if crds {
|
||||
for _, template := range templatesCrdFiles {
|
||||
crdFiles = append(crdFiles,
|
||||
&loader.BufferedFile{Name: template},
|
||||
)
|
||||
}
|
||||
if err := charts.FilesReader(static.Templates, l5dcharts.HelmChartDirCrds+"/", crdFiles); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for _, template := range templatesControlPlane {
|
||||
cpFiles = append(cpFiles,
|
||||
&loader.BufferedFile{Name: template},
|
||||
)
|
||||
}
|
||||
if err := charts.FilesReader(static.Templates, l5dcharts.HelmChartDirCP+"/", cpFiles); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var partialFiles []*loader.BufferedFile
|
||||
// renderChartToBuffer takes a slice of loaded template files and configuration values and renders
|
||||
// them into a buffer. The coalesced values are also returned so that they may be rendered via
|
||||
// `renderOverrides` if appropriate.
|
||||
func renderChartToBuffer(files []*loader.BufferedFile, values *l5dcharts.Values, valuesOverrides map[string]interface{}) (*bytes.Buffer, chartutil.Values, error) {
|
||||
// Load the partials in addition to the main chart.
|
||||
var partials []*loader.BufferedFile
|
||||
for _, template := range charts.L5dPartials {
|
||||
partialFiles = append(partialFiles,
|
||||
&loader.BufferedFile{Name: template},
|
||||
)
|
||||
partials = append(partials, &loader.BufferedFile{Name: template})
|
||||
}
|
||||
|
||||
// Load all partial chart files into buffer
|
||||
if err := charts.FilesReader(static.Templates, "", partialFiles); err != nil {
|
||||
return err
|
||||
if err := charts.FilesReader(static.Templates, "", partials); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Create a Chart obj from the files
|
||||
files := append(crdFiles, cpFiles...)
|
||||
files = append(files, partialFiles...)
|
||||
chart, err := loader.LoadFiles(files)
|
||||
chart, err := loader.LoadFiles(append(files, partials...))
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Store final Values generated from values.yaml and CLI flags
|
||||
chart.Values, err = values.ToMap()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
vals, err := chartutil.CoalesceValues(chart, valuesOverrides)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fullValues := map[string]interface{}{
|
||||
|
@ -277,7 +288,7 @@ func render(w io.Writer, values *l5dcharts.Values, crds bool, valuesOverrides ma
|
|||
// Attach the final values into the `Values` field for rendering to work
|
||||
renderedTemplates, err := engine.Render(chart, fullValues)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to render the template: %w", err)
|
||||
return nil, nil, fmt.Errorf("failed to render the template: %w", err)
|
||||
}
|
||||
|
||||
// Merge templates and inject
|
||||
|
@ -285,18 +296,55 @@ func render(w io.Writer, values *l5dcharts.Values, crds bool, valuesOverrides ma
|
|||
for _, tmpl := range chart.Templates {
|
||||
t := path.Join(chart.Metadata.Name, tmpl.Name)
|
||||
if _, err := buf.WriteString(renderedTemplates[t]); err != nil {
|
||||
return err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !crds {
|
||||
return &buf, vals, nil
|
||||
}
|
||||
|
||||
func renderCRDs(w io.Writer, values *l5dcharts.Values, valuesOverrides map[string]interface{}) error {
|
||||
files := []*loader.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
}
|
||||
for _, template := range templatesCrdFiles {
|
||||
files = append(files, &loader.BufferedFile{Name: template})
|
||||
}
|
||||
if err := charts.FilesReader(static.Templates, l5dcharts.HelmChartDirCrds+"/", files); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, _, err := renderChartToBuffer(files, values, valuesOverrides)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func renderControlPlane(w io.Writer, values *l5dcharts.Values, valuesOverrides map[string]interface{}) error {
|
||||
files := []*loader.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
}
|
||||
for _, template := range templatesControlPlane {
|
||||
files = append(files, &loader.BufferedFile{Name: template})
|
||||
}
|
||||
if err := charts.FilesReader(static.Templates, l5dcharts.HelmChartDirCP+"/", files); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, vals, err := renderChartToBuffer(files, values, valuesOverrides)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
overrides, err := renderOverrides(vals, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf.WriteString(yamlSep)
|
||||
buf.WriteString(string(overrides))
|
||||
}
|
||||
|
||||
_, err = w.Write(buf.Bytes())
|
||||
return err
|
||||
|
|
|
@ -236,7 +236,7 @@ func TestRender(t *testing.T) {
|
|||
t.Fatalf("Failed to get values overrides: %v", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := render(&buf, tc.values, false, valuesOverrides); err != nil {
|
||||
if err := renderControlPlane(&buf, tc.values, valuesOverrides); err != nil {
|
||||
t.Fatalf("Failed to render templates: %v", err)
|
||||
}
|
||||
testDataDiffer.DiffTestdata(t, tc.goldenFileName, buf.String())
|
||||
|
@ -252,7 +252,7 @@ func TestIgnoreCluster(t *testing.T) {
|
|||
addFakeTLSSecrets(defaultValues)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := install(context.Background(), nil, &buf, defaultValues, nil, false, values.Options{}); err != nil {
|
||||
if err := installControlPlane(context.Background(), nil, &buf, defaultValues, nil, values.Options{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ func TestRenderCRDs(t *testing.T) {
|
|||
addFakeTLSSecrets(defaultValues)
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := render(&buf, defaultValues, true, map[string]interface{}{}); err != nil {
|
||||
if err := renderCRDs(&buf, defaultValues, map[string]interface{}{}); err != nil {
|
||||
t.Fatalf("Failed to render templates: %v", err)
|
||||
}
|
||||
testDataDiffer.DiffTestdata(t, "install_crds.golden", buf.String())
|
||||
|
|
|
@ -227,10 +227,16 @@ the 'linkerd repair' command to repair the Linkerd config`)
|
|||
// rendering to a buffer and printing full contents of buffer after
|
||||
// render is complete, to ensure that okStatus prints separately
|
||||
var buf bytes.Buffer
|
||||
if err = render(&buf, values, crds, valuesOverrides); err != nil {
|
||||
if crds {
|
||||
if err = renderCRDs(&buf, values, valuesOverrides); err != nil {
|
||||
upgradeErrorf("Could not render upgrade configuration: %s", err)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
if err = renderControlPlane(&buf, values, valuesOverrides); err != nil {
|
||||
upgradeErrorf("Could not render upgrade configuration: %s", err)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -566,7 +566,7 @@ func pathMatch(path []string, template []string) bool {
|
|||
|
||||
func renderInstall(t *testing.T, values *linkerd2.Values) bytes.Buffer {
|
||||
var installBuf bytes.Buffer
|
||||
if err := render(&installBuf, values, false, nil); err != nil {
|
||||
if err := renderControlPlane(&installBuf, values, nil); err != nil {
|
||||
t.Fatalf("could not render install manifests: %s", err)
|
||||
}
|
||||
return installBuf
|
||||
|
|
Loading…
Reference in New Issue