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
a291846c
Commit
a291846c
authored
Aug 28, 2016
by
Daniel Smith
Committed by
GitHub
Aug 28, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Remove deprecated Namespace admission plug-ins"
parent
72fbb519
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
501 additions
and
2 deletions
+501
-2
config-default.sh
cluster/centos/config-default.sh
+1
-1
apiserver.sh
cluster/centos/master/scripts/apiserver.sh
+1
-1
plugins.go
cmd/kube-apiserver/app/plugins.go
+2
-0
admission.go
plugin/pkg/admission/namespace/autoprovision/admission.go
+100
-0
admission_test.go
...n/pkg/admission/namespace/autoprovision/admission_test.go
+172
-0
admission.go
plugin/pkg/admission/namespace/exists/admission.go
+107
-0
admission_test.go
plugin/pkg/admission/namespace/exists/admission_test.go
+118
-0
No files found.
cluster/centos/config-default.sh
View file @
a291846c
...
@@ -42,7 +42,7 @@ export FLANNEL_NET=${FLANNEL_NET:-"172.16.0.0/16"}
...
@@ -42,7 +42,7 @@ export FLANNEL_NET=${FLANNEL_NET:-"172.16.0.0/16"}
# Admission Controllers to invoke prior to persisting objects in cluster
# Admission Controllers to invoke prior to persisting objects in cluster
# If we included ResourceQuota, we should keep it at the end of the list to prevent incremeting quota usage prematurely.
# If we included ResourceQuota, we should keep it at the end of the list to prevent incremeting quota usage prematurely.
export
ADMISSION_CONTROL
=
NamespaceLifecycle,LimitRanger,ServiceAccount,SecurityContextDeny,DefaultStorageClass,ResourceQuota
export
ADMISSION_CONTROL
=
NamespaceLifecycle,
NamespaceExists,
LimitRanger,ServiceAccount,SecurityContextDeny,DefaultStorageClass,ResourceQuota
# Extra options to set on the Docker command line.
# Extra options to set on the Docker command line.
# This is useful for setting --insecure-registry for local registries.
# This is useful for setting --insecure-registry for local registries.
...
...
cluster/centos/master/scripts/apiserver.sh
View file @
a291846c
...
@@ -54,7 +54,7 @@ KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}"
...
@@ -54,7 +54,7 @@ KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=${SERVICE_CLUSTER_IP_RANGE}"
# --admission-control="AlwaysAdmit": Ordered list of plug-ins
# --admission-control="AlwaysAdmit": Ordered list of plug-ins
# to do admission control of resources into cluster.
# to do admission control of resources into cluster.
# Comma-delimited list of:
# Comma-delimited list of:
# LimitRanger, AlwaysDeny, SecurityContextDeny,
# LimitRanger, AlwaysDeny, SecurityContextDeny,
NamespaceExists,
# NamespaceLifecycle, NamespaceAutoProvision,
# NamespaceLifecycle, NamespaceAutoProvision,
# AlwaysAdmit, ServiceAccount, ResourceQuota, DefaultStorageClass
# AlwaysAdmit, ServiceAccount, ResourceQuota, DefaultStorageClass
KUBE_ADMISSION_CONTROL="--admission-control=
${
ADMISSION_CONTROL
}
"
KUBE_ADMISSION_CONTROL="--admission-control=
${
ADMISSION_CONTROL
}
"
...
...
cmd/kube-apiserver/app/plugins.go
View file @
a291846c
...
@@ -32,6 +32,8 @@ import (
...
@@ -32,6 +32,8 @@ import (
_
"k8s.io/kubernetes/plugin/pkg/admission/imagepolicy"
_
"k8s.io/kubernetes/plugin/pkg/admission/imagepolicy"
_
"k8s.io/kubernetes/plugin/pkg/admission/initialresources"
_
"k8s.io/kubernetes/plugin/pkg/admission/initialresources"
_
"k8s.io/kubernetes/plugin/pkg/admission/limitranger"
_
"k8s.io/kubernetes/plugin/pkg/admission/limitranger"
_
"k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision"
_
"k8s.io/kubernetes/plugin/pkg/admission/namespace/exists"
_
"k8s.io/kubernetes/plugin/pkg/admission/namespace/lifecycle"
_
"k8s.io/kubernetes/plugin/pkg/admission/namespace/lifecycle"
_
"k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label"
_
"k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label"
_
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota"
_
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota"
...
...
plugin/pkg/admission/namespace/autoprovision/admission.go
0 → 100644
View file @
a291846c
/*
Copyright 2014 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
autoprovision
import
(
"io"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"fmt"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/controller/framework/informers"
)
func
init
()
{
admission
.
RegisterPlugin
(
"NamespaceAutoProvision"
,
func
(
client
clientset
.
Interface
,
config
io
.
Reader
)
(
admission
.
Interface
,
error
)
{
return
NewProvision
(
client
),
nil
})
}
// provision is an implementation of admission.Interface.
// It looks at all incoming requests in a namespace context, and if the namespace does not exist, it creates one.
// It is useful in deployments that do not want to restrict creation of a namespace prior to its usage.
type
provision
struct
{
*
admission
.
Handler
client
clientset
.
Interface
namespaceInformer
framework
.
SharedIndexInformer
}
var
_
=
admission
.
WantsInformerFactory
(
&
provision
{})
func
(
p
*
provision
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// its a namespaced resource.
if
len
(
a
.
GetNamespace
())
==
0
||
a
.
GetKind
()
.
GroupKind
()
==
api
.
Kind
(
"Namespace"
)
{
return
nil
}
// we need to wait for our caches to warm
if
!
p
.
WaitForReady
()
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"not yet ready to handle request"
))
}
namespace
:=
&
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
a
.
GetNamespace
(),
Namespace
:
""
,
},
Status
:
api
.
NamespaceStatus
{},
}
_
,
exists
,
err
:=
p
.
namespaceInformer
.
GetStore
()
.
Get
(
namespace
)
if
err
!=
nil
{
return
admission
.
NewForbidden
(
a
,
err
)
}
if
exists
{
return
nil
}
_
,
err
=
p
.
client
.
Core
()
.
Namespaces
()
.
Create
(
namespace
)
if
err
!=
nil
&&
!
errors
.
IsAlreadyExists
(
err
)
{
return
admission
.
NewForbidden
(
a
,
err
)
}
return
nil
}
// NewProvision creates a new namespace provision admission control handler
func
NewProvision
(
c
clientset
.
Interface
)
admission
.
Interface
{
return
&
provision
{
Handler
:
admission
.
NewHandler
(
admission
.
Create
),
client
:
c
,
}
}
func
(
p
*
provision
)
SetInformerFactory
(
f
informers
.
SharedInformerFactory
)
{
p
.
namespaceInformer
=
f
.
Namespaces
()
.
Informer
()
p
.
SetReadyFunc
(
p
.
namespaceInformer
.
HasSynced
)
}
func
(
p
*
provision
)
Validate
()
error
{
if
p
.
namespaceInformer
==
nil
{
return
fmt
.
Errorf
(
"missing namespaceInformer"
)
}
return
nil
}
plugin/pkg/admission/namespace/autoprovision/admission_test.go
0 → 100644
View file @
a291846c
/*
Copyright 2014 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
autoprovision
import
(
"fmt"
"testing"
"time"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/controller/framework/informers"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/wait"
)
// newHandlerForTest returns the admission controller configured for testing.
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
admission
.
Interface
,
informers
.
SharedInformerFactory
,
error
)
{
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
handler
:=
NewProvision
(
c
)
plugins
:=
[]
admission
.
Interface
{
handler
}
pluginInitializer
:=
admission
.
NewPluginInitializer
(
f
)
pluginInitializer
.
Initialize
(
plugins
)
err
:=
admission
.
Validate
(
plugins
)
return
handler
,
f
,
err
}
// newMockClientForTest creates a mock client that returns a client configured for the specified list of namespaces.
func
newMockClientForTest
(
namespaces
[]
string
)
*
fake
.
Clientset
{
mockClient
:=
&
fake
.
Clientset
{}
mockClient
.
AddReactor
(
"list"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
namespaceList
:=
&
api
.
NamespaceList
{
ListMeta
:
unversioned
.
ListMeta
{
ResourceVersion
:
fmt
.
Sprintf
(
"%d"
,
len
(
namespaces
)),
},
}
for
i
,
ns
:=
range
namespaces
{
namespaceList
.
Items
=
append
(
namespaceList
.
Items
,
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
ns
,
ResourceVersion
:
fmt
.
Sprintf
(
"%d"
,
i
),
},
})
}
return
true
,
namespaceList
,
nil
})
return
mockClient
}
// newPod returns a new pod for the specified namespace
func
newPod
(
namespace
string
)
api
.
Pod
{
return
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
Spec
:
api
.
PodSpec
{
Volumes
:
[]
api
.
Volume
{{
Name
:
"vol"
}},
Containers
:
[]
api
.
Container
{{
Name
:
"ctr"
,
Image
:
"image"
}},
},
}
}
// hasCreateNamespaceAction returns true if it has the create namespace action
func
hasCreateNamespaceAction
(
mockClient
*
fake
.
Clientset
)
bool
{
for
_
,
action
:=
range
mockClient
.
Actions
()
{
if
action
.
GetVerb
()
==
"create"
&&
action
.
GetResource
()
.
Resource
==
"namespaces"
{
return
true
}
}
return
false
}
// TestAdmission verifies a namespace is created on create requests for namespace managed resources
func
TestAdmission
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
pod
:=
newPod
(
namespace
)
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error returned from admission handler"
)
}
if
!
hasCreateNamespaceAction
(
mockClient
)
{
t
.
Errorf
(
"expected create namespace action"
)
}
}
// TestAdmissionNamespaceExists verifies that no client call is made when a namespace already exists
func
TestAdmissionNamespaceExists
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{
namespace
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
pod
:=
newPod
(
namespace
)
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error returned from admission handler"
)
}
if
hasCreateNamespaceAction
(
mockClient
)
{
t
.
Errorf
(
"unexpected create namespace action"
)
}
}
// TestIgnoreAdmission validates that a request is ignored if its not a create
func
TestIgnoreAdmission
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
chainHandler
:=
admission
.
NewChainHandler
(
handler
)
pod
:=
newPod
(
namespace
)
err
=
chainHandler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Update
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error returned from admission handler"
)
}
if
hasCreateNamespaceAction
(
mockClient
)
{
t
.
Errorf
(
"unexpected create namespace action"
)
}
}
func
TestAdmissionWithLatentCache
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{})
mockClient
.
AddReactor
(
"create"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
return
true
,
nil
,
errors
.
NewAlreadyExists
(
api
.
Resource
(
"namespaces"
),
namespace
)
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
pod
:=
newPod
(
namespace
)
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error returned from admission handler"
)
}
if
!
hasCreateNamespaceAction
(
mockClient
)
{
t
.
Errorf
(
"expected create namespace action"
)
}
}
plugin/pkg/admission/namespace/exists/admission.go
0 → 100644
View file @
a291846c
/*
Copyright 2014 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
exists
import
(
"io"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"fmt"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/controller/framework/informers"
)
func
init
()
{
admission
.
RegisterPlugin
(
"NamespaceExists"
,
func
(
client
clientset
.
Interface
,
config
io
.
Reader
)
(
admission
.
Interface
,
error
)
{
return
NewExists
(
client
),
nil
})
}
// exists is an implementation of admission.Interface.
// It rejects all incoming requests in a namespace context if the namespace does not exist.
// It is useful in deployments that want to enforce pre-declaration of a Namespace resource.
type
exists
struct
{
*
admission
.
Handler
client
clientset
.
Interface
namespaceInformer
framework
.
SharedIndexInformer
}
var
_
=
admission
.
WantsInformerFactory
(
&
exists
{})
func
(
e
*
exists
)
Admit
(
a
admission
.
Attributes
)
(
err
error
)
{
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// its a namespaced resource.
if
len
(
a
.
GetNamespace
())
==
0
||
a
.
GetKind
()
.
GroupKind
()
==
api
.
Kind
(
"Namespace"
)
{
return
nil
}
// we need to wait for our caches to warm
if
!
e
.
WaitForReady
()
{
return
admission
.
NewForbidden
(
a
,
fmt
.
Errorf
(
"not yet ready to handle request"
))
}
namespace
:=
&
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
a
.
GetNamespace
(),
Namespace
:
""
,
},
Status
:
api
.
NamespaceStatus
{},
}
_
,
exists
,
err
:=
e
.
namespaceInformer
.
GetStore
()
.
Get
(
namespace
)
if
err
!=
nil
{
return
errors
.
NewInternalError
(
err
)
}
if
exists
{
return
nil
}
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
_
,
err
=
e
.
client
.
Core
()
.
Namespaces
()
.
Get
(
a
.
GetNamespace
())
if
err
!=
nil
{
if
errors
.
IsNotFound
(
err
)
{
return
err
}
return
errors
.
NewInternalError
(
err
)
}
return
nil
}
// NewExists creates a new namespace exists admission control handler
func
NewExists
(
c
clientset
.
Interface
)
admission
.
Interface
{
return
&
exists
{
client
:
c
,
Handler
:
admission
.
NewHandler
(
admission
.
Create
,
admission
.
Update
,
admission
.
Delete
),
}
}
func
(
e
*
exists
)
SetInformerFactory
(
f
informers
.
SharedInformerFactory
)
{
e
.
namespaceInformer
=
f
.
Namespaces
()
.
Informer
()
e
.
SetReadyFunc
(
e
.
namespaceInformer
.
HasSynced
)
}
func
(
e
*
exists
)
Validate
()
error
{
if
e
.
namespaceInformer
==
nil
{
return
fmt
.
Errorf
(
"missing namespaceInformer"
)
}
return
nil
}
plugin/pkg/admission/namespace/exists/admission_test.go
0 → 100644
View file @
a291846c
/*
Copyright 2014 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
exists
import
(
"fmt"
"testing"
"time"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
clientset
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/controller/framework/informers"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/wait"
)
// newHandlerForTest returns the admission controller configured for testing.
func
newHandlerForTest
(
c
clientset
.
Interface
)
(
admission
.
Interface
,
informers
.
SharedInformerFactory
,
error
)
{
f
:=
informers
.
NewSharedInformerFactory
(
c
,
5
*
time
.
Minute
)
handler
:=
NewExists
(
c
)
plugins
:=
[]
admission
.
Interface
{
handler
}
pluginInitializer
:=
admission
.
NewPluginInitializer
(
f
)
pluginInitializer
.
Initialize
(
plugins
)
err
:=
admission
.
Validate
(
plugins
)
return
handler
,
f
,
err
}
// newMockClientForTest creates a mock client that returns a client configured for the specified list of namespaces.
func
newMockClientForTest
(
namespaces
[]
string
)
*
fake
.
Clientset
{
mockClient
:=
&
fake
.
Clientset
{}
mockClient
.
AddReactor
(
"list"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
namespaceList
:=
&
api
.
NamespaceList
{
ListMeta
:
unversioned
.
ListMeta
{
ResourceVersion
:
fmt
.
Sprintf
(
"%d"
,
len
(
namespaces
)),
},
}
for
i
,
ns
:=
range
namespaces
{
namespaceList
.
Items
=
append
(
namespaceList
.
Items
,
api
.
Namespace
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
ns
,
ResourceVersion
:
fmt
.
Sprintf
(
"%d"
,
i
),
},
})
}
return
true
,
namespaceList
,
nil
})
return
mockClient
}
// newPod returns a new pod for the specified namespace
func
newPod
(
namespace
string
)
api
.
Pod
{
return
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"123"
,
Namespace
:
namespace
},
Spec
:
api
.
PodSpec
{
Volumes
:
[]
api
.
Volume
{{
Name
:
"vol"
}},
Containers
:
[]
api
.
Container
{{
Name
:
"ctr"
,
Image
:
"image"
}},
},
}
}
// TestAdmissionNamespaceExists verifies pod is admitted only if namespace exists.
func
TestAdmissionNamespaceExists
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{
namespace
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
pod
:=
newPod
(
namespace
)
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error returned from admission handler"
)
}
}
// TestAdmissionNamespaceDoesNotExist verifies pod is not admitted if namespace does not exist.
func
TestAdmissionNamespaceDoesNotExist
(
t
*
testing
.
T
)
{
namespace
:=
"test"
mockClient
:=
newMockClientForTest
([]
string
{})
mockClient
.
AddReactor
(
"get"
,
"namespaces"
,
func
(
action
core
.
Action
)
(
bool
,
runtime
.
Object
,
error
)
{
return
true
,
nil
,
fmt
.
Errorf
(
"nope, out of luck"
)
})
handler
,
informerFactory
,
err
:=
newHandlerForTest
(
mockClient
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error initializing handler: %v"
,
err
)
}
informerFactory
.
Start
(
wait
.
NeverStop
)
pod
:=
newPod
(
namespace
)
err
=
handler
.
Admit
(
admission
.
NewAttributesRecord
(
&
pod
,
nil
,
api
.
Kind
(
"Pod"
)
.
WithVersion
(
"version"
),
pod
.
Namespace
,
pod
.
Name
,
api
.
Resource
(
"pods"
)
.
WithVersion
(
"version"
),
""
,
admission
.
Create
,
nil
))
if
err
==
nil
{
actions
:=
""
for
_
,
action
:=
range
mockClient
.
Actions
()
{
actions
=
actions
+
action
.
GetVerb
()
+
":"
+
action
.
GetResource
()
.
Resource
+
":"
+
action
.
GetSubresource
()
+
", "
}
t
.
Errorf
(
"expected error returned from admission handler: %v"
,
actions
)
}
}
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