diff --git a/pkg/cli/run.go b/pkg/cli/run.go index 629f26603..9bac751b2 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -27,6 +27,7 @@ import ( "github.com/accurics/terrascan/pkg/runtime" "github.com/accurics/terrascan/pkg/utils" "github.com/accurics/terrascan/pkg/writer" + "github.com/mattn/go-isatty" "go.uber.org/zap" ) @@ -34,80 +35,182 @@ const ( humanOutputFormat = "human" ) +// ScanOptions represents scan command and its optional flags +type ScanOptions struct { + // Policy path directory + policyPath []string + + // Cloud type (aws, azure, gcp, github) + policyType []string + + // IaC type (terraform) + iacType string + + // IaC version (for terraform:v12) + iacVersion string + + // Path to a single IaC file + iacFilePath string + + // Path to a directory containing one or more IaC files + iacDirPath string + + // remoteType indicates the type of remote backend. Supported backends are + // git s3, gcs, http. + remoteType string + + // remoteURL points to the remote Iac repository on git, s3, gcs, http + remoteURL string + + // configOnly will output resource config (should only be used for debugging purposes) + configOnly bool + + // config file path + configFile string + + // the output format for wring the results + outputType string + + // UseColors indicates whether to use color output + UseColors bool + useColors string // used for flag processing + + // Verbose indicates whether to display all fields in default human readlbe output + Verbose bool +} + +// NewScanOptions returns a new pointer to ScanOptions +func NewScanOptions() *ScanOptions { + return new(ScanOptions) +} + +// Scan executes the terrascan scan command +func (s *ScanOptions) Scan() error { + if err := s.Init(); err != nil { + zap.S().Error("scan init failed", zap.Error(err)) + return err + } + + if err := s.Run(); err != nil { + zap.S().Error("scan run failed", zap.Error(err)) + return err + } + return nil +} + +//Init initalises and validates ScanOptions +func (s *ScanOptions) Init() error { + s.initColor() + err := s.validate() + if err != nil { + zap.S().Error("failed to start scan", zap.Error(err)) + return err + } + return nil +} + +// validate config only for human readable output +// rest command options are validated by the executor +func (s ScanOptions) validate() error { + // human readable output doesn't support --config-only flag + // if --config-only flag is set, then exit with an error + // asking the user to use yaml or json output format + if s.configOnly && strings.EqualFold(s.outputType, humanOutputFormat) { + return errors.New("please use yaml or json output format when using --config-only flag") + } + return nil +} + +// initialises use colors options +func (s *ScanOptions) initColor() { + switch strings.ToLower(s.useColors) { + case "auto": + if isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) { + s.UseColors = true + } else { + s.UseColors = false + } + + case "true": + fallthrough + case "t": + fallthrough + case "y": + fallthrough + case "1": + fallthrough + case "force": + s.UseColors = true + + default: + s.UseColors = false + } +} + // Run executes terrascan in CLI mode -func Run(iacType, iacVersion string, cloudType []string, - iacFilePath, iacDirPath, configFile string, policyPath []string, - format, remoteType, remoteURL string, configOnly, useColors, verbose bool) { +func (s *ScanOptions) Run() error { // temp dir to download the remote repo tempDir := filepath.Join(os.TempDir(), utils.GenRandomString(6)) defer os.RemoveAll(tempDir) // download remote repository - path, err := downloadRemoteRepository(remoteType, remoteURL, tempDir) + err := s.downloadRemoteRepository(tempDir) if err != nil { - return - } - - if path != "" { - iacDirPath = path + return err } // create a new runtime executor for processing IaC - executor, err := runtime.NewExecutor(iacType, iacVersion, cloudType, - iacFilePath, iacDirPath, configFile, policyPath) + executor, err := runtime.NewExecutor(s.iacType, s.iacVersion, s.policyType, + s.iacFilePath, s.iacDirPath, s.configFile, s.policyPath) if err != nil { - return + return err } // executor output results, err := executor.Execute() if err != nil { - return + return err } // write results to console - err = writeResults(results, useColors, verbose, configOnly, format) + err = s.writeResults(results) if err != nil { zap.S().Error("failed to write results", zap.Error(err)) - return + return err } if results.Violations.ViolationStore.Summary.ViolatedPolicies != 0 && flag.Lookup("test.v") == nil { os.RemoveAll(tempDir) os.Exit(3) } + return nil } -func downloadRemoteRepository(remoteType, remoteURL, tempDir string) (string, error) { +func (s *ScanOptions) downloadRemoteRepository(tempDir string) error { d := downloader.NewDownloader() - path, err := d.DownloadWithType(remoteType, remoteURL, tempDir) + path, err := d.DownloadWithType(s.remoteType, s.remoteURL, tempDir) + if path != "" { + s.iacDirPath = path + } if err == downloader.ErrEmptyURLType { // url and type empty, proceed with regular scanning zap.S().Debugf("remote url and type not configured, proceeding with regular scanning") } else if err != nil { // some error while downloading remote repository - return path, err + return err } - return path, nil + return nil } -func writeResults(results runtime.Output, useColors, verbose, configOnly bool, format string) error { +func (s ScanOptions) writeResults(results runtime.Output) error { // add verbose flag to the scan summary - results.Violations.ViolationStore.Summary.ShowViolationDetails = verbose + results.Violations.ViolationStore.Summary.ShowViolationDetails = s.Verbose - outputWriter := NewOutputWriter(useColors) + outputWriter := NewOutputWriter(s.UseColors) - if configOnly { - // human readable output doesn't support --config-only flag - // if --config-only flag is set, then exit with an error - // asking the user to use yaml or json output format - if strings.EqualFold(format, humanOutputFormat) { - return errors.New("please use yaml or json output format when using --config-only flag") - } - writer.Write(format, results.ResourceConfig, outputWriter) - } else { - writer.Write(format, results.Violations, outputWriter) + if s.configOnly { + return writer.Write(s.outputType, results.ResourceConfig, outputWriter) } - return nil + return writer.Write(s.outputType, results.Violations, outputWriter) } diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go index 589f2d453..7b3574286 100644 --- a/pkg/cli/run_test.go +++ b/pkg/cli/run_test.go @@ -28,172 +28,423 @@ import ( "github.com/accurics/terrascan/pkg/utils" ) +func TestMain(m *testing.M) { + setup() + code := m.Run() + shutdown() + os.Exit(code) +} + +func setup() { + // to download the policies for Run test + // downloads the policies at $HOME/.terrascan + initial(nil, nil) +} + +func shutdown() { + // remove the downloaded policies + os.RemoveAll(os.Getenv("HOME") + "/.terrascan") +} + func TestRun(t *testing.T) { + testDirPath := "testdata/run-test" + kustomizeTestDirPath := testDirPath + "/kustomize-test" + testTerraformFilePath := testDirPath + "/config-only.tf" + table := []struct { name string - iacType string - iacVersion string - cloudType []string - format string - iacFilePath string - iacDirPath string configFile string - configOnly bool - verbose bool + scanOptions *ScanOptions stdOut string want string - wantErr error + wantErr bool }{ { - name: "normal terraform run", - cloudType: []string{"terraform"}, - iacDirPath: "testdata/run-test", + name: "normal terraform run", + scanOptions: &ScanOptions{ + // policy type terraform is not supported, error expected + policyType: []string{"terraform"}, + iacDirPath: testDirPath, + }, + wantErr: true, }, { - name: "normal k8s run", - cloudType: []string{"k8s"}, - iacDirPath: "testdata/run-test", + name: "normal terraform run with successful output", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacDirPath: testDirPath, + outputType: "json", + }, }, { - name: "config-only flag terraform", - cloudType: []string{"terraform"}, - iacFilePath: "testdata/run-test/config-only.tf", - configOnly: true, + name: "normal k8s run", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + // kustomization.y(a)ml file not present under the dir path, error expected + iacDirPath: testDirPath, + }, + wantErr: true, }, { - name: "config-only flag k8s", - cloudType: []string{"k8s"}, - iacFilePath: "testdata/run-test/config-only.yaml", - configOnly: true, + name: "normal k8s run with successful output", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + iacDirPath: kustomizeTestDirPath, + outputType: "human", + }, }, { - name: "config-only flag true with human readable format", - cloudType: []string{"terraform"}, - iacFilePath: "testdata/run-test/config-only.tf", - configOnly: true, - format: "human", + name: "config-only flag terraform", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + configOnly: true, + outputType: "yaml", + }, }, { - name: "config-only flag false with human readable format", - cloudType: []string{"k8s"}, - iacFilePath: "testdata/run-test/config-only.yaml", - format: "human", + name: "config-only flag k8s", + scanOptions: &ScanOptions{ + policyType: []string{"k8s"}, + iacDirPath: kustomizeTestDirPath, + configOnly: true, + outputType: "json", + }, + }, + { + // xml doesn't support config-only, error expected + // modify the test results when xml supports config-only + name: "config-only flag true with xml output format", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + configOnly: true, + outputType: "xml", + }, + wantErr: true, + }, + { + name: "fail to download remote repository", + scanOptions: &ScanOptions{ + policyType: []string{"all"}, + iacFilePath: testTerraformFilePath, + remoteURL: "test", + remoteType: "test", + }, + wantErr: true, }, } for _, tt := range table { t.Run(tt.name, func(t *testing.T) { - Run(tt.iacType, tt.iacVersion, tt.cloudType, tt.iacFilePath, tt.iacDirPath, tt.configFile, []string{}, tt.format, "", "", tt.configOnly, false, tt.verbose) + err := tt.scanOptions.Run() + if (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.Run() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} + +func TestScanOptionsDownloadRemoteRepository(t *testing.T) { + testTempdir := filepath.Join(os.TempDir(), utils.GenRandomString(6)) + defer os.RemoveAll(testTempdir) + + type fields struct { + RemoteType string + RemoteURL string + } + tests := []struct { + name string + fields fields + tempDir string + want string + wantErr bool + }{ + { + name: "blank input parameters", + fields: fields{ + RemoteType: "", + RemoteURL: "", + }, + tempDir: "", + }, + { + name: "invalid input parameters", + fields: fields{ + RemoteType: "test", + RemoteURL: "test", + }, + tempDir: "test", + wantErr: true, + }, + { + name: "valid input parameters", + fields: fields{ + RemoteType: "git", + RemoteURL: "github.com/accurics/terrascan", + }, + tempDir: testTempdir, + want: testTempdir, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := ScanOptions{ + remoteType: tt.fields.RemoteType, + remoteURL: tt.fields.RemoteURL, + } + err := s.downloadRemoteRepository(tt.tempDir) + if (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.downloadRemoteRepository() error = %v, wantErr %v", err, tt.wantErr) + return + } + if s.iacDirPath != tt.want { + t.Errorf("ScanOptions.downloadRemoteRepository() = %v, want %v", s.iacDirPath, tt.want) + } }) } } -func TestWriteResults(t *testing.T) { +func TestScanOptionsWriteResults(t *testing.T) { testInput := runtime.Output{ ResourceConfig: output.AllResourceConfigs{}, Violations: policy.EngineOutput{ ViolationStore: &results.ViolationStore{}, }, } - type args struct { - results runtime.Output - useColors bool - verbose bool + + type fields struct { + ConfigOnly bool + OutputType string + } + tests := []struct { + name string + fields fields + args runtime.Output + wantErr bool + }{ + { + name: "config only true", + fields: fields{ + ConfigOnly: true, + OutputType: "yaml", + }, + args: testInput, + }, + { + name: "config only false", + fields: fields{ + ConfigOnly: false, + OutputType: "json", + }, + args: testInput, + }, + { + // until we support config only flag for xml, this test case is for expected failure + name: "config only true for xml", + fields: fields{ + ConfigOnly: true, + OutputType: "xml", + }, + args: testInput, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := ScanOptions{ + configOnly: tt.fields.ConfigOnly, + outputType: tt.fields.OutputType, + } + if err := s.writeResults(tt.args); (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.writeResults() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestScanOptionsValidate(t *testing.T) { + type fields struct { configOnly bool - format string + outputType string } tests := []struct { name string - args args + fields fields wantErr bool }{ { - name: "config only true with human readable output format", - args: args{ - results: testInput, + name: "validate --config-only with human readable output", + fields: fields{ configOnly: true, - format: "human", + outputType: "human", }, wantErr: true, }, { - name: "config only true with non human readable output format", - args: args{ - results: testInput, + name: "validate --config-only with non human readable output", + fields: fields{ configOnly: true, - format: "json", + outputType: "json", }, wantErr: false, }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := ScanOptions{ + configOnly: tt.fields.configOnly, + outputType: tt.fields.outputType, + } + if err := s.validate(); (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.validate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestScanOptionsInitColor(t *testing.T) { + type fields struct { + useColors string + } + tests := []struct { + name string + fields fields + want bool + }{ { - name: "config only false", - args: args{ - results: testInput, - configOnly: false, - format: "human", + name: "test for auto as input", + fields: fields{ + useColors: "auto", + }, + }, + { + name: "test for true as input", + fields: fields{ + useColors: "true", + }, + want: true, + }, + { + name: "test for 1 as input", + fields: fields{ + useColors: "1", + }, + want: true, + }, + { + name: "test for false as input", + fields: fields{ + useColors: "false", }, - wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := writeResults(tt.args.results, tt.args.useColors, tt.args.verbose, tt.args.configOnly, tt.args.format); (err != nil) != tt.wantErr { - t.Errorf("writeResults() error = gotErr: %v, wantErr: %v", err, tt.wantErr) + s := &ScanOptions{ + useColors: tt.fields.useColors, + } + s.initColor() + if s.useColors != "auto" { + if s.UseColors != tt.want { + t.Errorf("ScanOptions.initColor() incorrect value for UseColors, got: %v, want %v", s.useColors, tt.want) + } } }) } } -func TestDownloadRemoteRepository(t *testing.T) { - testTempdir := filepath.Join(os.TempDir(), utils.GenRandomString(6)) +func TestScanOptionsInit(t *testing.T) { + type fields struct { + configOnly bool + outputType string + useColors string + } + tests := []struct { + name string + fields fields + wantErr bool + }{ + { + name: "test for init fail", + fields: fields{ + useColors: "auto", + outputType: "human", + configOnly: true, + }, + wantErr: true, + }, + { + name: "test for init success", + fields: fields{ + useColors: "auto", + outputType: "human", + configOnly: false, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &ScanOptions{ + configOnly: tt.fields.configOnly, + outputType: tt.fields.outputType, + useColors: tt.fields.useColors, + } + if err := s.Init(); (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.Init() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} - type args struct { - remoteType string - remoteURL string - tempDir string +func TestScanOptionsScan(t *testing.T) { + type fields struct { + policyType []string + iacDirPath string + configOnly bool + outputType string } tests := []struct { name string - args args - want string + fields fields wantErr bool }{ { - name: "blank input paramters", - args: args{ - remoteType: "", - remoteURL: "", - tempDir: "", + name: "failure in init", + fields: fields{ + configOnly: true, + outputType: "human", }, + wantErr: true, }, { - name: "invalid input parameters", - args: args{ - remoteType: "test", - remoteURL: "test", - tempDir: "test", + name: "failure in run", + fields: fields{ + policyType: []string{"terraform"}, + iacDirPath: "testdata/run-test", }, wantErr: true, }, { - name: "valid inputs paramters", - args: args{ - remoteType: "git", - remoteURL: "github.com/accurics/terrascan", - tempDir: testTempdir, + name: "successful scan", + fields: fields{ + policyType: []string{"all"}, + iacDirPath: "testdata/run-test", + outputType: "json", }, - want: testTempdir, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := downloadRemoteRepository(tt.args.remoteType, tt.args.remoteURL, tt.args.tempDir) - if (err != nil) != tt.wantErr { - t.Errorf("downloadRemoteRepository() error = %v, wantErr %v", err, tt.wantErr) - return + s := &ScanOptions{ + policyType: tt.fields.policyType, + iacDirPath: tt.fields.iacDirPath, + configOnly: tt.fields.configOnly, + outputType: tt.fields.outputType, } - if got != tt.want { - t.Errorf("downloadRemoteRepository() = %v, want %v", got, tt.want) + if err := s.Scan(); (err != nil) != tt.wantErr { + t.Errorf("ScanOptions.Scan() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/pkg/cli/scan.go b/pkg/cli/scan.go index 54568ac6a..4ff3d0586 100644 --- a/pkg/cli/scan.go +++ b/pkg/cli/scan.go @@ -18,52 +18,15 @@ package cli import ( "fmt" - "os" "strings" iacProvider "github.com/accurics/terrascan/pkg/iac-providers" "github.com/accurics/terrascan/pkg/policy" - "github.com/mattn/go-isatty" "github.com/spf13/cobra" "go.uber.org/zap" ) -var ( - // PolicyPath Policy path directory - PolicyPath []string - - // PolicyType Cloud type (aws, azure, gcp, github) - PolicyType []string - - // IacType IaC type (terraform) - IacType string - - // IacVersion IaC version (for terraform:v12) - IacVersion string - - // IacFilePath Path to a single IaC file - IacFilePath string - - // IacDirPath Path to a directory containing one or more IaC files - IacDirPath string - - // RemoteType indicates the type of remote backend. Supported backends are - // git s3, gcs, http. - RemoteType string - - // RemoteURL points to the remote Iac repository on git, s3, gcs, http - RemoteURL string - - // ConfigOnly will output resource config (should only be used for debugging purposes) - ConfigOnly bool - - // UseColors indicates whether to use color output - UseColors bool - useColors string // used for flag processing - - // Verbose indicates whether to display all fields in default human readlbe output - Verbose bool -) +var scanOptions = NewScanOptions() var scanCmd = &cobra.Command{ Use: "scan", @@ -72,52 +35,29 @@ var scanCmd = &cobra.Command{ Detect compliance and security violations across Infrastructure as Code to mitigate risk before provisioning cloud native infrastructure. `, - PreRun: func(cmd *cobra.Command, args []string) { - switch strings.ToLower(useColors) { - case "auto": - if isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) { - UseColors = true - } else { - UseColors = false - } - - case "true": - fallthrough - case "t": - fallthrough - case "y": - fallthrough - case "1": - fallthrough - case "force": - UseColors = true - - default: - UseColors = false - } - initial(cmd, args) - }, - Run: scan, + PreRun: initial, + Run: scan, } func scan(cmd *cobra.Command, args []string) { zap.S().Debug("running terrascan in cli mode") - Run(IacType, IacVersion, PolicyType, IacFilePath, IacDirPath, ConfigFile, - PolicyPath, OutputType, RemoteType, RemoteURL, ConfigOnly, UseColors, Verbose) + scanOptions.configFile = ConfigFile + scanOptions.outputType = OutputType + scanOptions.Scan() } func init() { - scanCmd.Flags().StringSliceVarP(&PolicyType, "policy-type", "t", []string{"all"}, fmt.Sprintf("policy type (%s)", strings.Join(policy.SupportedPolicyTypes(true), ", "))) - scanCmd.Flags().StringVarP(&IacType, "iac-type", "i", "", fmt.Sprintf("iac type (%v)", strings.Join(iacProvider.SupportedIacProviders(), ", "))) - scanCmd.Flags().StringVarP(&IacVersion, "iac-version", "", "", fmt.Sprintf("iac version (%v)", strings.Join(iacProvider.SupportedIacVersions(), ", "))) - scanCmd.Flags().StringVarP(&IacFilePath, "iac-file", "f", "", "path to a single IaC file") - scanCmd.Flags().StringVarP(&IacDirPath, "iac-dir", "d", ".", "path to a directory containing one or more IaC files") - scanCmd.Flags().StringArrayVarP(&PolicyPath, "policy-path", "p", []string{}, "policy path directory") - scanCmd.Flags().StringVarP(&RemoteType, "remote-type", "r", "", "type of remote backend (git, s3, gcs, http)") - scanCmd.Flags().StringVarP(&RemoteURL, "remote-url", "u", "", "url pointing to remote IaC repository") - scanCmd.Flags().BoolVarP(&ConfigOnly, "config-only", "", false, "will output resource config (should only be used for debugging purposes)") + scanCmd.Flags().StringSliceVarP(&scanOptions.policyType, "policy-type", "t", []string{"all"}, fmt.Sprintf("policy type (%s)", strings.Join(policy.SupportedPolicyTypes(true), ", "))) + scanCmd.Flags().StringVarP(&scanOptions.iacType, "iac-type", "i", "", fmt.Sprintf("iac type (%v)", strings.Join(iacProvider.SupportedIacProviders(), ", "))) + scanCmd.Flags().StringVarP(&scanOptions.iacVersion, "iac-version", "", "", fmt.Sprintf("iac version (%v)", strings.Join(iacProvider.SupportedIacVersions(), ", "))) + scanCmd.Flags().StringVarP(&scanOptions.iacFilePath, "iac-file", "f", "", "path to a single IaC file") + scanCmd.Flags().StringVarP(&scanOptions.iacDirPath, "iac-dir", "d", ".", "path to a directory containing one or more IaC files") + scanCmd.Flags().StringArrayVarP(&scanOptions.policyPath, "policy-path", "p", []string{}, "policy path directory") + scanCmd.Flags().StringVarP(&scanOptions.remoteType, "remote-type", "r", "", "type of remote backend (git, s3, gcs, http)") + scanCmd.Flags().StringVarP(&scanOptions.remoteURL, "remote-url", "u", "", "url pointing to remote IaC repository") + scanCmd.Flags().BoolVarP(&scanOptions.configOnly, "config-only", "", false, "will output resource config (should only be used for debugging purposes)") // flag passes a string, but we normalize to bool in PreRun - scanCmd.Flags().StringVar(&useColors, "use-colors", "auto", "color output (auto, t, f)") - scanCmd.Flags().BoolVarP(&Verbose, "verbose", "v", false, "will show violations with details (applicable for default output)") + scanCmd.Flags().StringVar(&scanOptions.useColors, "use-colors", "auto", "color output (auto, t, f)") + scanCmd.Flags().BoolVarP(&scanOptions.Verbose, "verbose", "v", false, "will show violations with details (applicable for default output)") RegisterCommand(rootCmd, scanCmd) } diff --git a/pkg/cli/testdata/run-test/kustomize-test/configMap.yaml b/pkg/cli/testdata/run-test/kustomize-test/configMap.yaml new file mode 100644 index 000000000..e335ab8cc --- /dev/null +++ b/pkg/cli/testdata/run-test/kustomize-test/configMap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: the-map +data: + altGreeting: "Good Morning!" + enableRisky: "false" diff --git a/pkg/cli/testdata/run-test/kustomize-test/deployment.yaml b/pkg/cli/testdata/run-test/kustomize-test/deployment.yaml new file mode 100644 index 000000000..00e5eb937 --- /dev/null +++ b/pkg/cli/testdata/run-test/kustomize-test/deployment.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: the-deployment +spec: + replicas: 3 + selector: + matchLabels: + deployment: hello + template: + metadata: + labels: + deployment: hello + spec: + containers: + - name: the-container + image: monopole/hello:1 + command: ["/hello", + "--port=8080", + "--enableRiskyFeature=$(ENABLE_RISKY)"] + ports: + - containerPort: 8080 + env: + - name: ALT_GREETING + valueFrom: + configMapKeyRef: + name: the-map + key: altGreeting + - name: ENABLE_RISKY + valueFrom: + configMapKeyRef: + name: the-map + key: enableRisky diff --git a/pkg/cli/testdata/run-test/kustomize-test/kustomization.yaml b/pkg/cli/testdata/run-test/kustomize-test/kustomization.yaml new file mode 100644 index 000000000..882d52bfe --- /dev/null +++ b/pkg/cli/testdata/run-test/kustomize-test/kustomization.yaml @@ -0,0 +1,8 @@ +# Example configuration for the webserver +# at https://github.com/monopole/hello +commonLabels: + app: hello + +resources: +- deployment.yaml +- configMap.yaml