Initial commit

Signed-off-by: Andy Goldstein <andy.goldstein@gmail.com>
This commit is contained in:
Andy Goldstein
2017-08-02 13:27:17 -04:00
commit 2fe501f527
2024 changed files with 948288 additions and 0 deletions
+106
View File
@@ -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)
})
}
}
+114
View File
@@ -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
}
+44
View File
@@ -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")
}
}
}
+67
View File
@@ -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
}
+37
View File
@@ -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
}
}
+57
View File
@@ -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)
}
+66
View File
@@ -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)
}
+49
View File
@@ -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")
}
+81
View File
@@ -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
}
}
+106
View File
@@ -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
}
+62
View File
@@ -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
}
+61
View File
@@ -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
}