sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/config/store/yaml/store_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     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 yaml
    18  
    19  import (
    20  	"errors"
    21  	"os"
    22  	"testing"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	"github.com/spf13/afero"
    27  
    28  	"sigs.k8s.io/kubebuilder/v3/pkg/config"
    29  	"sigs.k8s.io/kubebuilder/v3/pkg/config/store"
    30  	cfgv2 "sigs.k8s.io/kubebuilder/v3/pkg/config/v2"
    31  	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
    32  )
    33  
    34  func TestConfigStoreYaml(t *testing.T) {
    35  	RegisterFailHandler(Fail)
    36  	RunSpecs(t, "Config Store YAML Suite")
    37  }
    38  
    39  var _ = Describe("New", func() {
    40  	It("should return a new empty store", func() {
    41  		s := New(machinery.Filesystem{FS: afero.NewMemMapFs()})
    42  		Expect(s.Config()).To(BeNil())
    43  
    44  		ys, ok := s.(*yamlStore)
    45  		Expect(ok).To(BeTrue())
    46  		Expect(ys.fs).NotTo(BeNil())
    47  	})
    48  })
    49  
    50  var _ = Describe("yamlStore", func() {
    51  	const (
    52  		v2File = `version: "2"
    53  `
    54  		unversionedFile = `version:
    55  `
    56  		nonexistentVersionFile = `version: 1-alpha
    57  ` // v1-alpha never existed
    58  		wrongFile = `version: "2"
    59  layout: ""
    60  ` // layout field does not exist in v2
    61  	)
    62  
    63  	var (
    64  		s *yamlStore
    65  
    66  		path = DefaultPath + "2"
    67  	)
    68  
    69  	BeforeEach(func() {
    70  		s = New(machinery.Filesystem{FS: afero.NewMemMapFs()}).(*yamlStore)
    71  	})
    72  
    73  	Context("New", func() {
    74  		It("should initialize a new Config backend for the provided version", func() {
    75  			Expect(s.New(cfgv2.Version)).To(Succeed())
    76  			Expect(s.fs).NotTo(BeNil())
    77  			Expect(s.mustNotExist).To(BeTrue())
    78  			Expect(s.Config()).NotTo(BeNil())
    79  			Expect(s.Config().GetVersion().Compare(cfgv2.Version)).To(Equal(0))
    80  		})
    81  
    82  		It("should fail for an unregistered config version", func() {
    83  			Expect(s.New(config.Version{})).NotTo(Succeed())
    84  		})
    85  	})
    86  
    87  	Context("Load", func() {
    88  		It("should load the Config from an existing file at the default path", func() {
    89  			Expect(afero.WriteFile(s.fs, DefaultPath, []byte(commentStr+v2File), os.ModePerm)).To(Succeed())
    90  
    91  			Expect(s.Load()).To(Succeed())
    92  			Expect(s.fs).NotTo(BeNil())
    93  			Expect(s.mustNotExist).To(BeFalse())
    94  			Expect(s.Config()).NotTo(BeNil())
    95  			Expect(s.Config().GetVersion().Compare(cfgv2.Version)).To(Equal(0))
    96  		})
    97  
    98  		It("should fail if no file exists at the default path", func() {
    99  			err := s.Load()
   100  			Expect(err).To(HaveOccurred())
   101  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   102  		})
   103  
   104  		It("should fail if unable to identify the version of the file at the default path", func() {
   105  			Expect(afero.WriteFile(s.fs, DefaultPath, []byte(commentStr+unversionedFile), os.ModePerm)).To(Succeed())
   106  
   107  			err := s.Load()
   108  			Expect(err).To(HaveOccurred())
   109  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   110  		})
   111  
   112  		It("should fail if unable to create a Config for the version of the file at the default path", func() {
   113  			Expect(afero.WriteFile(s.fs, DefaultPath, []byte(commentStr+nonexistentVersionFile), os.ModePerm)).To(Succeed())
   114  
   115  			err := s.Load()
   116  			Expect(err).To(HaveOccurred())
   117  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   118  		})
   119  
   120  		It("should fail if unable to unmarshal the file at the default path", func() {
   121  			Expect(afero.WriteFile(s.fs, DefaultPath, []byte(commentStr+wrongFile), os.ModePerm)).To(Succeed())
   122  
   123  			err := s.Load()
   124  			Expect(err).To(HaveOccurred())
   125  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   126  		})
   127  	})
   128  
   129  	Context("LoadFrom", func() {
   130  		It("should load the Config from an existing file from the specified path", func() {
   131  			Expect(afero.WriteFile(s.fs, path, []byte(commentStr+v2File), os.ModePerm)).To(Succeed())
   132  
   133  			Expect(s.LoadFrom(path)).To(Succeed())
   134  			Expect(s.fs).NotTo(BeNil())
   135  			Expect(s.mustNotExist).To(BeFalse())
   136  			Expect(s.Config()).NotTo(BeNil())
   137  			Expect(s.Config().GetVersion().Compare(cfgv2.Version)).To(Equal(0))
   138  		})
   139  
   140  		It("should fail if no file exists at the specified path", func() {
   141  			err := s.LoadFrom(path)
   142  			Expect(err).To(HaveOccurred())
   143  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   144  		})
   145  
   146  		It("should fail if unable to identify the version of the file at the specified path", func() {
   147  			Expect(afero.WriteFile(s.fs, path, []byte(commentStr+unversionedFile), os.ModePerm)).To(Succeed())
   148  
   149  			err := s.LoadFrom(path)
   150  			Expect(err).To(HaveOccurred())
   151  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   152  		})
   153  
   154  		It("should fail if unable to create a Config for the version of the file at the specified path", func() {
   155  			Expect(afero.WriteFile(s.fs, path, []byte(commentStr+nonexistentVersionFile), os.ModePerm)).To(Succeed())
   156  
   157  			err := s.LoadFrom(path)
   158  			Expect(err).To(HaveOccurred())
   159  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   160  		})
   161  
   162  		It("should fail if unable to unmarshal the file at the specified path", func() {
   163  			Expect(afero.WriteFile(s.fs, path, []byte(commentStr+wrongFile), os.ModePerm)).To(Succeed())
   164  
   165  			err := s.LoadFrom(path)
   166  			Expect(err).To(HaveOccurred())
   167  			Expect(errors.As(err, &store.LoadError{})).To(BeTrue())
   168  		})
   169  	})
   170  
   171  	Context("Save", func() {
   172  		It("should succeed for a valid config", func() {
   173  			s.cfg = cfgv2.New()
   174  			Expect(s.Save()).To(Succeed())
   175  
   176  			cfgBytes, err := afero.ReadFile(s.fs, DefaultPath)
   177  			Expect(err).NotTo(HaveOccurred())
   178  			Expect(string(cfgBytes)).To(Equal(commentStr + v2File))
   179  		})
   180  
   181  		It("should succeed for a valid config that must not exist", func() {
   182  			s.cfg = cfgv2.New()
   183  			s.mustNotExist = true
   184  			Expect(s.Save()).To(Succeed())
   185  
   186  			cfgBytes, err := afero.ReadFile(s.fs, DefaultPath)
   187  			Expect(err).NotTo(HaveOccurred())
   188  			Expect(string(cfgBytes)).To(Equal(commentStr + v2File))
   189  		})
   190  
   191  		It("should fail for an empty config", func() {
   192  			err := s.Save()
   193  			Expect(err).To(HaveOccurred())
   194  			Expect(errors.As(err, &store.SaveError{})).To(BeTrue())
   195  		})
   196  
   197  		It("should fail for a pre-existent file that must not exist", func() {
   198  			s.cfg = cfgv2.New()
   199  			s.mustNotExist = true
   200  			Expect(afero.WriteFile(s.fs, DefaultPath, []byte(v2File), os.ModePerm)).To(Succeed())
   201  
   202  			err := s.Save()
   203  			Expect(err).To(HaveOccurred())
   204  			Expect(errors.As(err, &store.SaveError{})).To(BeTrue())
   205  		})
   206  	})
   207  
   208  	Context("SaveTo", func() {
   209  		It("should success for valid configs", func() {
   210  			s.cfg = cfgv2.New()
   211  			Expect(s.SaveTo(path)).To(Succeed())
   212  
   213  			cfgBytes, err := afero.ReadFile(s.fs, path)
   214  			Expect(err).NotTo(HaveOccurred())
   215  			Expect(string(cfgBytes)).To(Equal(commentStr + v2File))
   216  		})
   217  
   218  		It("should succeed for a valid config that must not exist", func() {
   219  			s.cfg = cfgv2.New()
   220  			s.mustNotExist = true
   221  			Expect(s.SaveTo(path)).To(Succeed())
   222  
   223  			cfgBytes, err := afero.ReadFile(s.fs, path)
   224  			Expect(err).NotTo(HaveOccurred())
   225  			Expect(string(cfgBytes)).To(Equal(commentStr + v2File))
   226  		})
   227  
   228  		It("should fail for an empty config", func() {
   229  			err := s.SaveTo(path)
   230  			Expect(err).To(HaveOccurred())
   231  			Expect(errors.As(err, &store.SaveError{})).To(BeTrue())
   232  		})
   233  
   234  		It("should fail for a pre-existent file that must not exist", func() {
   235  			s.cfg = cfgv2.New()
   236  			s.mustNotExist = true
   237  			Expect(afero.WriteFile(s.fs, path, []byte(v2File), os.ModePerm)).To(Succeed())
   238  
   239  			err := s.SaveTo(path)
   240  			Expect(err).To(HaveOccurred())
   241  			Expect(errors.As(err, &store.SaveError{})).To(BeTrue())
   242  		})
   243  	})
   244  })