Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
304030a6
Commit
304030a6
authored
Mar 14, 2017
by
Maru Newby
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fed: Add integration test for secrets
parent
bc675650
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
820 additions
and
20 deletions
+820
-20
BUILD
federation/BUILD
+1
-0
BUILD
federation/pkg/typeadapters/BUILD
+42
-0
adapter.go
federation/pkg/typeadapters/adapter.go
+48
-0
BUILD
federation/pkg/typeadapters/crudtester/BUILD
+35
-0
crudtester.go
federation/pkg/typeadapters/crudtester/crudtester.go
+217
-0
secret.go
federation/pkg/typeadapters/secret.go
+93
-0
BUILD
test/integration/federation/BUILD
+5
-1
api_test.go
test/integration/federation/api_test.go
+2
-2
crud_test.go
test/integration/federation/crud_test.go
+68
-0
BUILD
test/integration/federation/framework/BUILD
+14
-0
api.go
test/integration/federation/framework/api.go
+19
-11
controller.go
test/integration/federation/framework/controller.go
+46
-0
crudtester.go
test/integration/federation/framework/crudtester.go
+47
-0
federation.go
test/integration/federation/framework/federation.go
+123
-0
secret.go
test/integration/federation/framework/secret.go
+49
-0
util.go
test/integration/federation/framework/util.go
+11
-6
No files found.
federation/BUILD
View file @
304030a6
...
...
@@ -29,6 +29,7 @@ filegroup(
"//federation/pkg/dnsprovider:all-srcs",
"//federation/pkg/federation-controller:all-srcs",
"//federation/pkg/kubefed:all-srcs",
"//federation/pkg/typeadapters:all-srcs",
"//federation/registry/cluster:all-srcs",
],
tags = ["automanaged"],
...
...
federation/pkg/typeadapters/BUILD
0 → 100644
View file @
304030a6
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"adapter.go",
"secret.go",
],
tags = ["automanaged"],
deps = [
"//federation/client/clientset_generated/federation_clientset:go_default_library",
"//federation/pkg/federation-controller/util:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/types",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//federation/pkg/typeadapters/crudtester:all-srcs",
],
tags = ["automanaged"],
)
federation/pkg/typeadapters/adapter.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
typeadapters
import
(
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
pkgruntime
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
federationclientset
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)
// FederatedTypeAdapter defines operations for interacting with a
// federated type. Code written to this interface can then target any
// type for which an implementation of this interface exists.
type
FederatedTypeAdapter
interface
{
SetClient
(
client
federationclientset
.
Interface
)
Kind
()
string
Equivalent
(
obj1
,
obj2
pkgruntime
.
Object
)
bool
ObjectMeta
(
obj
pkgruntime
.
Object
)
*
metav1
.
ObjectMeta
NamespacedName
(
obj
pkgruntime
.
Object
)
types
.
NamespacedName
// Fed* operations target the federation control plane
FedCreate
(
obj
pkgruntime
.
Object
)
(
pkgruntime
.
Object
,
error
)
FedGet
(
namespacedName
types
.
NamespacedName
)
(
pkgruntime
.
Object
,
error
)
FedUpdate
(
obj
pkgruntime
.
Object
)
(
pkgruntime
.
Object
,
error
)
FedDelete
(
namespacedName
types
.
NamespacedName
,
options
*
metav1
.
DeleteOptions
)
error
// The following operations are intended to target a cluster that is a member of a federation
ClusterGet
(
client
clientset
.
Interface
,
namespacedName
types
.
NamespacedName
)
(
pkgruntime
.
Object
,
error
)
NewTestObject
(
namespace
string
)
pkgruntime
.
Object
}
federation/pkg/typeadapters/crudtester/BUILD
0 → 100644
View file @
304030a6
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["crudtester.go"],
tags = ["automanaged"],
deps = [
"//federation/pkg/typeadapters:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/wait",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
federation/pkg/typeadapters/crudtester/crudtester.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
crudtester
import
(
"time"
"k8s.io/apimachinery/pkg/api/errors"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
pkgruntime
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/federation/pkg/typeadapters"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)
const
(
AnnotationTestFederationCRUDUpdate
string
=
"federation.kubernetes.io/test-federation-crud-update"
)
// TestLogger defines operations common across different types of testing
type
TestLogger
interface
{
Fatalf
(
format
string
,
args
...
interface
{})
Fatal
(
msg
string
)
Logf
(
format
string
,
args
...
interface
{})
}
// FederatedTypeCRUDTester exercises Create/Read/Update/Delete operations for
// federated types via the Federation API and validates that the
// results of those operations are propagated to clusters that are
// members of a federation.
type
FederatedTypeCRUDTester
struct
{
tl
TestLogger
adapter
typeadapters
.
FederatedTypeAdapter
kind
string
clusterClients
[]
clientset
.
Interface
waitInterval
time
.
Duration
// Federation operations will use wait.ForeverTestTimeout. Any
// operation that involves member clusters may take longer due to
// propagation latency.
clusterWaitTimeout
time
.
Duration
}
func
NewFederatedTypeCRUDTester
(
testLogger
TestLogger
,
adapter
typeadapters
.
FederatedTypeAdapter
,
clusterClients
[]
clientset
.
Interface
,
waitInterval
,
clusterWaitTimeout
time
.
Duration
)
*
FederatedTypeCRUDTester
{
return
&
FederatedTypeCRUDTester
{
tl
:
testLogger
,
adapter
:
adapter
,
kind
:
adapter
.
Kind
(),
clusterClients
:
clusterClients
,
waitInterval
:
waitInterval
,
clusterWaitTimeout
:
clusterWaitTimeout
,
}
}
func
(
c
*
FederatedTypeCRUDTester
)
CheckLifecycle
(
desiredObject
pkgruntime
.
Object
)
{
obj
:=
c
.
CheckCreate
(
desiredObject
)
c
.
CheckUpdate
(
obj
)
// Validate the golden path - removal of dependents
orphanDependents
:=
false
c
.
CheckDelete
(
obj
,
&
orphanDependents
)
}
func
(
c
*
FederatedTypeCRUDTester
)
CheckCreate
(
desiredObject
pkgruntime
.
Object
)
pkgruntime
.
Object
{
namespace
:=
c
.
adapter
.
ObjectMeta
(
desiredObject
)
.
Namespace
c
.
tl
.
Logf
(
"Creating new federated %s in namespace %q"
,
c
.
kind
,
namespace
)
obj
,
err
:=
c
.
adapter
.
FedCreate
(
desiredObject
)
if
err
!=
nil
{
c
.
tl
.
Fatalf
(
"Error creating federated %s in namespace %q : %v"
,
c
.
kind
,
namespace
,
err
)
}
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
c
.
tl
.
Logf
(
"Created new federated %s %q"
,
c
.
kind
,
namespacedName
)
c
.
CheckPropagation
(
obj
)
return
obj
}
func
(
c
*
FederatedTypeCRUDTester
)
CheckUpdate
(
obj
pkgruntime
.
Object
)
{
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
var
initialAnnotation
string
meta
:=
c
.
adapter
.
ObjectMeta
(
obj
)
if
meta
.
Annotations
!=
nil
{
initialAnnotation
=
meta
.
Annotations
[
AnnotationTestFederationCRUDUpdate
]
}
c
.
tl
.
Logf
(
"Updating federated %s %q"
,
c
.
kind
,
namespacedName
)
updatedObj
,
err
:=
c
.
updateFedObject
(
obj
)
if
err
!=
nil
{
c
.
tl
.
Fatalf
(
"Error updating federated %s %q: %v"
,
c
.
kind
,
namespacedName
,
err
)
}
// updateFedObject is expected to have changed the value of the annotation
meta
=
c
.
adapter
.
ObjectMeta
(
updatedObj
)
updatedAnnotation
:=
meta
.
Annotations
[
AnnotationTestFederationCRUDUpdate
]
if
updatedAnnotation
==
initialAnnotation
{
c
.
tl
.
Fatalf
(
"Federated %s %q not mutated"
,
c
.
kind
,
namespacedName
)
}
c
.
CheckPropagation
(
updatedObj
)
}
func
(
c
*
FederatedTypeCRUDTester
)
CheckDelete
(
obj
pkgruntime
.
Object
,
orphanDependents
*
bool
)
{
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
c
.
tl
.
Logf
(
"Deleting federated %s %q"
,
c
.
kind
,
namespacedName
)
err
:=
c
.
adapter
.
FedDelete
(
namespacedName
,
&
metav1
.
DeleteOptions
{
OrphanDependents
:
orphanDependents
})
if
err
!=
nil
{
c
.
tl
.
Fatalf
(
"Error deleting federated %s %q: %v"
,
c
.
kind
,
namespacedName
,
err
)
}
deletingInCluster
:=
(
orphanDependents
!=
nil
&&
*
orphanDependents
==
false
)
waitTimeout
:=
wait
.
ForeverTestTimeout
if
deletingInCluster
{
// May need extra time to delete both federation and cluster resources
waitTimeout
=
c
.
clusterWaitTimeout
}
// Wait for deletion. The federation resource will only be removed once orphan deletion has been
// completed or deemed unnecessary.
err
=
wait
.
PollImmediate
(
c
.
waitInterval
,
waitTimeout
,
func
()
(
bool
,
error
)
{
_
,
err
:=
c
.
adapter
.
FedGet
(
namespacedName
)
if
errors
.
IsNotFound
(
err
)
{
return
true
,
nil
}
return
false
,
err
})
if
err
!=
nil
{
c
.
tl
.
Fatalf
(
"Error deleting federated %s %q: %v"
,
c
.
kind
,
namespacedName
,
err
)
}
var
stateMsg
string
=
"present"
if
deletingInCluster
{
stateMsg
=
"not present"
}
for
_
,
client
:=
range
c
.
clusterClients
{
_
,
err
:=
c
.
adapter
.
ClusterGet
(
client
,
namespacedName
)
switch
{
case
!
deletingInCluster
&&
errors
.
IsNotFound
(
err
)
:
c
.
tl
.
Fatalf
(
"Federated %s %q was unexpectedly deleted from a member cluster"
,
c
.
kind
,
namespacedName
)
case
deletingInCluster
&&
err
==
nil
:
c
.
tl
.
Fatalf
(
"Federated %s %q was unexpectedly orphaned in a member cluster"
,
c
.
kind
,
namespacedName
)
case
err
!=
nil
&&
!
errors
.
IsNotFound
(
err
)
:
c
.
tl
.
Fatalf
(
"Error while checking whether %s %q is %s in member clusters: %v"
,
c
.
kind
,
namespacedName
,
stateMsg
,
err
)
}
}
}
func
(
c
*
FederatedTypeCRUDTester
)
CheckPropagation
(
obj
pkgruntime
.
Object
)
{
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
c
.
tl
.
Logf
(
"Waiting for %s %q in %d clusters"
,
c
.
kind
,
namespacedName
,
len
(
c
.
clusterClients
))
for
_
,
client
:=
range
c
.
clusterClients
{
err
:=
c
.
waitForResource
(
client
,
obj
)
if
err
!=
nil
{
c
.
tl
.
Fatalf
(
"Failed to verify %s %q in a member cluster: %v"
,
c
.
kind
,
namespacedName
,
err
)
}
}
}
func
(
c
*
FederatedTypeCRUDTester
)
waitForResource
(
client
clientset
.
Interface
,
obj
pkgruntime
.
Object
)
error
{
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
err
:=
wait
.
PollImmediate
(
c
.
waitInterval
,
c
.
clusterWaitTimeout
,
func
()
(
bool
,
error
)
{
clusterObj
,
err
:=
c
.
adapter
.
ClusterGet
(
client
,
namespacedName
)
if
err
==
nil
&&
c
.
adapter
.
Equivalent
(
clusterObj
,
obj
)
{
return
true
,
nil
}
if
errors
.
IsNotFound
(
err
)
{
return
false
,
nil
}
return
false
,
err
})
return
err
}
func
(
c
*
FederatedTypeCRUDTester
)
updateFedObject
(
obj
pkgruntime
.
Object
)
(
pkgruntime
.
Object
,
error
)
{
err
:=
wait
.
PollImmediate
(
c
.
waitInterval
,
wait
.
ForeverTestTimeout
,
func
()
(
bool
,
error
)
{
// Target the metadata for simplicity (it's type-agnostic)
meta
:=
c
.
adapter
.
ObjectMeta
(
obj
)
if
meta
.
Annotations
==
nil
{
meta
.
Annotations
=
make
(
map
[
string
]
string
)
}
meta
.
Annotations
[
AnnotationTestFederationCRUDUpdate
]
=
"updated"
_
,
err
:=
c
.
adapter
.
FedUpdate
(
obj
)
if
errors
.
IsConflict
(
err
)
{
// The resource was updated by the federation controller.
// Get the latest version and retry.
namespacedName
:=
c
.
adapter
.
NamespacedName
(
obj
)
obj
,
err
=
c
.
adapter
.
FedGet
(
namespacedName
)
return
false
,
err
}
// Be tolerant of a slow server
if
errors
.
IsServerTimeout
(
err
)
{
return
false
,
nil
}
return
(
err
==
nil
),
err
})
return
obj
,
err
}
federation/pkg/typeadapters/secret.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
typeadapters
import
(
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
pkgruntime
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
federationclientset
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
apiv1
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)
type
SecretAdapter
struct
{
client
federationclientset
.
Interface
}
func
NewSecretAdapter
(
client
federationclientset
.
Interface
)
*
SecretAdapter
{
return
&
SecretAdapter
{
client
:
client
}
}
func
(
a
*
SecretAdapter
)
SetClient
(
client
federationclientset
.
Interface
)
{
a
.
client
=
client
}
func
(
a
*
SecretAdapter
)
Kind
()
string
{
return
"secret"
}
func
(
a
*
SecretAdapter
)
Equivalent
(
obj1
,
obj2
pkgruntime
.
Object
)
bool
{
secret1
:=
obj1
.
(
*
apiv1
.
Secret
)
secret2
:=
obj2
.
(
*
apiv1
.
Secret
)
return
util
.
SecretEquivalent
(
*
secret1
,
*
secret2
)
}
func
(
a
*
SecretAdapter
)
ObjectMeta
(
obj
pkgruntime
.
Object
)
*
metav1
.
ObjectMeta
{
return
&
obj
.
(
*
apiv1
.
Secret
)
.
ObjectMeta
}
func
(
a
*
SecretAdapter
)
NamespacedName
(
obj
pkgruntime
.
Object
)
types
.
NamespacedName
{
secret
:=
obj
.
(
*
apiv1
.
Secret
)
return
types
.
NamespacedName
{
Namespace
:
secret
.
Namespace
,
Name
:
secret
.
Name
}
}
func
(
a
*
SecretAdapter
)
FedCreate
(
obj
pkgruntime
.
Object
)
(
pkgruntime
.
Object
,
error
)
{
secret
:=
obj
.
(
*
apiv1
.
Secret
)
return
a
.
client
.
CoreV1
()
.
Secrets
(
secret
.
Namespace
)
.
Create
(
secret
)
}
func
(
a
*
SecretAdapter
)
FedGet
(
namespacedName
types
.
NamespacedName
)
(
pkgruntime
.
Object
,
error
)
{
return
a
.
client
.
CoreV1
()
.
Secrets
(
namespacedName
.
Namespace
)
.
Get
(
namespacedName
.
Name
,
metav1
.
GetOptions
{})
}
func
(
a
*
SecretAdapter
)
FedUpdate
(
obj
pkgruntime
.
Object
)
(
pkgruntime
.
Object
,
error
)
{
secret
:=
obj
.
(
*
apiv1
.
Secret
)
return
a
.
client
.
CoreV1
()
.
Secrets
(
secret
.
Namespace
)
.
Update
(
secret
)
}
func
(
a
*
SecretAdapter
)
FedDelete
(
namespacedName
types
.
NamespacedName
,
options
*
metav1
.
DeleteOptions
)
error
{
return
a
.
client
.
CoreV1
()
.
Secrets
(
namespacedName
.
Namespace
)
.
Delete
(
namespacedName
.
Name
,
options
)
}
func
(
a
*
SecretAdapter
)
ClusterGet
(
client
clientset
.
Interface
,
namespacedName
types
.
NamespacedName
)
(
pkgruntime
.
Object
,
error
)
{
return
client
.
CoreV1
()
.
Secrets
(
namespacedName
.
Namespace
)
.
Get
(
namespacedName
.
Name
,
metav1
.
GetOptions
{})
}
func
(
a
*
SecretAdapter
)
NewTestObject
(
namespace
string
)
pkgruntime
.
Object
{
return
&
apiv1
.
Secret
{
ObjectMeta
:
metav1
.
ObjectMeta
{
GenerateName
:
"test-secret-"
,
Namespace
:
namespace
,
},
Data
:
map
[
string
][]
byte
{
"A"
:
[]
byte
(
"ala ma kota"
),
},
Type
:
apiv1
.
SecretTypeOpaque
,
}
}
test/integration/federation/BUILD
View file @
304030a6
...
...
@@ -9,7 +9,10 @@ load(
go_test(
name = "go_default_test",
srcs = ["api_test.go"],
srcs = [
"api_test.go",
"crud_test.go",
],
tags = ["automanaged"],
deps = [
"//federation/apis/federation/v1beta1:go_default_library",
...
...
@@ -18,6 +21,7 @@ go_test(
"//pkg/apis/batch/v1:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//test/integration/federation/framework:go_default_library",
"//vendor:github.com/pborman/uuid",
"//vendor:github.com/stretchr/testify/assert",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
...
...
test/integration/federation/api_test.go
View file @
304030a6
...
...
@@ -46,8 +46,8 @@ type apiTestFunc func(t *testing.T, host string)
func
TestFederationAPI
(
t
*
testing
.
T
)
{
f
:=
&
framework
.
FederationAPIFixture
{}
f
.
Set
u
p
(
t
)
defer
f
.
Tear
d
own
(
t
)
f
.
Set
U
p
(
t
)
defer
f
.
Tear
D
own
(
t
)
testCases
:=
map
[
string
]
apiTestFunc
{
"swaggerSpec"
:
testSwaggerSpec
,
...
...
test/integration/federation/crud_test.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
federation
import
(
"testing"
"github.com/pborman/uuid"
"k8s.io/kubernetes/test/integration/federation/framework"
)
// TestFederationCRUD validates create/read/update/delete operations for federated resource types.
func
TestFederationCRUD
(
t
*
testing
.
T
)
{
fedFixture
:=
framework
.
FederationFixture
{
DesiredClusterCount
:
2
}
fedFixture
.
SetUp
(
t
)
defer
fedFixture
.
TearDown
(
t
)
controllerFixtures
:=
[]
framework
.
ControllerFixture
{
&
framework
.
SecretFixture
{},
}
for
_
,
fixture
:=
range
controllerFixtures
{
t
.
Run
(
fixture
.
Kind
(),
func
(
t
*
testing
.
T
)
{
framework
.
SetUpControllerFixture
(
t
,
fedFixture
.
APIFixture
,
fixture
)
defer
fixture
.
TearDown
(
t
)
adapter
:=
fixture
.
Adapter
()
crudtester
:=
framework
.
NewFederatedTypeCRUDTester
(
t
,
adapter
,
fedFixture
.
ClusterClients
)
obj
:=
adapter
.
NewTestObject
(
uuid
.
New
())
crudtester
.
CheckLifecycle
(
obj
)
})
}
// Validate deletion handling where orphanDependents is true or nil for a single resource type since the
// underlying logic is common across all types.
orphanedDependents
:=
true
testCases
:=
map
[
string
]
*
bool
{
"Resources should not be deleted from underlying clusters when OrphanDependents is true"
:
&
orphanedDependents
,
"Resources should not be deleted from underlying clusters when OrphanDependents is nil"
:
nil
,
}
for
testName
,
orphanDependents
:=
range
testCases
{
t
.
Run
(
testName
,
func
(
t
*
testing
.
T
)
{
fixture
:=
&
framework
.
SecretFixture
{}
framework
.
SetUpControllerFixture
(
t
,
fedFixture
.
APIFixture
,
fixture
)
defer
fixture
.
TearDown
(
t
)
adapter
:=
fixture
.
Adapter
()
crudtester
:=
framework
.
NewFederatedTypeCRUDTester
(
t
,
adapter
,
fedFixture
.
ClusterClients
)
obj
:=
adapter
.
NewTestObject
(
uuid
.
New
())
updatedObj
:=
crudtester
.
CheckCreate
(
obj
)
crudtester
.
CheckDelete
(
updatedObj
,
orphanDependents
)
})
}
}
test/integration/federation/framework/BUILD
View file @
304030a6
...
...
@@ -11,15 +11,29 @@ go_library(
name = "go_default_library",
srcs = [
"api.go",
"controller.go",
"crudtester.go",
"federation.go",
"secret.go",
"util.go",
],
tags = ["automanaged"],
deps = [
"//federation/apis/federation/v1beta1:go_default_library",
"//federation/client/clientset_generated/federation_clientset:go_default_library",
"//federation/cmd/federation-apiserver/app:go_default_library",
"//federation/cmd/federation-apiserver/app/options:go_default_library",
"//federation/pkg/federation-controller/cluster:go_default_library",
"//federation/pkg/federation-controller/secret:go_default_library",
"//federation/pkg/typeadapters:go_default_library",
"//federation/pkg/typeadapters/crudtester:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/master:go_default_library",
"//test/integration/framework:go_default_library",
"//vendor:github.com/pborman/uuid",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/client-go/rest",
],
)
...
...
test/integration/federation/framework/api.go
View file @
304030a6
...
...
@@ -20,20 +20,18 @@ import (
"fmt"
"net/http"
"testing"
"time"
"github.com/pborman/uuid"
"k8s.io/apimachinery/pkg/util/wait"
restclient
"k8s.io/client-go/rest"
federationclientset
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
"k8s.io/kubernetes/federation/cmd/federation-apiserver/app"
"k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options"
"k8s.io/kubernetes/test/integration/framework"
)
const
(
apiNoun
=
"federation apiserver"
waitInterval
=
50
*
time
.
Millisecond
)
const
apiNoun
=
"federation apiserver"
func
getRunOptions
()
*
options
.
ServerRunOptions
{
r
:=
options
.
NewServerRunOptions
()
...
...
@@ -51,11 +49,11 @@ type FederationAPIFixture struct {
stopChan
chan
struct
{}
}
func
(
f
*
FederationAPIFixture
)
Set
u
p
(
t
*
testing
.
T
)
{
func
(
f
*
FederationAPIFixture
)
Set
U
p
(
t
*
testing
.
T
)
{
if
f
.
stopChan
!=
nil
{
t
.
Fatal
(
"Set
u
p() already called"
)
t
.
Fatal
(
"Set
U
p() already called"
)
}
defer
Tear
d
ownOnPanic
(
t
,
f
)
defer
Tear
D
ownOnPanic
(
t
,
f
)
f
.
stopChan
=
make
(
chan
struct
{})
...
...
@@ -74,15 +72,25 @@ func (f *FederationAPIFixture) Setup(t *testing.T) {
}
}
func
(
f
*
FederationAPIFixture
)
Tear
d
own
(
t
*
testing
.
T
)
{
func
(
f
*
FederationAPIFixture
)
Tear
D
own
(
t
*
testing
.
T
)
{
if
f
.
stopChan
!=
nil
{
close
(
f
.
stopChan
)
f
.
stopChan
=
nil
}
}
func
(
f
*
FederationAPIFixture
)
NewConfig
()
*
restclient
.
Config
{
return
&
restclient
.
Config
{
Host
:
f
.
Host
}
}
func
(
f
*
FederationAPIFixture
)
NewClient
(
userAgent
string
)
federationclientset
.
Interface
{
config
:=
f
.
NewConfig
()
restclient
.
AddUserAgent
(
config
,
userAgent
)
return
federationclientset
.
NewForConfigOrDie
(
config
)
}
func
startServer
(
t
*
testing
.
T
,
runOptions
*
options
.
ServerRunOptions
,
stopChan
<-
chan
struct
{})
error
{
err
:=
wait
.
PollImmediate
(
w
aitInterval
,
wait
.
ForeverTestTimeout
,
func
()
(
bool
,
error
)
{
err
:=
wait
.
PollImmediate
(
DefaultW
aitInterval
,
wait
.
ForeverTestTimeout
,
func
()
(
bool
,
error
)
{
port
,
err
:=
framework
.
FindFreeLocalPort
()
if
err
!=
nil
{
t
.
Logf
(
"Error allocating an ephemeral port: %v"
,
err
)
...
...
@@ -105,7 +113,7 @@ func startServer(t *testing.T, runOptions *options.ServerRunOptions, stopChan <-
}
func
waitForServer
(
t
*
testing
.
T
,
host
string
)
error
{
err
:=
wait
.
PollImmediate
(
w
aitInterval
,
wait
.
ForeverTestTimeout
,
func
()
(
bool
,
error
)
{
err
:=
wait
.
PollImmediate
(
DefaultW
aitInterval
,
wait
.
ForeverTestTimeout
,
func
()
(
bool
,
error
)
{
_
,
err
:=
http
.
Get
(
host
)
if
err
!=
nil
{
t
.
Logf
(
"Error when trying to contact the API: %v"
,
err
)
...
...
test/integration/federation/framework/controller.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
framework
import
(
"fmt"
"testing"
restclient
"k8s.io/client-go/rest"
federationclientset
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
"k8s.io/kubernetes/federation/pkg/typeadapters"
)
// ControllerFixture defines operations for managing a federation
// controller. Tests written to this interface can then target any
// controller for which an implementation of this interface exists.
type
ControllerFixture
interface
{
TestFixture
SetUp
(
t
*
testing
.
T
,
testClient
federationclientset
.
Interface
,
config
*
restclient
.
Config
)
Kind
()
string
Adapter
()
typeadapters
.
FederatedTypeAdapter
}
// SetUpControllerFixture configures the given resource fixture to target the provided api fixture
func
SetUpControllerFixture
(
t
*
testing
.
T
,
apiFixture
*
FederationAPIFixture
,
controllerFixture
ControllerFixture
)
{
client
:=
apiFixture
.
NewClient
(
fmt
.
Sprintf
(
"test-%s"
,
controllerFixture
.
Kind
()))
config
:=
apiFixture
.
NewConfig
()
controllerFixture
.
SetUp
(
t
,
client
,
config
)
}
test/integration/federation/framework/crudtester.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
framework
import
(
"testing"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/federation/pkg/typeadapters"
"k8s.io/kubernetes/federation/pkg/typeadapters/crudtester"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)
type
IntegrationLogger
struct
{
t
*
testing
.
T
}
func
(
l
*
IntegrationLogger
)
Logf
(
format
string
,
args
...
interface
{})
{
l
.
t
.
Logf
(
format
,
args
...
)
}
func
(
l
*
IntegrationLogger
)
Fatalf
(
format
string
,
args
...
interface
{})
{
l
.
t
.
Fatalf
(
format
,
args
...
)
}
func
(
l
*
IntegrationLogger
)
Fatal
(
msg
string
)
{
l
.
t
.
Fatal
(
msg
)
}
func
NewFederatedTypeCRUDTester
(
t
*
testing
.
T
,
adapter
typeadapters
.
FederatedTypeAdapter
,
clusterClients
[]
clientset
.
Interface
)
*
crudtester
.
FederatedTypeCRUDTester
{
logger
:=
&
IntegrationLogger
{
t
}
return
crudtester
.
NewFederatedTypeCRUDTester
(
logger
,
adapter
,
clusterClients
,
DefaultWaitInterval
,
wait
.
ForeverTestTimeout
)
}
test/integration/federation/framework/federation.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
framework
import
(
"fmt"
"net/http/httptest"
"testing"
"time"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
federationapi
"k8s.io/kubernetes/federation/apis/federation/v1beta1"
clustercontroller
"k8s.io/kubernetes/federation/pkg/federation-controller/cluster"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
"k8s.io/kubernetes/pkg/master"
"k8s.io/kubernetes/test/integration/framework"
)
type
MemberCluster
struct
{
Server
*
httptest
.
Server
Config
*
master
.
Config
Client
clientset
.
Interface
Host
string
}
// FederationFixture manages a federation api server and a set of member clusters
type
FederationFixture
struct
{
APIFixture
*
FederationAPIFixture
DesiredClusterCount
int
Clusters
[]
*
MemberCluster
ClusterClients
[]
clientset
.
Interface
ClusterController
*
clustercontroller
.
ClusterController
stopChan
chan
struct
{}
}
func
(
f
*
FederationFixture
)
SetUp
(
t
*
testing
.
T
)
{
if
f
.
APIFixture
!=
nil
{
t
.
Fatal
(
"Fixture already started"
)
}
if
f
.
DesiredClusterCount
<
1
{
f
.
DesiredClusterCount
=
1
}
defer
TearDownOnPanic
(
t
,
f
)
t
.
Logf
(
"Starting a federation of %d clusters"
,
f
.
DesiredClusterCount
)
f
.
APIFixture
=
&
FederationAPIFixture
{}
f
.
APIFixture
.
SetUp
(
t
)
f
.
stopChan
=
make
(
chan
struct
{})
monitorPeriod
:=
1
*
time
.
Second
clustercontroller
.
StartClusterController
(
f
.
APIFixture
.
NewConfig
(),
f
.
stopChan
,
monitorPeriod
)
f
.
startClusters
()
}
func
(
f
*
FederationFixture
)
startClusters
()
{
fedClient
:=
f
.
APIFixture
.
NewClient
(
"federation-fixture"
)
for
i
:=
0
;
i
<
f
.
DesiredClusterCount
;
i
++
{
config
:=
framework
.
NewMasterConfig
()
_
,
server
:=
framework
.
RunAMaster
(
config
)
host
:=
config
.
GenericConfig
.
LoopbackClientConfig
.
Host
// Use fmt to ensure the output will be visible when run with go test -v
fmt
.
Printf
(
"Federated cluster %d serving on %s"
,
i
,
host
)
clusterClient
:=
clientset
.
NewForConfigOrDie
(
config
.
GenericConfig
.
LoopbackClientConfig
)
f
.
Clusters
=
append
(
f
.
Clusters
,
&
MemberCluster
{
Server
:
server
,
Config
:
config
,
Client
:
clusterClient
,
Host
:
host
,
})
f
.
ClusterClients
=
append
(
f
.
ClusterClients
,
clusterClient
)
cluster
:=
&
federationapi
.
Cluster
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"cluster-%d"
,
i
),
},
Spec
:
federationapi
.
ClusterSpec
{
ServerAddressByClientCIDRs
:
[]
federationapi
.
ServerAddressByClientCIDR
{
{
ClientCIDR
:
"0.0.0.0/0"
,
ServerAddress
:
host
,
},
},
// Use insecure access
SecretRef
:
nil
,
},
}
fedClient
.
FederationV1beta1
()
.
Clusters
()
.
Create
(
cluster
)
}
}
func
(
f
*
FederationFixture
)
TearDown
(
t
*
testing
.
T
)
{
if
f
.
stopChan
!=
nil
{
close
(
f
.
stopChan
)
f
.
stopChan
=
nil
}
for
_
,
cluster
:=
range
f
.
Clusters
{
cluster
.
Server
.
Close
()
}
f
.
Clusters
=
nil
if
f
.
APIFixture
!=
nil
{
f
.
APIFixture
.
TearDown
(
t
)
f
.
APIFixture
=
nil
}
}
test/integration/federation/framework/secret.go
0 → 100644
View file @
304030a6
/*
Copyright 2017 The Kubernetes 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
framework
import
(
"testing"
restclient
"k8s.io/client-go/rest"
federationclientset
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
secretcontroller
"k8s.io/kubernetes/federation/pkg/federation-controller/secret"
"k8s.io/kubernetes/federation/pkg/typeadapters"
)
type
SecretFixture
struct
{
adapter
*
typeadapters
.
SecretAdapter
stopChan
chan
struct
{}
}
func
(
f
*
SecretFixture
)
SetUp
(
t
*
testing
.
T
,
client
federationclientset
.
Interface
,
config
*
restclient
.
Config
)
{
f
.
adapter
=
typeadapters
.
NewSecretAdapter
(
client
)
f
.
stopChan
=
make
(
chan
struct
{})
secretcontroller
.
StartSecretController
(
config
,
f
.
stopChan
,
true
)
}
func
(
f
*
SecretFixture
)
TearDown
(
t
*
testing
.
T
)
{
close
(
f
.
stopChan
)
}
func
(
f
*
SecretFixture
)
Kind
()
string
{
adapter
:=
&
typeadapters
.
SecretAdapter
{}
return
adapter
.
Kind
()
}
func
(
f
*
SecretFixture
)
Adapter
()
typeadapters
.
FederatedTypeAdapter
{
return
f
.
adapter
}
test/integration/federation/framework/util.go
View file @
304030a6
...
...
@@ -18,18 +18,23 @@ package framework
import
(
"testing"
"time"
)
// Setup is likely to be fixture-specific, but Teardown needs to be
// consistent to enable TeardownOnPanic.
const
(
DefaultWaitInterval
=
50
*
time
.
Millisecond
)
// SetUp is likely to be fixture-specific, but TearDown needs to be
// consistent to enable TearDownOnPanic.
type
TestFixture
interface
{
Tear
d
own
(
t
*
testing
.
T
)
Tear
D
own
(
t
*
testing
.
T
)
}
// Tear
d
ownOnPanic can be used to ensure cleanup on setup failure.
func
Tear
d
ownOnPanic
(
t
*
testing
.
T
,
f
TestFixture
)
{
// Tear
D
ownOnPanic can be used to ensure cleanup on setup failure.
func
Tear
D
ownOnPanic
(
t
*
testing
.
T
,
f
TestFixture
)
{
if
r
:=
recover
();
r
!=
nil
{
f
.
Tear
d
own
(
t
)
f
.
Tear
D
own
(
t
)
panic
(
r
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment