test(zfspv): minikube setup for travis

to run integration test cases

Signed-off-by: Pawan <pawan@mayadata.io>
This commit is contained in:
Pawan 2019-11-26 17:09:07 +05:30 committed by Kiran Mova
parent 7ab6156b98
commit d933b47c75
27 changed files with 4933 additions and 5 deletions

115
tests/sc/build.go Normal file
View file

@ -0,0 +1,115 @@
/*
Copyright 2019 The OpenEBS Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sc
import (
"github.com/openebs/zfs-localpv/pkg/common/errors"
storagev1 "k8s.io/api/storage/v1"
)
// Builder enables building an instance of StorageClass
type Builder struct {
sc *StorageClass
errs []error
}
// NewBuilder returns new instance of Builder
func NewBuilder() *Builder {
return &Builder{sc: &StorageClass{object: &storagev1.StorageClass{}}}
}
// WithName sets the Name field of storageclass with provided argument.
func (b *Builder) WithName(name string) *Builder {
if len(name) == 0 {
b.errs = append(b.errs, errors.New("failed to build storageclass: missing storageclass name"))
return b
}
b.sc.object.Name = name
return b
}
// WithGenerateName appends a random string after the name
func (b *Builder) WithGenerateName(name string) *Builder {
b.sc.object.GenerateName = name + "-"
return b
}
// WithAnnotations sets the Annotations field of storageclass with provided value.
func (b *Builder) WithAnnotations(annotations map[string]string) *Builder {
if len(annotations) == 0 {
b.errs = append(b.errs, errors.New("failed to build storageclass: missing annotations"))
}
b.sc.object.Annotations = annotations
return b
}
// WithParametersNew resets existing parameters if any with
// ones that are provided here
func (b *Builder) WithParametersNew(parameters map[string]string) *Builder {
if len(parameters) == 0 {
b.errs = append(
b.errs,
errors.New("failed to build storageclass object: no new parameters"),
)
return b
}
// copy of original map
newparameters := map[string]string{}
for key, value := range parameters {
newparameters[key] = value
}
// override
b.sc.object.Parameters = newparameters
return b
}
// WithProvisioner sets the Provisioner field of storageclass with provided argument.
func (b *Builder) WithProvisioner(provisioner string) *Builder {
if len(provisioner) == 0 {
b.errs = append(b.errs, errors.New("failed to build storageclass: missing provisioner name"))
return b
}
b.sc.object.Provisioner = provisioner
return b
}
// WithVolumeExpansion sets the AllowedVolumeExpansion field of storageclass with provided argument.
func (b *Builder) WithVolumeExpansion(expansionAllowed bool) *Builder {
b.sc.object.AllowVolumeExpansion = &expansionAllowed
return b
}
// Build returns the StorageClass API instance
func (b *Builder) Build() (*storagev1.StorageClass, error) {
if len(b.errs) > 0 {
return nil, errors.Errorf("%+v", b.errs)
}
return b.sc.object, nil
}
// WithVolumeBindingMode sets the volume binding mode of storageclass with
// provided argument.
func (b *Builder) WithVolumeBindingMode(bindingMode storagev1.VolumeBindingMode) *Builder {
if bindingMode == "" {
b.errs = append(b.errs, errors.New("failed to build storageclass: missing volume binding mode"))
return b
}
b.sc.object.VolumeBindingMode = &bindingMode
return b
}

102
tests/sc/buildlist.go Normal file
View file

@ -0,0 +1,102 @@
/*
Copyright 2019 The OpenEBS Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sc
import (
"github.com/openebs/zfs-localpv/pkg/common/errors"
storagev1 "k8s.io/api/storage/v1"
)
// ListBuilder enables building an instance of StorageClassList
type ListBuilder struct {
list *StorageClassList
filters predicateList
errs []error
}
// NewListBuilder returns a instance of ListBuilder
func NewListBuilder() *ListBuilder {
return &ListBuilder{list: &StorageClassList{items: []*StorageClass{}}}
}
// ListBuilderForAPIList builds the ListBuilder object based on SC API list
func ListBuilderForAPIList(scl *storagev1.StorageClassList) *ListBuilder {
b := &ListBuilder{list: &StorageClassList{}}
if scl == nil {
b.errs = append(b.errs, errors.New("failed to build storageclass list: missing api list"))
return b
}
for _, sc := range scl.Items {
sc := sc
b.list.items = append(b.list.items, &StorageClass{object: &sc})
}
return b
}
// ListBuilderForObjects returns a instance of ListBuilder from SC instances
func ListBuilderForObjects(scl *StorageClassList) *ListBuilder {
b := &ListBuilder{list: &StorageClassList{}}
if scl == nil {
b.errs = append(b.errs, errors.New("failed to build storageclass list: missing object list"))
return b
}
b.list = scl
return b
}
// List returns the list of StorageClass instances that was built by this builder
func (b *ListBuilder) List() (*StorageClassList, error) {
if len(b.errs) > 0 {
return nil, errors.Errorf("failed to list storageclass: %+v", b.errs)
}
if b.filters == nil || len(b.filters) == 0 {
return b.list, nil
}
filtered := &StorageClassList{}
for _, sc := range b.list.items {
if b.filters.all(sc) {
sc := sc // Pin it
filtered.items = append(filtered.items, sc)
}
}
return filtered, nil
}
// WithFilter add filters on which the StorageClass has to be filtered
func (b *ListBuilder) WithFilter(pred ...Predicate) *ListBuilder {
b.filters = append(b.filters, pred...)
return b
}
// APIList builds core API PVC list using listbuilder
func (b *ListBuilder) APIList() (*storagev1.StorageClassList, error) {
l, err := b.List()
if err != nil {
return nil, err
}
return l.ToAPIList(), nil
}
// Len returns the number of items present
// in the PVCList of a builder
func (b *ListBuilder) Len() (int, error) {
l, err := b.List()
if err != nil {
return 0, err
}
return l.Len(), nil
}

193
tests/sc/kubernetes.go Normal file
View file

@ -0,0 +1,193 @@
/*
Copyright 2019 The OpenEBS Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sc
import (
"github.com/openebs/zfs-localpv/pkg/common/errors"
client "github.com/openebs/zfs-localpv/pkg/common/kubernetes/client"
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// getClientsetFn is a typed function that abstracts
// fetching an instance of kubernetes clientset
type getClientsetFn func() (clientset *kubernetes.Clientset, err error)
// getClientsetFromPathFn is a typed function that
// abstracts fetching of clientset from kubeConfigPath
type getClientsetForPathFn func(kubeConfigPath string) (clientset *kubernetes.Clientset, err error)
// listFn is a typed function that abstracts
// listing of storageclasses
type listFn func(cli *kubernetes.Clientset, opts metav1.ListOptions) (*storagev1.StorageClassList, error)
// getFn is a typed function that abstracts
// fetching an instance of storageclass
type getFn func(cli *kubernetes.Clientset, name string, opts metav1.GetOptions) (*storagev1.StorageClass, error)
// createFn is a typed function that abstracts
// to create storage class
type createFn func(cli *kubernetes.Clientset, sc *storagev1.StorageClass) (*storagev1.StorageClass, error)
// deleteFn is a typed function that abstracts
// to delete storageclass
type deleteFn func(cli *kubernetes.Clientset, name string, opts *metav1.DeleteOptions) error
// Kubeclient enables kubernetes API operations on storageclass instance
type Kubeclient struct {
// clientset refers to storageclass clientset
// that will be responsible to
// make kubernetes API calls
clientset *kubernetes.Clientset
// kubeconfig path to get kubernetes clientset
kubeConfigPath string
// functions useful during mocking
getClientset getClientsetFn
getClientsetForPath getClientsetForPathFn
list listFn
get getFn
create createFn
del deleteFn
}
// KubeClientBuildOption defines the abstraction
// to build a kubeclient instance
type KubeClientBuildOption func(*Kubeclient)
func (k *Kubeclient) withDefaults() {
if k.getClientset == nil {
k.getClientset = func() (clients *kubernetes.Clientset, err error) {
return client.New().Clientset()
}
}
if k.getClientsetForPath == nil {
k.getClientsetForPath = func(kubeConfigPath string) (clients *kubernetes.Clientset, err error) {
return client.New(client.WithKubeConfigPath(kubeConfigPath)).Clientset()
}
}
if k.list == nil {
k.list = func(cli *kubernetes.Clientset, opts metav1.ListOptions) (*storagev1.StorageClassList, error) {
return cli.StorageV1().StorageClasses().List(opts)
}
}
if k.get == nil {
k.get = func(cli *kubernetes.Clientset, name string, opts metav1.GetOptions) (*storagev1.StorageClass, error) {
return cli.StorageV1().StorageClasses().Get(name, opts)
}
}
if k.create == nil {
k.create = func(cli *kubernetes.Clientset, sc *storagev1.StorageClass) (*storagev1.StorageClass, error) {
return cli.StorageV1().StorageClasses().Create(sc)
}
}
if k.del == nil {
k.del = func(cli *kubernetes.Clientset, name string, opts *metav1.DeleteOptions) error {
return cli.StorageV1().StorageClasses().Delete(name, opts)
}
}
}
// NewKubeClient returns a new instance of kubeclient meant for storageclass
func NewKubeClient(opts ...KubeClientBuildOption) *Kubeclient {
k := &Kubeclient{}
for _, o := range opts {
o(k)
}
k.withDefaults()
return k
}
// WithClientSet sets the kubernetes client against
// the kubeclient instance
func WithClientSet(c *kubernetes.Clientset) KubeClientBuildOption {
return func(k *Kubeclient) {
k.clientset = c
}
}
// WithKubeConfigPath sets the kubeConfig path
// against client instance
func WithKubeConfigPath(path string) KubeClientBuildOption {
return func(k *Kubeclient) {
k.kubeConfigPath = path
}
}
func (k *Kubeclient) getClientsetForPathOrDirect() (*kubernetes.Clientset, error) {
if k.kubeConfigPath != "" {
return k.getClientsetForPath(k.kubeConfigPath)
}
return k.getClientset()
}
// getClientsetOrCached returns either a new
// instance of kubernetes clientset or its
// cached copy cached copy
func (k *Kubeclient) getClientsetOrCached() (*kubernetes.Clientset, error) {
if k.clientset != nil {
return k.clientset, nil
}
cs, err := k.getClientsetForPathOrDirect()
if err != nil {
return nil, errors.Wrapf(err, "failed to get clientset")
}
k.clientset = cs
return k.clientset, nil
}
// List returns a list of storageclass instances present in kubernetes cluster
func (k *Kubeclient) List(opts metav1.ListOptions) (*storagev1.StorageClassList, error) {
cli, err := k.getClientsetOrCached()
if err != nil {
return nil, errors.Wrapf(err, "failed to list storageclasses")
}
return k.list(cli, opts)
}
// Get return a storageclass instance present in kubernetes cluster
func (k *Kubeclient) Get(name string, opts metav1.GetOptions) (*storagev1.StorageClass, error) {
cli, err := k.getClientsetOrCached()
if err != nil {
return nil, errors.Wrapf(err, "failed to get storageclass {%s}", name)
}
return k.get(cli, name, opts)
}
// Create creates and returns a storageclass instance
func (k *Kubeclient) Create(sc *storagev1.StorageClass) (*storagev1.StorageClass, error) {
if sc == nil {
return nil, errors.New("failed to create storageclass: nil storageclass object")
}
cli, err := k.getClientsetOrCached()
if err != nil {
return nil, errors.Wrapf(err, "failed to create storageclass")
}
return k.create(cli, sc)
}
// Delete deletes the storageclass if present in kubernetes cluster
func (k *Kubeclient) Delete(name string, opts *metav1.DeleteOptions) error {
cli, err := k.getClientsetOrCached()
if err != nil {
return errors.Wrapf(err, "failed to delete storageclass: {%s}", name)
}
return k.del(cli, name, opts)
}

73
tests/sc/storageclass.go Normal file
View file

@ -0,0 +1,73 @@
/*
Copyright 2019 The OpenEBS Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sc
import (
storagev1 "k8s.io/api/storage/v1"
)
// StorageClass is a wrapper over API based
// storage class instance
type StorageClass struct {
object *storagev1.StorageClass
}
// StorageClassList holds the list of StorageClass instances
type StorageClassList struct {
items []*StorageClass
}
// Predicate defines an abstraction
// to determine conditional checks
// against the provided StorageClass instance
type Predicate func(*StorageClass) bool
// predicateList holds the list of predicates
type predicateList []Predicate
// ToAPIList converts StorageClassList to API StorageClassList
func (scl *StorageClassList) ToAPIList() *storagev1.StorageClassList {
sclist := &storagev1.StorageClassList{}
for _, sc := range scl.items {
sc := sc // Pin it
sclist.Items = append(sclist.Items, *sc.object)
}
return sclist
}
// all returns true if all the predicateList
// succeed against the provided StorageClass
// instance
func (l predicateList) all(sc *StorageClass) bool {
for _, pred := range l {
if !pred(sc) {
return false
}
}
return true
}
// Len returns the number of items present in the StorageClassList
func (scl *StorageClassList) Len() int {
return len(scl.items)
}
// NewForAPIObject returns a new instance of StorageClass
func NewForAPIObject(obj *storagev1.StorageClass) *StorageClass {
sc := &StorageClass{object: obj}
return sc
}