From 5130a154e4ba0e74505805d1c0ff3aa1cd777218 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 24 May 2022 12:03:40 +0200 Subject: [PATCH] Ensure proper FS root is set while bootstrapping This ensures relative paths to e.g. bases can be used. Signed-off-by: Hidde Beydals --- cmd/flux/install.go | 2 +- internal/bootstrap/bootstrap_plain_git.go | 11 ++++--- internal/utils/apply.go | 29 ++++++++++++++----- .../kustomization/kustomization.go | 16 +++++++--- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/cmd/flux/install.go b/cmd/flux/install.go index 0af11cee..4d0e6d82 100644 --- a/cmd/flux/install.go +++ b/cmd/flux/install.go @@ -194,7 +194,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error { return nil } - applyOutput, err := utils.Apply(ctx, kubeconfigArgs, kubeclientOptions, filepath.Join(tmpDir, manifest.Path)) + applyOutput, err := utils.Apply(ctx, kubeconfigArgs, kubeclientOptions, tmpDir, filepath.Join(tmpDir, manifest.Path)) if err != nil { return fmt.Errorf("install failed: %w", err) } diff --git a/internal/bootstrap/bootstrap_plain_git.go b/internal/bootstrap/bootstrap_plain_git.go index 863c4cd7..685c1f0d 100644 --- a/internal/bootstrap/bootstrap_plain_git.go +++ b/internal/bootstrap/bootstrap_plain_git.go @@ -163,19 +163,18 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest // Conditionally install manifests if mustInstallManifests(ctx, b.kube, options.Namespace) { - componentsYAML := filepath.Join(b.git.Path(), manifests.Path) + b.logger.Actionf("installing components in %q namespace", options.Namespace) - // Apply components using any existing customisations + componentsYAML := filepath.Join(b.git.Path(), manifests.Path) kfile := filepath.Join(filepath.Dir(componentsYAML), konfig.DefaultKustomizationFileName()) if _, err := os.Stat(kfile); err == nil { // Apply the components and their patches - b.logger.Actionf("installing components in %q namespace", options.Namespace) - if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, kfile); err != nil { + if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), kfile); err != nil { return err } } else { // Apply the CRDs and controllers - if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, componentsYAML); err != nil { + if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), componentsYAML); err != nil { return err } } @@ -328,7 +327,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options // Apply to cluster b.logger.Actionf("applying sync manifests") - if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, filepath.Join(b.git.Path(), kusManifests.Path)); err != nil { + if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), filepath.Join(b.git.Path(), kusManifests.Path)); err != nil { return err } diff --git a/internal/utils/apply.go b/internal/utils/apply.go index 95badc1f..1979759b 100644 --- a/internal/utils/apply.go +++ b/internal/utils/apply.go @@ -31,16 +31,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/kustomize/api/konfig" + "github.com/fluxcd/flux2/pkg/manifestgen/kustomization" runclient "github.com/fluxcd/pkg/runtime/client" "github.com/fluxcd/pkg/ssa" - - "github.com/fluxcd/flux2/pkg/manifestgen/kustomization" ) // Apply is the equivalent of 'kubectl apply --server-side -f'. // If the given manifest is a kustomization.yaml, then apply performs the equivalent of 'kubectl apply --server-side -k'. -func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, opts *runclient.Options, manifestPath string) (string, error) { - objs, err := readObjects(manifestPath) +func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, opts *runclient.Options, root, manifestPath string) (string, error) { + objs, err := readObjects(root, manifestPath) if err != nil { return "", err } @@ -92,13 +91,17 @@ func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, opts *ru return changeSet.String(), nil } -func readObjects(manifestPath string) ([]*unstructured.Unstructured, error) { - if _, err := os.Stat(manifestPath); err != nil { +func readObjects(root, manifestPath string) ([]*unstructured.Unstructured, error) { + fi, err := os.Lstat(manifestPath) + if err != nil { return nil, err } + if fi.IsDir() || !fi.Mode().IsRegular() { + return nil, fmt.Errorf("expected %q to be a file", manifestPath) + } - if filepath.Base(manifestPath) == konfig.DefaultKustomizationFileName() { - resources, err := kustomization.Build(filepath.Dir(manifestPath)) + if isRecognizedKustomizationFile(manifestPath) { + resources, err := kustomization.BuildWithRoot(root, filepath.Dir(manifestPath)) if err != nil { return nil, err } @@ -152,3 +155,13 @@ func waitForSet(rcg genericclioptions.RESTClientGetter, opts *runclient.Options, } return man.WaitForSet(changeSet.ToObjMetadataSet(), ssa.WaitOptions{Interval: 2 * time.Second, Timeout: time.Minute}) } + +func isRecognizedKustomizationFile(path string) bool { + base := filepath.Base(path) + for _, v := range konfig.RecognizedKustomizationFileNames() { + if base == v { + return true + } + } + return false +} diff --git a/pkg/manifestgen/kustomization/kustomization.go b/pkg/manifestgen/kustomization/kustomization.go index 45a40315..058049b7 100644 --- a/pkg/manifestgen/kustomization/kustomization.go +++ b/pkg/manifestgen/kustomization/kustomization.go @@ -138,14 +138,22 @@ func Generate(options Options) (*manifestgen.Manifest, error) { var kustomizeBuildMutex sync.Mutex // Build takes the path to a directory with a konfig.RecognizedKustomizationFileNames, -// builds it, and returns the resulting manifests as multi-doc YAML. +// builds it, and returns the resulting manifests as multi-doc YAML. It restricts the +// Kustomize file system to the parent directory of the base. func Build(base string) ([]byte, error) { + // TODO(hidde): drop this when consumers have moved away to BuildWithRoot. + parent := filepath.Dir(strings.TrimSuffix(base, string(filepath.Separator))) + return BuildWithRoot(parent, base) +} + +// BuildWithRoot takes the path to a directory with a konfig.RecognizedKustomizationFileNames, +// builds it, and returns the resulting manifests as multi-doc YAML. +// The Kustomize file system is restricted to root. +func BuildWithRoot(root, base string) ([]byte, error) { kustomizeBuildMutex.Lock() defer kustomizeBuildMutex.Unlock() - // TODO(hidde): make this configurable to a specific root (relative to base) - parent := filepath.Dir(strings.TrimSuffix(base, string(filepath.Separator))) - fs, err := filesys.MakeFsOnDiskSecureBuild(parent) + fs, err := filesys.MakeFsOnDiskSecureBuild(root) if err != nil { return nil, err }