mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-09-12 02:56:31 +00:00
Initial commit
Signed-off-by: Andy Goldstein <andy.goldstein@gmail.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 collections
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// IncludesExcludes is a type that manages lists of included
|
||||
// and excluded items. The logic implemented is that everything
|
||||
// in the included list except those items in the excluded list
|
||||
// should be included. '*' in the includes list means "include
|
||||
// everything", but it is not valid in the exclude list.
|
||||
type IncludesExcludes struct {
|
||||
includes sets.String
|
||||
excludes sets.String
|
||||
}
|
||||
|
||||
func NewIncludesExcludes() *IncludesExcludes {
|
||||
return &IncludesExcludes{
|
||||
includes: sets.NewString(),
|
||||
excludes: sets.NewString(),
|
||||
}
|
||||
}
|
||||
|
||||
// Includes adds items to the includes list. '*' is a wildcard
|
||||
// value meaning "include everything".
|
||||
func (ie *IncludesExcludes) Includes(includes ...string) *IncludesExcludes {
|
||||
ie.includes.Insert(includes...)
|
||||
return ie
|
||||
}
|
||||
|
||||
// GetIncludes returns the items in the includes list
|
||||
func (ie *IncludesExcludes) GetIncludes() []string {
|
||||
return ie.includes.List()
|
||||
}
|
||||
|
||||
// Excludes adds items to the excludes list
|
||||
func (ie *IncludesExcludes) Excludes(excludes ...string) *IncludesExcludes {
|
||||
ie.excludes.Insert(excludes...)
|
||||
return ie
|
||||
}
|
||||
|
||||
// GetExcludes returns the items in the excludes list
|
||||
func (ie *IncludesExcludes) GetExcludes() []string {
|
||||
return ie.excludes.List()
|
||||
}
|
||||
|
||||
// ShouldInclude returns whether the specified item should be
|
||||
// included or not. Everything in the includes list except those
|
||||
// items in the excludes list should be included.
|
||||
func (ie *IncludesExcludes) ShouldInclude(s string) bool {
|
||||
if ie.excludes.Has(s) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ie.includes.Has("*") || ie.includes.Has(s)
|
||||
}
|
||||
|
||||
func ValidateIncludesExcludes(includesList, excludesList []string) []error {
|
||||
// TODO we should not allow an IncludesExcludes object to be created that
|
||||
// does not meet these criteria. Do a more significant refactoring to embed
|
||||
// this logic in object creation/modification.
|
||||
|
||||
var errs []error
|
||||
|
||||
includes := sets.NewString(includesList...)
|
||||
excludes := sets.NewString(excludesList...)
|
||||
|
||||
if includes.Len() == 0 {
|
||||
errs = append(errs, errors.New("includes list cannot be empty"))
|
||||
}
|
||||
|
||||
if includes.Len() > 1 && includes.Has("*") {
|
||||
errs = append(errs, errors.New("includes list must either contain '*' only, or a non-empty list of items"))
|
||||
}
|
||||
|
||||
if excludes.Has("*") {
|
||||
errs = append(errs, errors.New("excludes list cannot contain '*'"))
|
||||
}
|
||||
|
||||
for _, itm := range excludes.List() {
|
||||
if includes.Has(itm) {
|
||||
errs = append(errs, errors.New(fmt.Sprintf("excludes list cannot contain an item in the includes list: %v", itm)))
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 collections
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestShouldInclude(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
includes []string
|
||||
excludes []string
|
||||
check string
|
||||
should bool
|
||||
}{
|
||||
{
|
||||
name: "empty - don't include anything",
|
||||
check: "foo",
|
||||
should: false,
|
||||
},
|
||||
{
|
||||
name: "include *",
|
||||
includes: []string{"*"},
|
||||
check: "foo",
|
||||
should: true,
|
||||
},
|
||||
{
|
||||
name: "include specific - found",
|
||||
includes: []string{"foo", "bar", "baz"},
|
||||
check: "foo",
|
||||
should: true,
|
||||
},
|
||||
{
|
||||
name: "include specific - not found",
|
||||
includes: []string{"foo", "baz"},
|
||||
check: "bar",
|
||||
should: false,
|
||||
},
|
||||
{
|
||||
name: "include *, exclude foo",
|
||||
includes: []string{"*"},
|
||||
excludes: []string{"foo"},
|
||||
check: "foo",
|
||||
should: false,
|
||||
},
|
||||
{
|
||||
name: "include *, exclude foo, check bar",
|
||||
includes: []string{"*"},
|
||||
excludes: []string{"foo"},
|
||||
check: "bar",
|
||||
should: true,
|
||||
},
|
||||
{
|
||||
name: "both include and exclude foo",
|
||||
includes: []string{"foo"},
|
||||
excludes: []string{"foo"},
|
||||
check: "foo",
|
||||
should: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
i := NewIncludesExcludes().Includes(test.includes...).Excludes(test.excludes...)
|
||||
if e, a := test.should, i.ShouldInclude(test.check); e != a {
|
||||
t.Errorf("expected %t, got %t", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIncludesExcludes(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
includes []string
|
||||
excludes []string
|
||||
expected []error
|
||||
}{
|
||||
{
|
||||
name: "include nothing not allowed",
|
||||
includes: []string{},
|
||||
expected: []error{errors.New("includes list cannot be empty")},
|
||||
},
|
||||
{
|
||||
name: "include everything",
|
||||
includes: []string{"*"},
|
||||
},
|
||||
{
|
||||
name: "include everything not allowed with other includes",
|
||||
includes: []string{"*", "foo"},
|
||||
expected: []error{errors.New("includes list must either contain '*' only, or a non-empty list of items")},
|
||||
},
|
||||
{
|
||||
name: "exclude everything not allowed",
|
||||
includes: []string{"foo"},
|
||||
excludes: []string{"*"},
|
||||
expected: []error{errors.New("excludes list cannot contain '*'")},
|
||||
},
|
||||
{
|
||||
name: "excludes cannot contain items in includes",
|
||||
includes: []string{"foo", "bar"},
|
||||
excludes: []string{"bar"},
|
||||
expected: []error{errors.New("excludes list cannot contain an item in the includes list: bar")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
res := ValidateIncludesExcludes(test.includes, test.excludes)
|
||||
|
||||
assert.Equal(t, test.expected, res)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 collections
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetValue returns the object at root[path], where path is a dot separated string.
|
||||
func GetValue(root map[string]interface{}, path string) (interface{}, error) {
|
||||
if root == nil {
|
||||
return "", errors.New("root is nil")
|
||||
}
|
||||
|
||||
pathParts := strings.Split(path, ".")
|
||||
key := pathParts[0]
|
||||
|
||||
obj, found := root[pathParts[0]]
|
||||
if !found {
|
||||
return "", fmt.Errorf("key %v not found", pathParts[0])
|
||||
}
|
||||
|
||||
if len(pathParts) == 1 {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
subMap, ok := obj.(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("value at key %v is not a map[string]interface{}", key)
|
||||
}
|
||||
|
||||
return GetValue(subMap, strings.Join(pathParts[1:], "."))
|
||||
}
|
||||
|
||||
// GetString returns the string at root[path], where path is a dot separated string.
|
||||
func GetString(root map[string]interface{}, path string) (string, error) {
|
||||
obj, err := GetValue(root, path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
str, ok := obj.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("value at path %v is not a string", path)
|
||||
}
|
||||
|
||||
return str, nil
|
||||
}
|
||||
|
||||
// GetMap returns the map at root[path], where path is a dot separated string.
|
||||
func GetMap(root map[string]interface{}, path string) (map[string]interface{}, error) {
|
||||
obj, err := GetValue(root, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, ok := obj.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("value at path %v is not a map[string]interface{}", path)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetSlice returns the slice at root[path], where path is a dot separated string.
|
||||
func GetSlice(root map[string]interface{}, path string) ([]interface{}, error) {
|
||||
obj, err := GetValue(root, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, ok := obj.([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("value at path %v is not a []interface{}", path)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ForEach calls fn on each object in the root[path] array, where path is a dot separated string.
|
||||
func ForEach(root map[string]interface{}, path string, fn func(obj map[string]interface{}) error) error {
|
||||
s, err := GetSlice(root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range s {
|
||||
obj, ok := s[i].(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("unable to convert %s[%d] to an object", path, i)
|
||||
}
|
||||
if err := fn(obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 collections
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetString(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
root map[string]interface{}
|
||||
path string
|
||||
expectErr bool
|
||||
result string
|
||||
}{
|
||||
{map[string]interface{}{"path": "value"}, "path", false, "value"},
|
||||
{map[string]interface{}{"path": "value"}, "path2", true, ""},
|
||||
{map[string]interface{}{"path1": map[string]interface{}{"path2": "value"}}, "path1.path2", false, "value"},
|
||||
{map[string]interface{}{"path1": map[string]interface{}{"path2": "value"}}, "path1.path1", true, ""},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
res, err := GetString(tc.root, tc.path)
|
||||
|
||||
if (err != nil) != tc.expectErr {
|
||||
t.Error("err")
|
||||
}
|
||||
if res != tc.result {
|
||||
t.Error("res")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 encode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
"github.com/heptio/ark/pkg/generated/clientset/scheme"
|
||||
)
|
||||
|
||||
// Encode converts the provided object to the specified format
|
||||
// and returns a byte slice of the encoded data.
|
||||
func Encode(obj runtime.Object, format string) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if err := EncodeTo(obj, format, buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// EncodeTo converts the provided object to the specified format and
|
||||
// writes the encoded data to the provided io.Writer.
|
||||
func EncodeTo(obj runtime.Object, format string, w io.Writer) error {
|
||||
encoder, err := EncoderFor(format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return encoder.Encode(obj, w)
|
||||
}
|
||||
|
||||
// EncoderFor gets the appropriate encoder for the specified format.
|
||||
func EncoderFor(format string) (runtime.Encoder, error) {
|
||||
var encoder runtime.Encoder
|
||||
desiredMediaType := fmt.Sprintf("application/%s", format)
|
||||
serializerInfo, found := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), desiredMediaType)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("unable to locate an encoder for %q", desiredMediaType)
|
||||
}
|
||||
if serializerInfo.PrettySerializer != nil {
|
||||
encoder = serializerInfo.PrettySerializer
|
||||
} else {
|
||||
encoder = serializerInfo.Serializer
|
||||
}
|
||||
encoder = scheme.Codecs.EncoderForVersion(encoder, v1.SchemeGroupVersion)
|
||||
return encoder, nil
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 kube
|
||||
|
||||
import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
)
|
||||
|
||||
// EnsureNamespaceExists attempts to create the provided Kubernetes namespace. It returns two values:
|
||||
// a bool indicating whether or not the namespace was created, and an error if the create failed
|
||||
// for a reason other than that the namespace already exists. Note that in the case where the
|
||||
// namespace already exists, this function will return (false, nil).
|
||||
func EnsureNamespaceExists(namespace *v1.Namespace, client corev1.NamespaceInterface) (bool, error) {
|
||||
if _, err := client.Create(namespace); err == nil {
|
||||
return true, nil
|
||||
} else if apierrors.IsAlreadyExists(err) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
)
|
||||
|
||||
type FakeBackupService struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (f *FakeBackupService) GetAllBackups(bucket string) ([]*v1.Backup, error) {
|
||||
args := f.Called(bucket)
|
||||
|
||||
var backups []*v1.Backup
|
||||
|
||||
b := args.Get(0)
|
||||
if b != nil {
|
||||
backups = b.([]*v1.Backup)
|
||||
}
|
||||
|
||||
return backups, args.Error(1)
|
||||
}
|
||||
|
||||
func (f *FakeBackupService) UploadBackup(bucket, name string, metadata, backup io.ReadSeeker) error {
|
||||
args := f.Called(bucket, name, metadata, backup)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (f *FakeBackupService) DownloadBackup(bucket, name string) (io.ReadCloser, error) {
|
||||
args := f.Called(bucket, name)
|
||||
return args.Get(0).(io.ReadCloser), args.Error(1)
|
||||
}
|
||||
|
||||
func (f *FakeBackupService) DeleteBackup(bucket, backupName string) error {
|
||||
args := f.Called(bucket, backupName)
|
||||
return args.Error(0)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"github.com/heptio/ark/pkg/client"
|
||||
)
|
||||
|
||||
type FakeDynamicFactory struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
var _ client.DynamicFactory = &FakeDynamicFactory{}
|
||||
|
||||
func (df *FakeDynamicFactory) ClientForGroupVersionResource(gvr schema.GroupVersionResource, resource metav1.APIResource, namespace string) (client.Dynamic, error) {
|
||||
args := df.Called(gvr, resource, namespace)
|
||||
return args.Get(0).(client.Dynamic), args.Error(1)
|
||||
}
|
||||
|
||||
func (df *FakeDynamicFactory) ClientForGroupVersionKind(gvk schema.GroupVersionKind, resource metav1.APIResource, namespace string) (client.Dynamic, error) {
|
||||
args := df.Called(gvk, resource, namespace)
|
||||
return args.Get(0).(client.Dynamic), args.Error(1)
|
||||
}
|
||||
|
||||
type FakeDynamicClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
var _ client.Dynamic = &FakeDynamicClient{}
|
||||
|
||||
func (c *FakeDynamicClient) List(options metav1.ListOptions) (runtime.Object, error) {
|
||||
args := c.Called(options)
|
||||
return args.Get(0).(runtime.Object), args.Error(1)
|
||||
}
|
||||
|
||||
func (c *FakeDynamicClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||
args := c.Called(obj)
|
||||
return args.Get(0).(*unstructured.Unstructured), args.Error(1)
|
||||
}
|
||||
|
||||
func (c *FakeDynamicClient) Watch(options metav1.ListOptions) (watch.Interface, error) {
|
||||
args := c.Called(options)
|
||||
return args.Get(0).(watch.Interface), args.Error(1)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type FakeMapper struct {
|
||||
meta.RESTMapper
|
||||
AutoReturnResource bool
|
||||
Resources map[schema.GroupVersionResource]schema.GroupVersionResource
|
||||
}
|
||||
|
||||
func (m *FakeMapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) {
|
||||
if m.AutoReturnResource {
|
||||
return schema.GroupVersionResource{
|
||||
Group: input.Group,
|
||||
Version: input.Version,
|
||||
Resource: input.Resource,
|
||||
}, nil
|
||||
}
|
||||
if m.Resources == nil {
|
||||
return schema.GroupVersionResource{}, errors.New("invalid resource")
|
||||
}
|
||||
|
||||
if gr, found := m.Resources[input]; found {
|
||||
return gr, nil
|
||||
}
|
||||
|
||||
return schema.GroupVersionResource{}, errors.New("invalid resource")
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
)
|
||||
|
||||
type FakeSnapshotService struct {
|
||||
// SnapshotID->VolumeID
|
||||
SnapshotsTaken sets.String
|
||||
|
||||
// VolumeID -> (SnapshotID, Type, Iops)
|
||||
SnapshottableVolumes map[string]api.VolumeBackupInfo
|
||||
|
||||
// VolumeBackupInfo -> VolumeID
|
||||
RestorableVolumes map[api.VolumeBackupInfo]string
|
||||
}
|
||||
|
||||
func (s *FakeSnapshotService) GetAllSnapshots() ([]string, error) {
|
||||
return s.SnapshotsTaken.List(), nil
|
||||
}
|
||||
|
||||
func (s *FakeSnapshotService) CreateSnapshot(volumeID string) (string, error) {
|
||||
if _, exists := s.SnapshottableVolumes[volumeID]; !exists {
|
||||
return "", errors.New("snapshottable volume not found")
|
||||
}
|
||||
|
||||
if s.SnapshotsTaken == nil {
|
||||
s.SnapshotsTaken = sets.NewString()
|
||||
}
|
||||
s.SnapshotsTaken.Insert(s.SnapshottableVolumes[volumeID].SnapshotID)
|
||||
|
||||
return s.SnapshottableVolumes[volumeID].SnapshotID, nil
|
||||
}
|
||||
|
||||
func (s *FakeSnapshotService) CreateVolumeFromSnapshot(snapshotID, volumeType string, iops *int) (string, error) {
|
||||
key := api.VolumeBackupInfo{
|
||||
SnapshotID: snapshotID,
|
||||
Type: volumeType,
|
||||
Iops: iops,
|
||||
}
|
||||
|
||||
return s.RestorableVolumes[key], nil
|
||||
}
|
||||
|
||||
func (s *FakeSnapshotService) DeleteSnapshot(snapshotID string) error {
|
||||
if !s.SnapshotsTaken.Has(snapshotID) {
|
||||
return errors.New("snapshot not found")
|
||||
}
|
||||
|
||||
s.SnapshotsTaken.Delete(snapshotID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FakeSnapshotService) GetVolumeInfo(volumeID string) (string, *int, error) {
|
||||
if volumeInfo, exists := s.SnapshottableVolumes[volumeID]; !exists {
|
||||
return "", nil, errors.New("VolumeID not found")
|
||||
} else {
|
||||
return volumeInfo.Type, volumeInfo.Iops, nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
)
|
||||
|
||||
type TestBackup struct {
|
||||
*v1.Backup
|
||||
}
|
||||
|
||||
func NewTestBackup() *TestBackup {
|
||||
return &TestBackup{
|
||||
Backup: &v1.Backup{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: v1.DefaultNamespace,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithNamespace(namespace string) *TestBackup {
|
||||
b.Namespace = namespace
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithName(name string) *TestBackup {
|
||||
b.Name = name
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithLabel(key, value string) *TestBackup {
|
||||
if b.Labels == nil {
|
||||
b.Labels = make(map[string]string)
|
||||
}
|
||||
b.Labels[key] = value
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithPhase(phase v1.BackupPhase) *TestBackup {
|
||||
b.Status.Phase = phase
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithIncludedResources(r ...string) *TestBackup {
|
||||
b.Spec.IncludedResources = r
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithExcludedResources(r ...string) *TestBackup {
|
||||
b.Spec.ExcludedResources = r
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithIncludedNamespaces(ns ...string) *TestBackup {
|
||||
b.Spec.IncludedNamespaces = ns
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithExcludedNamespaces(ns ...string) *TestBackup {
|
||||
b.Spec.ExcludedNamespaces = ns
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithTTL(ttl time.Duration) *TestBackup {
|
||||
b.Spec.TTL = metav1.Duration{Duration: ttl}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithExpiration(expiration time.Time) *TestBackup {
|
||||
b.Status.Expiration = metav1.Time{Time: expiration}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithVersion(version int) *TestBackup {
|
||||
b.Status.Version = version
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *TestBackup) WithSnapshot(pv string, snapshot string) *TestBackup {
|
||||
if b.Status.VolumeBackups == nil {
|
||||
b.Status.VolumeBackups = make(map[string]*v1.VolumeBackupInfo)
|
||||
}
|
||||
b.Status.VolumeBackups[pv] = &v1.VolumeBackupInfo{SnapshotID: snapshot}
|
||||
return b
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
)
|
||||
|
||||
type TestRestore struct {
|
||||
*api.Restore
|
||||
}
|
||||
|
||||
func NewTestRestore(ns, name string, phase api.RestorePhase) *TestRestore {
|
||||
return &TestRestore{
|
||||
Restore: &api.Restore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: ns,
|
||||
Name: name,
|
||||
},
|
||||
Spec: api.RestoreSpec{},
|
||||
Status: api.RestoreStatus{
|
||||
Phase: phase,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *TestRestore) WithRestorableNamespace(name string) *TestRestore {
|
||||
r.Spec.Namespaces = append(r.Spec.Namespaces, name)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *TestRestore) WithValidationError(err string) *TestRestore {
|
||||
r.Status.ValidationErrors = append(r.Status.ValidationErrors, err)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *TestRestore) WithBackup(name string) *TestRestore {
|
||||
r.Spec.BackupName = name
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *TestRestore) WithErrors(e api.RestoreResult) *TestRestore {
|
||||
r.Status.Errors = e
|
||||
return r
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2017 Heptio Inc.
|
||||
|
||||
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 test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
)
|
||||
|
||||
type TestSchedule struct {
|
||||
*api.Schedule
|
||||
}
|
||||
|
||||
func NewTestSchedule(namespace, name string) *TestSchedule {
|
||||
return &TestSchedule{
|
||||
Schedule: &api.Schedule{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *TestSchedule) WithPhase(phase api.SchedulePhase) *TestSchedule {
|
||||
s.Status.Phase = phase
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *TestSchedule) WithValidationError(msg string) *TestSchedule {
|
||||
s.Status.ValidationErrors = append(s.Status.ValidationErrors, msg)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *TestSchedule) WithCronSchedule(cronExpression string) *TestSchedule {
|
||||
s.Spec.Schedule = cronExpression
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *TestSchedule) WithLastBackupTime(timeString string) *TestSchedule {
|
||||
t, _ := time.Parse("2006-01-02 15:04:05", timeString)
|
||||
s.Status.LastBackup = metav1.Time{Time: t}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user