github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/thirdparty/cmdconfig/commands/cmdsource/cmdsource.go (about)

     1  // Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package cmdsource
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"path/filepath"
    10  
    11  	"github.com/GoogleContainerTools/kpt/internal/docs/generated/fndocs"
    12  	"github.com/GoogleContainerTools/kpt/internal/pkg"
    13  	"github.com/GoogleContainerTools/kpt/internal/printer"
    14  	"github.com/GoogleContainerTools/kpt/internal/util/argutil"
    15  	"github.com/GoogleContainerTools/kpt/internal/util/cmdutil"
    16  	kptfile "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1"
    17  	"github.com/GoogleContainerTools/kpt/thirdparty/cmdconfig/commands/runner"
    18  	"github.com/spf13/cobra"
    19  	"sigs.k8s.io/kustomize/kyaml/kio"
    20  	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
    21  	"sigs.k8s.io/kustomize/kyaml/yaml"
    22  )
    23  
    24  // GetSourceRunner returns a command for Source.
    25  func GetSourceRunner(ctx context.Context, name string) *SourceRunner {
    26  	r := &SourceRunner{
    27  		WrapKind:       kio.ResourceListKind,
    28  		WrapAPIVersion: kio.ResourceListAPIVersion,
    29  		Ctx:            ctx,
    30  	}
    31  	c := &cobra.Command{
    32  		Use:     "source [DIR] [flags]",
    33  		Short:   fndocs.SourceShort,
    34  		Long:    fndocs.SourceShort + "\n" + fndocs.SourceLong,
    35  		Example: fndocs.SourceExamples,
    36  		Args:    cobra.MaximumNArgs(1),
    37  		RunE:    r.runE,
    38  		PreRunE: r.preRunE,
    39  	}
    40  	c.Flags().StringVarP(&r.Output, "output", "o", cmdutil.Stdout,
    41  		fmt.Sprintf("output resources are written to stdout in provided format. Allowed values: %s|%s", cmdutil.Stdout, cmdutil.Unwrap))
    42  	c.Flags().StringVar(&r.FunctionConfig, "fn-config", "",
    43  		"path to function config file.")
    44  	c.Flags().BoolVar(&r.IncludeMetaResources,
    45  		"include-meta-resources", false, "include package meta resources in the command output")
    46  	if err := c.Flags().MarkHidden("include-meta-resources"); err != nil {
    47  		panic(err)
    48  	}
    49  	r.Command = c
    50  	if err := c.MarkFlagFilename("fn-config", "yaml", "json", "yml"); err != nil {
    51  		panic(err)
    52  	}
    53  	return r
    54  }
    55  
    56  func NewCommand(ctx context.Context, name string) *cobra.Command {
    57  	return GetSourceRunner(ctx, name).Command
    58  }
    59  
    60  // SourceRunner contains the run function
    61  type SourceRunner struct {
    62  	Output               string
    63  	WrapKind             string
    64  	WrapAPIVersion       string
    65  	FunctionConfig       string
    66  	Command              *cobra.Command
    67  	IncludeMetaResources bool
    68  	Ctx                  context.Context
    69  }
    70  
    71  func (r *SourceRunner) preRunE(c *cobra.Command, _ []string) error {
    72  	if r.IncludeMetaResources {
    73  		return fmt.Errorf("--include-meta-resources is no longer necessary because meta resources are now included by default")
    74  	}
    75  	return nil
    76  }
    77  
    78  func (r *SourceRunner) runE(c *cobra.Command, args []string) error {
    79  	if r.Output != cmdutil.Stdout && r.Output != cmdutil.Unwrap {
    80  		return fmt.Errorf("invalid input for --output flag %q, must be %q or %q", r.Output, cmdutil.Stdout, cmdutil.Unwrap)
    81  	}
    82  	if len(args) == 0 {
    83  		// default to current working directory
    84  		args = append(args, ".")
    85  	}
    86  	// if there is a function-config specified, emit it
    87  	var functionConfig *yaml.RNode
    88  	if r.FunctionConfig != "" {
    89  		configs, err := kio.LocalPackageReader{PackagePath: r.FunctionConfig, PreserveSeqIndent: true, WrapBareSeqNode: true}.Read()
    90  		if err != nil {
    91  			return err
    92  		}
    93  		if len(configs) != 1 {
    94  			return fmt.Errorf("expected exactly 1 functionConfig, found %d", len(configs))
    95  		}
    96  		functionConfig = configs[0]
    97  	}
    98  
    99  	var inputs []kio.Reader
   100  	for _, a := range args {
   101  		pkgPath, err := filepath.Abs(a)
   102  		if err != nil {
   103  			return fmt.Errorf("cannot convert input path %q to absolute path: %w", a, err)
   104  		}
   105  		resolvedPath, err := argutil.ResolveSymlink(r.Ctx, pkgPath)
   106  		if err != nil {
   107  			return err
   108  		}
   109  		inputs = append(inputs, kio.LocalPackageReader{
   110  			PackagePath:        resolvedPath,
   111  			MatchFilesGlob:     pkg.MatchAllKRM,
   112  			PreserveSeqIndent:  true,
   113  			PackageFileName:    kptfile.KptFileName,
   114  			IncludeSubpackages: true,
   115  			WrapBareSeqNode:    true,
   116  		})
   117  	}
   118  
   119  	var outputs []kio.Writer
   120  	if r.Output == cmdutil.Stdout {
   121  		outputs = append(outputs, kio.ByteWriter{
   122  			Writer:                printer.FromContextOrDie(r.Ctx).OutStream(),
   123  			KeepReaderAnnotations: true,
   124  			WrappingKind:          r.WrapKind,
   125  			WrappingAPIVersion:    r.WrapAPIVersion,
   126  			FunctionConfig:        functionConfig,
   127  		})
   128  	} else {
   129  		outputs = append(outputs, kio.ByteWriter{
   130  			Writer:         printer.FromContextOrDie(r.Ctx).OutStream(),
   131  			FunctionConfig: functionConfig,
   132  			ClearAnnotations: []string{kioutil.IndexAnnotation, kioutil.PathAnnotation,
   133  				kioutil.LegacyPathAnnotation, kioutil.LegacyIndexAnnotation}, // nolint:staticcheck
   134  		})
   135  	}
   136  
   137  	err := kio.Pipeline{Inputs: inputs, Outputs: outputs}.Execute()
   138  	return runner.HandleError(r.Ctx, err)
   139  }