github.com/splunk/dan1-qbec@v0.7.3/internal/commands/validate_test.go (about)

     1  /*
     2     Copyright 2019 Splunk Inc.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package commands
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  	"testing"
    23  
    24  	"github.com/splunk/qbec/internal/remote/k8smeta"
    25  	"github.com/stretchr/testify/assert"
    26  	"github.com/stretchr/testify/require"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  )
    30  
    31  type v struct{}
    32  
    33  func (v *v) Validate(obj *unstructured.Unstructured) []error {
    34  	if obj.GetName() == "svc2-cm" {
    35  		return []error{fmt.Errorf("bad config map")}
    36  	}
    37  	return nil
    38  }
    39  
    40  func factory(gvk schema.GroupVersionKind) (k8smeta.Validator, error) {
    41  	if gvk.Kind == "PodSecurityPolicy" {
    42  		return nil, k8smeta.ErrSchemaNotFound
    43  	}
    44  	return &v{}, nil
    45  }
    46  
    47  func TestValidateAll(t *testing.T) {
    48  	s := newScaffold(t)
    49  	defer s.reset()
    50  	s.client.validatorFunc = factory
    51  	err := s.executeCommand("validate", "dev")
    52  	require.NotNil(t, err)
    53  	s.assertOutputLineMatch(regexp.MustCompile(`✔ ClusterRole::allow-root-psp-policy is valid`))
    54  	s.assertOutputLineMatch(regexp.MustCompile(`\? PodSecurityPolicy::100-default: no schema found, cannot validate`))
    55  	s.assertOutputLineMatch(regexp.MustCompile(`✘ ConfigMap:bar-system:svc2-cm is invalid`))
    56  	s.assertOutputLineMatch(regexp.MustCompile(`- bad config map`))
    57  }
    58  
    59  func TestValidateSilent(t *testing.T) {
    60  	s := newScaffold(t)
    61  	defer s.reset()
    62  	s.client.validatorFunc = factory
    63  	err := s.executeCommand("validate", "dev", "--silent")
    64  	require.NotNil(t, err)
    65  	s.assertOutputLineNoMatch(regexp.MustCompile(`✔ ClusterRole::allow-root-psp-policy is valid`))
    66  	s.assertOutputLineNoMatch(regexp.MustCompile(`\? PodSecurityPolicy::100-default: no schema found, cannot validate`))
    67  	s.assertOutputLineMatch(regexp.MustCompile(`✘ ConfigMap:bar-system:svc2-cm is invalid`))
    68  	s.assertOutputLineMatch(regexp.MustCompile(`- bad config map`))
    69  }
    70  
    71  func TestValidateNegative(t *testing.T) {
    72  	tests := []struct {
    73  		name     string
    74  		args     []string
    75  		init     func(s *scaffold)
    76  		asserter func(s *scaffold, err error)
    77  		dir      string
    78  	}{
    79  		{
    80  			name: "no env",
    81  			args: []string{"validate"},
    82  			asserter: func(s *scaffold, err error) {
    83  				a := assert.New(s.t)
    84  				a.True(isUsageError(err))
    85  				a.Equal("exactly one environment required", err.Error())
    86  			},
    87  		},
    88  		{
    89  			name: "2 envs",
    90  			args: []string{"validate", "dev", "prod"},
    91  			asserter: func(s *scaffold, err error) {
    92  				a := assert.New(s.t)
    93  				a.True(isUsageError(err))
    94  				a.Equal("exactly one environment required", err.Error())
    95  			},
    96  		},
    97  		{
    98  			name: "bad env",
    99  			args: []string{"validate", "foo"},
   100  			asserter: func(s *scaffold, err error) {
   101  				a := assert.New(s.t)
   102  				a.False(isUsageError(err))
   103  				a.Equal(`invalid environment "foo"`, err.Error())
   104  			},
   105  		},
   106  		{
   107  			name: "bad component",
   108  			args: []string{"validate", "dev", "-c", "foo"},
   109  			asserter: func(s *scaffold, err error) {
   110  				a := assert.New(s.t)
   111  				a.False(isUsageError(err))
   112  				a.Equal(`specified components: bad component reference(s): foo`, err.Error())
   113  			},
   114  		},
   115  		{
   116  			name: "bad filters",
   117  			args: []string{"validate", "dev", "-c", "svc1-cm", "-C", "svc2-cm"},
   118  			asserter: func(s *scaffold, err error) {
   119  				a := assert.New(s.t)
   120  				a.True(isUsageError(err))
   121  				a.Equal(`cannot include as well as exclude components, specify one or the other`, err.Error())
   122  			},
   123  		},
   124  		{
   125  			name: "duplicate objects",
   126  			dir:  "testdata/dups",
   127  			args: []string{"validate", "dev"},
   128  			asserter: func(s *scaffold, err error) {
   129  				a := assert.New(s.t)
   130  				a.True(IsRuntimeError(err))
   131  				a.Equal(`duplicate objects ConfigMap cm1 (component: x) and ConfigMap cm1 (component: y)`, err.Error())
   132  			},
   133  		},
   134  		{
   135  			name: "duplicate objects even with filters",
   136  			dir:  "testdata/dups",
   137  			args: []string{"validate", "dev", "-K", "configmap"},
   138  			asserter: func(s *scaffold, err error) {
   139  				a := assert.New(s.t)
   140  				a.True(IsRuntimeError(err))
   141  				a.Equal(`duplicate objects ConfigMap cm1 (component: x) and ConfigMap cm1 (component: y)`, err.Error())
   142  			},
   143  		},
   144  		{
   145  			name: "baseline",
   146  			args: []string{"validate", "_"},
   147  			asserter: func(s *scaffold, err error) {
   148  				a := assert.New(s.t)
   149  				a.True(isUsageError(err))
   150  				a.Equal(`cannot validate baseline environment, use a real environment`, err.Error())
   151  			},
   152  		},
   153  		{
   154  			name: "errors",
   155  			args: []string{"validate", "dev"},
   156  			init: func(s *scaffold) {
   157  				s.client.validatorFunc = func(gvk schema.GroupVersionKind) (k8smeta.Validator, error) {
   158  					return nil, fmt.Errorf("no validator for you")
   159  				}
   160  			},
   161  			asserter: func(s *scaffold, err error) {
   162  				a := assert.New(s.t)
   163  				a.False(isUsageError(err))
   164  				a.Contains(err.Error(), "no validator for you")
   165  			},
   166  		},
   167  	}
   168  
   169  	for _, test := range tests {
   170  		t.Run(test.name, func(t *testing.T) {
   171  			s := newCustomScaffold(t, test.dir)
   172  			defer s.reset()
   173  			s.client.validatorFunc = factory
   174  			if test.init != nil {
   175  				test.init(s)
   176  			}
   177  			err := s.executeCommand(test.args...)
   178  			require.NotNil(t, err)
   179  			test.asserter(s, err)
   180  		})
   181  	}
   182  }