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
0348a674
Commit
0348a674
authored
Nov 12, 2014
by
Daniel Smith
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2195 from smarterclayton/prepare_pod_template_v1beta3
Allow an internal pod template reference or object
parents
ab3bf094
8a590004
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
637 additions
and
305 deletions
+637
-305
pod-list.json
api/examples/pod-list.json
+2
-2
integration.go
cmd/integration/integration.go
+5
-6
examples_test.go
examples/examples_test.go
+11
-2
pod-with-http-healthcheck.yaml
examples/walkthrough/pod-with-http-healthcheck.yaml
+1
-0
replication-controller.yaml
examples/walkthrough/replication-controller.yaml
+1
-1
conversion.go
pkg/api/conversion.go
+29
-0
validation.go
pkg/api/errors/validation.go
+1
-1
latest_test.go
pkg/api/latest/latest_test.go
+19
-0
serialization_test.go
pkg/api/serialization_test.go
+25
-5
types.go
pkg/api/types.go
+69
-23
conversion.go
pkg/api/v1beta1/conversion.go
+74
-6
types.go
pkg/api/v1beta1/types.go
+2
-0
conversion.go
pkg/api/v1beta2/conversion.go
+74
-6
types.go
pkg/api/v1beta2/types.go
+2
-0
validation.go
pkg/api/validation/validation.go
+45
-15
validation_test.go
pkg/api/validation/validation_test.go
+44
-45
client_test.go
pkg/client/client_test.go
+10
-6
conditions.go
pkg/client/conditions.go
+2
-2
replication_controller.go
pkg/controller/replication_controller.go
+24
-17
replication_controller_test.go
pkg/controller/replication_controller_test.go
+58
-51
meta.go
pkg/conversion/meta.go
+1
-1
scheme.go
pkg/conversion/scheme.go
+1
-1
kubecfg.go
pkg/kubecfg/kubecfg.go
+19
-20
kubecfg_test.go
pkg/kubecfg/kubecfg_test.go
+15
-17
parse_test.go
pkg/kubecfg/parse_test.go
+8
-11
resource_printer.go
pkg/kubecfg/resource_printer.go
+10
-2
describe.go
pkg/kubectl/describe.go
+13
-7
kubectl.go
pkg/kubectl/kubectl.go
+2
-2
resource_printer.go
pkg/kubectl/resource_printer.go
+9
-3
rest.go
pkg/registry/controller/rest.go
+11
-13
rest_test.go
pkg/registry/controller/rest_test.go
+48
-38
etcd_test.go
pkg/registry/etcd/etcd_test.go
+2
-2
No files found.
api/examples/pod-list.json
View file @
0348a674
...
...
@@ -6,7 +6,7 @@
"id"
:
"my-pod-1"
,
"labels"
:
{
"name"
:
"testRun"
,
"replication
C
ontroller"
:
"testRun"
"replication
c
ontroller"
:
"testRun"
},
"desiredState"
:
{
"manifest"
:
{
...
...
@@ -30,7 +30,7 @@
"id"
:
"my-pod-2"
,
"labels"
:
{
"name"
:
"testRun"
,
"replication
C
ontroller"
:
"testRun"
"replication
c
ontroller"
:
"testRun"
},
"desiredState"
:
{
"manifest"
:
{
...
...
cmd/integration/integration.go
View file @
0348a674
...
...
@@ -19,7 +19,6 @@ limitations under the License.
package
main
import
(
"encoding/json"
"io/ioutil"
"net"
"net/http"
...
...
@@ -237,24 +236,24 @@ func runReplicationControllerTest(c *client.Client) {
if
err
!=
nil
{
glog
.
Fatalf
(
"Unexpected error: %#v"
,
err
)
}
var
controller
Request
api
.
ReplicationController
if
err
:=
json
.
Unmarshal
(
data
,
&
controllerRequest
);
err
!=
nil
{
var
controller
api
.
ReplicationController
if
err
:=
api
.
Scheme
.
DecodeInto
(
data
,
&
controller
);
err
!=
nil
{
glog
.
Fatalf
(
"Unexpected error: %#v"
,
err
)
}
glog
.
Infof
(
"Creating replication controllers"
)
if
_
,
err
:=
c
.
ReplicationControllers
(
api
.
NamespaceDefault
)
.
Create
(
&
controller
Request
);
err
!=
nil
{
if
_
,
err
:=
c
.
ReplicationControllers
(
api
.
NamespaceDefault
)
.
Create
(
&
controller
);
err
!=
nil
{
glog
.
Fatalf
(
"Unexpected error: %#v"
,
err
)
}
glog
.
Infof
(
"Done creating replication controllers"
)
// Give the controllers some time to actually create the pods
if
err
:=
wait
.
Poll
(
time
.
Second
,
time
.
Second
*
30
,
c
.
ControllerHasDesiredReplicas
(
controller
Request
));
err
!=
nil
{
if
err
:=
wait
.
Poll
(
time
.
Second
,
time
.
Second
*
30
,
c
.
ControllerHasDesiredReplicas
(
controller
));
err
!=
nil
{
glog
.
Fatalf
(
"FAILED: pods never created %v"
,
err
)
}
// wait for minions to indicate they have info about the desired pods
pods
,
err
:=
c
.
Pods
(
api
.
NamespaceDefault
)
.
List
(
labels
.
Set
(
controller
Request
.
DesiredState
.
Replica
Selector
)
.
AsSelector
())
pods
,
err
:=
c
.
Pods
(
api
.
NamespaceDefault
)
.
List
(
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
())
if
err
!=
nil
{
glog
.
Fatalf
(
"FAILED: unable to get pods to list: %v"
,
err
)
}
...
...
examples/examples_test.go
View file @
0348a674
...
...
@@ -36,12 +36,18 @@ func validateObject(obj runtime.Object) (errors []error) {
ctx
:=
api
.
NewDefaultContext
()
switch
t
:=
obj
.
(
type
)
{
case
*
api
.
ReplicationController
:
errors
=
validation
.
ValidateManifest
(
&
t
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
)
if
t
.
Namespace
==
""
{
t
.
Namespace
=
api
.
NamespaceDefault
}
errors
=
validation
.
ValidateReplicationController
(
t
)
case
*
api
.
ReplicationControllerList
:
for
i
:=
range
t
.
Items
{
errors
=
append
(
errors
,
validateObject
(
&
t
.
Items
[
i
])
...
)
}
case
*
api
.
Service
:
if
t
.
Namespace
==
""
{
t
.
Namespace
=
api
.
NamespaceDefault
}
api
.
ValidNamespace
(
ctx
,
&
t
.
ObjectMeta
)
errors
=
validation
.
ValidateService
(
t
,
registrytest
.
NewServiceRegistry
(),
api
.
NewDefaultContext
())
case
*
api
.
ServiceList
:
...
...
@@ -49,8 +55,11 @@ func validateObject(obj runtime.Object) (errors []error) {
errors
=
append
(
errors
,
validateObject
(
&
t
.
Items
[
i
])
...
)
}
case
*
api
.
Pod
:
if
t
.
Namespace
==
""
{
t
.
Namespace
=
api
.
NamespaceDefault
}
api
.
ValidNamespace
(
ctx
,
&
t
.
ObjectMeta
)
errors
=
validation
.
Validate
Manifest
(
&
t
.
DesiredState
.
Manifes
t
)
errors
=
validation
.
Validate
Pod
(
t
)
case
*
api
.
PodList
:
for
i
:=
range
t
.
Items
{
errors
=
append
(
errors
,
validateObject
(
&
t
.
Items
[
i
])
...
)
...
...
examples/walkthrough/pod-with-http-healthcheck.yaml
View file @
0348a674
kind
:
Pod
apiVersion
:
v1beta1
id
:
pod-with-healthcheck
desiredState
:
manifest
:
version
:
v1beta1
...
...
examples/walkthrough/replication-controller.yaml
View file @
0348a674
...
...
@@ -22,4 +22,4 @@ desiredState:
# Important: these labels need to match the selector above
# The api server enforces this constraint.
labels
:
-
name
:
nginx
name
:
nginx
pkg/api/conversion.go
View file @
0348a674
...
...
@@ -59,6 +59,8 @@ func init() {
}
return
nil
},
// ContainerManifestList
func
(
in
*
ContainerManifestList
,
out
*
BoundPods
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Items
,
&
out
.
Items
,
0
);
err
!=
nil
{
return
err
...
...
@@ -90,5 +92,32 @@ func init() {
out
.
CreationTimestamp
=
in
.
CreationTimestamp
return
nil
},
// Conversion between Manifest and PodSpec
func
(
in
*
PodSpec
,
out
*
ContainerManifest
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
out
.
Version
=
"v1beta2"
return
nil
},
func
(
in
*
ContainerManifest
,
out
*
PodSpec
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
)
}
pkg/api/errors/validation.go
View file @
0348a674
...
...
@@ -140,7 +140,7 @@ func (list ValidationErrorList) Prefix(prefix string) ValidationErrorList {
}
list
[
i
]
=
err
}
else
{
glog
.
Warningf
(
"
ValidationErrorList holds non-ValidationError: %T"
,
list
)
glog
.
Warningf
(
"
Programmer error: ValidationErrorList holds non-ValidationError: %#v"
,
list
[
i
]
)
}
}
return
list
...
...
pkg/api/latest/latest_test.go
View file @
0348a674
...
...
@@ -75,6 +75,23 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
statuses
:=
[]
internal
.
PodCondition
{
internal
.
PodPending
,
internal
.
PodRunning
,
internal
.
PodFailed
}
*
j
=
statuses
[
c
.
Rand
.
Intn
(
len
(
statuses
))]
},
func
(
j
*
internal
.
ReplicationControllerSpec
,
c
fuzz
.
Continue
)
{
// TemplateRef must be nil for round trip
c
.
Fuzz
(
&
j
.
Template
)
if
j
.
Template
==
nil
{
// TODO: v1beta1/2 can't round trip a nil template correctly, fix by having v1beta1/2
// conversion compare converted object to nil via DeepEqual
j
.
Template
=
&
internal
.
PodTemplateSpec
{}
}
j
.
Template
.
ObjectMeta
=
internal
.
ObjectMeta
{
Labels
:
j
.
Template
.
ObjectMeta
.
Labels
}
j
.
Template
.
Spec
.
NodeSelector
=
nil
c
.
Fuzz
(
&
j
.
Selector
)
j
.
Replicas
=
int
(
c
.
RandUint64
())
},
func
(
j
*
internal
.
ReplicationControllerStatus
,
c
fuzz
.
Continue
)
{
// only replicas round trips
j
.
Replicas
=
int
(
c
.
RandUint64
())
},
func
(
intstr
*
util
.
IntOrString
,
c
fuzz
.
Continue
)
{
// util.IntOrString will panic if its kind is set wrong.
if
c
.
RandBool
()
{
...
...
@@ -127,6 +144,7 @@ func TestInternalRoundTrip(t *testing.T) {
if
err
:=
internal
.
Scheme
.
Convert
(
obj
,
newer
);
err
!=
nil
{
t
.
Errorf
(
"unable to convert %#v to %#v: %v"
,
obj
,
newer
,
err
)
continue
}
actual
,
err
:=
internal
.
Scheme
.
New
(
""
,
k
)
...
...
@@ -137,6 +155,7 @@ func TestInternalRoundTrip(t *testing.T) {
if
err
:=
internal
.
Scheme
.
Convert
(
newer
,
actual
);
err
!=
nil
{
t
.
Errorf
(
"unable to convert %#v to %#v: %v"
,
newer
,
actual
,
err
)
continue
}
if
!
reflect
.
DeepEqual
(
obj
,
actual
)
{
...
...
pkg/api/serialization_test.go
View file @
0348a674
...
...
@@ -90,6 +90,23 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
statuses
:=
[]
api
.
PodCondition
{
api
.
PodPending
,
api
.
PodRunning
,
api
.
PodFailed
}
*
j
=
statuses
[
c
.
Rand
.
Intn
(
len
(
statuses
))]
},
func
(
j
*
api
.
ReplicationControllerSpec
,
c
fuzz
.
Continue
)
{
// TemplateRef must be nil for round trip
c
.
Fuzz
(
&
j
.
Template
)
if
j
.
Template
==
nil
{
// TODO: v1beta1/2 can't round trip a nil template correctly, fix by having v1beta1/2
// conversion compare converted object to nil via DeepEqual
j
.
Template
=
&
api
.
PodTemplateSpec
{}
}
j
.
Template
.
ObjectMeta
=
api
.
ObjectMeta
{
Labels
:
j
.
Template
.
ObjectMeta
.
Labels
}
j
.
Template
.
Spec
.
NodeSelector
=
nil
c
.
Fuzz
(
&
j
.
Selector
)
j
.
Replicas
=
int
(
c
.
RandUint64
())
},
func
(
j
*
api
.
ReplicationControllerStatus
,
c
fuzz
.
Continue
)
{
// only replicas round trips
j
.
Replicas
=
int
(
c
.
RandUint64
())
},
func
(
intstr
*
util
.
IntOrString
,
c
fuzz
.
Continue
)
{
// util.IntOrString will panic if its kind is set wrong.
if
c
.
RandBool
()
{
...
...
@@ -176,18 +193,21 @@ func TestSpecificKind(t *testing.T) {
api
.
Scheme
.
Log
(
nil
)
}
func
TestTypes
(
t
*
testing
.
T
)
{
var
nonRoundTrippableTypes
=
util
.
NewStringSet
(
"ContainerManifest"
)
func
TestRoundTripTypes
(
t
*
testing
.
T
)
{
for
kind
:=
range
api
.
Scheme
.
KnownTypes
(
""
)
{
if
nonRoundTrippableTypes
.
Has
(
kind
)
{
continue
}
// Try a few times, since runTest uses random values.
for
i
:=
0
;
i
<
*
fuzzIters
;
i
++
{
item
,
err
:=
api
.
Scheme
.
New
(
""
,
kind
)
if
err
!=
nil
{
t
.
Errorf
(
"Couldn't make a %v? %v"
,
kind
,
err
)
continue
t
.
Fatalf
(
"Couldn't make a %v? %v"
,
kind
,
err
)
}
if
_
,
err
:=
meta
.
Accessor
(
item
);
err
!=
nil
{
t
.
Logf
(
"%s is not a TypeMeta and cannot be round tripped: %v"
,
kind
,
err
)
continue
t
.
Fatalf
(
"%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v"
,
kind
,
err
)
}
runTest
(
t
,
v1beta1
.
Codec
,
item
)
runTest
(
t
,
v1beta2
.
Codec
,
item
)
...
...
pkg/api/types.go
View file @
0348a674
...
...
@@ -442,6 +442,15 @@ type PodList struct {
Items
[]
Pod
`json:"items" yaml:"items"`
}
// PodSpec is a description of a pod
type
PodSpec
struct
{
Volumes
[]
Volume
`json:"volumes" yaml:"volumes"`
Containers
[]
Container
`json:"containers" yaml:"containers"`
RestartPolicy
RestartPolicy
`json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
// NodeSelector is a selector which must be true for the pod to fit on a node
NodeSelector
map
[
string
]
string
`json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
}
// Pod is a collection of containers, used as either input (create, update) or as output (list, get).
type
Pod
struct
{
TypeMeta
`json:",inline" yaml:",inline"`
...
...
@@ -453,19 +462,59 @@ type Pod struct {
NodeSelector
map
[
string
]
string
`json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
}
// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get).
type
ReplicationControllerState
struct
{
Replicas
int
`json:"replicas" yaml:"replicas"`
ReplicaSelector
map
[
string
]
string
`json:"replicaSelector,omitempty" yaml:"replicaSelector,omitempty"`
PodTemplate
PodTemplate
`json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
// PodTemplateSpec describes the data a pod should have when created from a template
type
PodTemplateSpec
struct
{
// Metadata of the pods created from this template.
ObjectMeta
`json:"metadata,omitempty" yaml:"metadata,omitempty"`
// Spec defines the behavior of a pod.
Spec
PodSpec
`json:"spec,omitempty" yaml:"spec,omitempty"`
}
// ReplicationControllerList is a collection of replication controllers.
type
ReplicationControllerList
struct
{
// PodTemplate describes a template for creating copies of a predefined pod.
type
PodTemplate
struct
{
TypeMeta
`json:",inline" yaml:",inline"`
ObjectMeta
`json:"metadata,omitempty" yaml:"metadata,omitempty"`
// Spec defines the pods that will be created from this template
Spec
PodTemplateSpec
`json:"spec,omitempty" yaml:"spec,omitempty"`
}
// PodTemplateList is a list of PodTemplates.
type
PodTemplateList
struct
{
TypeMeta
`json:",inline" yaml:",inline"`
ListMeta
`json:"metadata,omitempty" yaml:"metadata,omitempty"`
Items
[]
ReplicationController
`json:"items" yaml:"items"`
Items
[]
PodTemplate
`json:"items" yaml:"items"`
}
// ReplicationControllerSpec is the specification of a replication controller.
// As the internal representation of a replication controller, it may have either
// a TemplateRef or a Template set.
type
ReplicationControllerSpec
struct
{
// Replicas is the number of desired replicas.
Replicas
int
`json:"replicas" yaml:"replicas"`
// Selector is a label query over pods that should match the Replicas count.
Selector
map
[
string
]
string
`json:"selector" yaml:"selector"`
// TemplateRef is a reference to an object that describes the pod that will be created if
// insufficient replicas are detected. This reference is ignored if a Template is set.
// Must be set before converting to a v1beta3 API object
TemplateRef
*
ObjectReference
`json:"templateRef,omitempty" yaml:"templateRef,omitempty"`
// Template is the object that describes the pod that will be created if
// insufficient replicas are detected. Internally, this takes precedence over a
// TemplateRef.
// Must be set before converting to a v1beta1 or v1beta2 API object.
Template
*
PodTemplateSpec
`json:"template,omitempty" yaml:"template,omitempty"`
}
// ReplicationControllerStatus represents the current status of a replication
// controller.
type
ReplicationControllerStatus
struct
{
// Replicas is the number of actual replicas.
Replicas
int
`json:"replicas" yaml:"replicas"`
}
// ReplicationController represents the configuration of a replication controller.
...
...
@@ -473,14 +522,20 @@ type ReplicationController struct {
TypeMeta
`json:",inline" yaml:",inline"`
ObjectMeta
`json:"metadata,omitempty" yaml:"metadata,omitempty"`
DesiredState
ReplicationControllerState
`json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
CurrentState
ReplicationControllerState
`json:"currentState,omitempty" yaml:"currentState,omitempty"`
// Spec defines the desired behavior of this replication controller.
Spec
ReplicationControllerSpec
`json:"spec,omitempty" yaml:"spec,omitempty"`
// Status is the current status of this replication controller. This data may be
// out of date by some window of time.
Status
ReplicationControllerStatus
`json:"status,omitempty" yaml:"status,omitempty"`
}
// PodTemplate holds the information used for creating pods.
type
PodTemplate
struct
{
DesiredState
PodState
`json:"desiredState,omitempty" yaml:"desiredState,omitempty"`
Labels
map
[
string
]
string
`json:"labels,omitempty" yaml:"labels,omitempty"`
// ReplicationControllerList is a collection of replication controllers.
type
ReplicationControllerList
struct
{
TypeMeta
`json:",inline" yaml:",inline"`
ListMeta
`json:"metadata,omitempty" yaml:"metadata,omitempty"`
Items
[]
ReplicationController
`json:"items" yaml:"items"`
}
// ServiceList holds a list of services.
...
...
@@ -872,15 +927,6 @@ type ContainerManifestList struct {
Items
[]
ContainerManifest
`json:"items" yaml:"items,omitempty"`
}
// Included in partial form from v1beta3 to replace ContainerManifest
// PodSpec is a description of a pod
type
PodSpec
struct
{
Volumes
[]
Volume
`json:"volumes" yaml:"volumes"`
Containers
[]
Container
`json:"containers" yaml:"containers"`
RestartPolicy
RestartPolicy
`json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
}
// BoundPod is a collection of containers that should be run on a host. A BoundPod
// defines how a Pod may change after a Binding is created. A Pod is a request to
// execute a pod, whereas a BoundPod is the specification that would be run on a server.
...
...
pkg/api/v1beta1/conversion.go
View file @
0348a674
...
...
@@ -256,12 +256,10 @@ func init() {
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
CurrentState
,
&
out
.
CurrentState
,
0
);
err
!=
nil
{
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
return
err
}
out
.
CurrentState
.
Replicas
=
in
.
Status
.
Replicas
return
nil
},
func
(
in
*
ReplicationController
,
out
*
newer
.
ReplicationController
,
s
conversion
.
Scope
)
error
{
...
...
@@ -275,10 +273,80 @@ func init() {
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
CurrentState
,
&
out
.
CurrentState
,
0
);
err
!=
nil
{
out
.
Status
.
Replicas
=
in
.
CurrentState
.
Replicas
return
nil
},
func
(
in
*
newer
.
ReplicationControllerSpec
,
out
*
ReplicationControllerState
,
s
conversion
.
Scope
)
error
{
out
.
Replicas
=
in
.
Replicas
if
err
:=
s
.
Convert
(
&
in
.
Selector
,
&
out
.
ReplicaSelector
,
0
);
err
!=
nil
{
return
err
}
if
in
.
TemplateRef
!=
nil
&&
in
.
Template
==
nil
{
return
errors
.
New
(
"objects with a template ref cannot be converted to older objects, must populate template"
)
}
if
in
.
Template
!=
nil
{
if
err
:=
s
.
Convert
(
in
.
Template
,
&
out
.
PodTemplate
,
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
ReplicationControllerState
,
out
*
newer
.
ReplicationControllerSpec
,
s
conversion
.
Scope
)
error
{
out
.
Replicas
=
in
.
Replicas
if
err
:=
s
.
Convert
(
&
in
.
ReplicaSelector
,
&
out
.
Selector
,
0
);
err
!=
nil
{
return
err
}
out
.
Template
=
&
newer
.
PodTemplateSpec
{}
if
err
:=
s
.
Convert
(
&
in
.
PodTemplate
,
out
.
Template
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
PodTemplateSpec
,
out
*
PodTemplate
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
DesiredState
.
Manifest
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
ObjectMeta
.
Labels
,
&
out
.
Labels
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
PodTemplate
,
out
*
newer
.
PodTemplateSpec
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
.
Manifest
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Labels
,
&
out
.
ObjectMeta
.
Labels
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
PodSpec
,
out
*
ContainerManifest
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
out
.
Version
=
"v1beta2"
return
nil
},
func
(
in
*
ContainerManifest
,
out
*
newer
.
PodSpec
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
return
nil
...
...
pkg/api/v1beta1/types.go
View file @
0348a674
...
...
@@ -749,6 +749,8 @@ type PodSpec struct {
Volumes
[]
Volume
`json:"volumes" yaml:"volumes"`
Containers
[]
Container
`json:"containers" yaml:"containers"`
RestartPolicy
RestartPolicy
`json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
// NodeSelector is a selector which must be true for the pod to fit on a node
NodeSelector
map
[
string
]
string
`json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
}
// BoundPod is a collection of containers that should be run on a host. A BoundPod
...
...
pkg/api/v1beta2/conversion.go
View file @
0348a674
...
...
@@ -186,12 +186,10 @@ func init() {
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
CurrentState
,
&
out
.
CurrentState
,
0
);
err
!=
nil
{
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
return
err
}
out
.
CurrentState
.
Replicas
=
in
.
Status
.
Replicas
return
nil
},
func
(
in
*
ReplicationController
,
out
*
newer
.
ReplicationController
,
s
conversion
.
Scope
)
error
{
...
...
@@ -205,10 +203,80 @@ func init() {
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
DesiredState
,
0
);
err
!=
nil
{
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
CurrentState
,
&
out
.
CurrentState
,
0
);
err
!=
nil
{
out
.
Status
.
Replicas
=
in
.
CurrentState
.
Replicas
return
nil
},
func
(
in
*
newer
.
ReplicationControllerSpec
,
out
*
ReplicationControllerState
,
s
conversion
.
Scope
)
error
{
out
.
Replicas
=
in
.
Replicas
if
err
:=
s
.
Convert
(
&
in
.
Selector
,
&
out
.
ReplicaSelector
,
0
);
err
!=
nil
{
return
err
}
if
in
.
TemplateRef
!=
nil
&&
in
.
Template
==
nil
{
return
errors
.
New
(
"objects with a template ref cannot be converted to older objects, must populate template"
)
}
if
in
.
Template
!=
nil
{
if
err
:=
s
.
Convert
(
in
.
Template
,
&
out
.
PodTemplate
,
0
);
err
!=
nil
{
return
err
}
}
return
nil
},
func
(
in
*
ReplicationControllerState
,
out
*
newer
.
ReplicationControllerSpec
,
s
conversion
.
Scope
)
error
{
out
.
Replicas
=
in
.
Replicas
if
err
:=
s
.
Convert
(
&
in
.
ReplicaSelector
,
&
out
.
Selector
,
0
);
err
!=
nil
{
return
err
}
out
.
Template
=
&
newer
.
PodTemplateSpec
{}
if
err
:=
s
.
Convert
(
&
in
.
PodTemplate
,
out
.
Template
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
PodTemplateSpec
,
out
*
PodTemplate
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Spec
,
&
out
.
DesiredState
.
Manifest
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
ObjectMeta
.
Labels
,
&
out
.
Labels
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
PodTemplate
,
out
*
newer
.
PodTemplateSpec
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
DesiredState
.
Manifest
,
&
out
.
Spec
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Labels
,
&
out
.
ObjectMeta
.
Labels
,
0
);
err
!=
nil
{
return
err
}
return
nil
},
func
(
in
*
newer
.
PodSpec
,
out
*
ContainerManifest
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
out
.
Version
=
"v1beta2"
return
nil
},
func
(
in
*
ContainerManifest
,
out
*
newer
.
PodSpec
,
s
conversion
.
Scope
)
error
{
if
err
:=
s
.
Convert
(
&
in
.
Volumes
,
&
out
.
Volumes
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
Containers
,
&
out
.
Containers
,
0
);
err
!=
nil
{
return
err
}
if
err
:=
s
.
Convert
(
&
in
.
RestartPolicy
,
&
out
.
RestartPolicy
,
0
);
err
!=
nil
{
return
err
}
return
nil
...
...
pkg/api/v1beta2/types.go
View file @
0348a674
...
...
@@ -750,6 +750,8 @@ type PodSpec struct {
Volumes
[]
Volume
`json:"volumes" yaml:"volumes"`
Containers
[]
Container
`json:"containers" yaml:"containers"`
RestartPolicy
RestartPolicy
`json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
// NodeSelector is a selector which must be true for the pod to fit on a node
NodeSelector
map
[
string
]
string
`json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
}
// BoundPod is a collection of containers that should be run on a host. A BoundPod
...
...
pkg/api/validation/validation.go
View file @
0348a674
...
...
@@ -167,7 +167,7 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs
if
len
(
mnt
.
Name
)
==
0
{
mErrs
=
append
(
mErrs
,
errs
.
NewFieldRequired
(
"name"
,
mnt
.
Name
))
}
else
if
!
volumes
.
Has
(
mnt
.
Name
)
{
mErrs
=
append
(
mErrs
,
errs
.
NewNotFound
(
"name"
,
mnt
.
Name
))
mErrs
=
append
(
mErrs
,
errs
.
New
Field
NotFound
(
"name"
,
mnt
.
Name
))
}
if
len
(
mnt
.
MountPath
)
==
0
{
mErrs
=
append
(
mErrs
,
errs
.
NewFieldRequired
(
"mountPath"
,
mnt
.
MountPath
))
...
...
@@ -293,6 +293,7 @@ var supportedManifestVersions = util.NewStringSet("v1beta1", "v1beta2")
// This includes checking formatting and uniqueness. It also canonicalizes the
// structure by setting default values and implementing any backwards-compatibility
// tricks.
// TODO: replaced by ValidatePodSpec
func
ValidateManifest
(
manifest
*
api
.
ContainerManifest
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
...
...
@@ -348,6 +349,21 @@ func ValidatePod(pod *api.Pod) errs.ValidationErrorList {
return
allErrs
}
// ValidatePodSpec tests that the specified PodSpec has valid data.
// This includes checking formatting and uniqueness. It also canonicalizes the
// structure by setting default values and implementing any backwards-compatibility
// tricks.
func
ValidatePodSpec
(
spec
*
api
.
PodSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allVolumes
,
vErrs
:=
validateVolumes
(
spec
.
Volumes
)
allErrs
=
append
(
allErrs
,
vErrs
.
Prefix
(
"volumes"
)
...
)
allErrs
=
append
(
allErrs
,
validateContainers
(
spec
.
Containers
,
allVolumes
)
.
Prefix
(
"containers"
)
...
)
allErrs
=
append
(
allErrs
,
validateRestartPolicy
(
&
spec
.
RestartPolicy
)
.
Prefix
(
"restartPolicy"
)
...
)
allErrs
=
append
(
allErrs
,
validateLabels
(
spec
.
NodeSelector
)
.
Prefix
(
"nodeSelector"
)
...
)
return
allErrs
}
func
validateLabels
(
labels
map
[
string
]
string
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
for
k
:=
range
labels
{
...
...
@@ -435,30 +451,44 @@ func ValidateReplicationController(controller *api.ReplicationController) errs.V
if
!
util
.
IsDNSSubdomain
(
controller
.
Namespace
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"namespace"
,
controller
.
Namespace
))
}
allErrs
=
append
(
allErrs
,
ValidateReplicationControllerS
tate
(
&
controller
.
DesiredState
)
.
Prefix
(
"desiredState
"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateReplicationControllerS
pec
(
&
controller
.
Spec
)
.
Prefix
(
"spec
"
)
...
)
allErrs
=
append
(
allErrs
,
validateLabels
(
controller
.
Labels
)
...
)
return
allErrs
}
// ValidateReplicationControllerS
tate tests if required fields in the replication controller state
are set.
func
ValidateReplicationControllerS
tate
(
state
*
api
.
ReplicationControllerState
)
errs
.
ValidationErrorList
{
// ValidateReplicationControllerS
pec tests if required fields in the replication controller spec
are set.
func
ValidateReplicationControllerS
pec
(
spec
*
api
.
ReplicationControllerSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
labels
.
Set
(
state
.
ReplicaSelector
)
.
AsSelector
()
.
Empty
()
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"replicaSelector"
,
state
.
ReplicaSelector
))
selector
:=
labels
.
Set
(
spec
.
Selector
)
.
AsSelector
()
if
selector
.
Empty
()
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"selector"
,
spec
.
Selector
))
}
selector
:=
labels
.
Set
(
state
.
ReplicaSelector
)
.
AsSelector
()
labels
:=
labels
.
Set
(
state
.
PodTemplate
.
Labels
)
if
!
selector
.
Matches
(
labels
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"podTemplate.labels"
,
state
.
PodTemplate
))
if
spec
.
Replicas
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"replicas"
,
spec
.
Replicas
))
}
allErrs
=
append
(
allErrs
,
validateLabels
(
labels
)
...
)
if
state
.
Replicas
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"replicas"
,
state
.
Replicas
))
if
spec
.
Template
==
nil
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldRequired
(
"template"
,
spec
.
Template
))
}
else
{
labels
:=
labels
.
Set
(
spec
.
Template
.
Labels
)
if
!
selector
.
Matches
(
labels
)
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"template.labels"
,
spec
.
Template
.
Labels
))
}
allErrs
=
append
(
allErrs
,
validateLabels
(
spec
.
Template
.
Labels
)
.
Prefix
(
"template.labels"
)
...
)
allErrs
=
append
(
allErrs
,
ValidatePodTemplateSpec
(
spec
.
Template
)
.
Prefix
(
"template"
)
...
)
}
allErrs
=
append
(
allErrs
,
ValidateManifest
(
&
state
.
PodTemplate
.
DesiredState
.
Manifest
)
.
Prefix
(
"podTemplate.desiredState.manifest"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateReadOnlyPersistentDisks
(
state
.
PodTemplate
.
DesiredState
.
Manifest
.
Volumes
)
.
Prefix
(
"podTemplate.desiredState.manifest"
)
...
)
return
allErrs
}
// ValidatePodTemplateSpec validates the spec of a pod template
func
ValidatePodTemplateSpec
(
spec
*
api
.
PodTemplateSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
ValidatePodSpec
(
&
spec
.
Spec
)
.
Prefix
(
"spec"
)
...
)
allErrs
=
append
(
allErrs
,
ValidateReadOnlyPersistentDisks
(
spec
.
Spec
.
Volumes
)
.
Prefix
(
"spec.volumes"
)
...
)
return
allErrs
}
func
ValidateReadOnlyPersistentDisks
(
volumes
[]
api
.
Volume
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
for
_
,
vol
:=
range
volumes
{
...
...
pkg/api/validation/validation_test.go
View file @
0348a674
...
...
@@ -862,43 +862,41 @@ func TestValidateService(t *testing.T) {
func
TestValidateReplicationController
(
t
*
testing
.
T
)
{
validSelector
:=
map
[
string
]
string
{
"a"
:
"b"
}
validPodTemplate
:=
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Version
:
"v1beta1"
,
Spec
:
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
validSelector
,
},
},
Labels
:
validSelector
,
}
invalidVolumePodTemplate
:=
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Version
:
"v1beta1"
,
Spec
:
api
.
PodTemplateSpec
{
Spec
:
api
.
PodSpec
{
Volumes
:
[]
api
.
Volume
{{
Name
:
"gcepd"
,
Source
:
&
api
.
VolumeSource
{
GCEPersistentDisk
:
&
api
.
GCEPersistentDisk
{
"my-PD"
,
"ext4"
,
1
,
false
}}}},
},
},
}
invalidSelector
:=
map
[
string
]
string
{
"NoUppercaseOrSpecialCharsLike=Equals"
:
"b"
}
invalidPodTemplate
:=
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Version
:
"v1beta1"
,
Spec
:
api
.
PodTemplateSpec
{
Spec
:
api
.
PodSpec
{},
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
invalidSelector
,
},
},
Labels
:
invalidSelector
,
}
successCases
:=
[]
api
.
ReplicationController
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
validPodTemplate
.
Spec
,
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc-123"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
validPodTemplate
.
Spec
,
},
},
}
...
...
@@ -911,49 +909,49 @@ func TestValidateReplicationController(t *testing.T) {
errorCases
:=
map
[
string
]
api
.
ReplicationController
{
"zero-length ID"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
""
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
validPodTemplate
.
Spec
,
},
},
"missing-namespace"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc-123"
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
validPodTemplate
.
Spec
,
},
},
"empty selector"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Template
:
&
validPodTemplate
.
Spec
,
},
},
"selector_doesnt_match"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
map
[
string
]
string
{
"foo"
:
"bar"
},
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"foo"
:
"bar"
},
Template
:
&
validPodTemplate
.
Spec
,
},
},
"invalid manifest"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
},
},
"read-write presistent disk"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
invalidVolumePodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
invalidVolumePodTemplate
.
Spec
,
},
},
"negative_replicas"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
DesiredState
:
api
.
ReplicationControllerState
{
Replicas
:
-
1
,
Replica
Selector
:
validSelector
,
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
-
1
,
Selector
:
validSelector
,
},
},
"invalid_label"
:
{
...
...
@@ -964,9 +962,9 @@ func TestValidateReplicationController(t *testing.T) {
"NoUppercaseOrSpecialCharsLike=Equals"
:
"bar"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
validSelector
,
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
validSelector
,
Template
:
&
validPodTemplate
.
Spec
,
},
},
"invalid_label 2"
:
{
...
...
@@ -977,8 +975,8 @@ func TestValidateReplicationController(t *testing.T) {
"NoUppercaseOrSpecialCharsLike=Equals"
:
"bar"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
PodTemplate
:
invalidPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Template
:
&
invalidPodTemplate
.
Spec
,
},
},
}
...
...
@@ -989,13 +987,14 @@ func TestValidateReplicationController(t *testing.T) {
}
for
i
:=
range
errs
{
field
:=
errs
[
i
]
.
(
errors
.
ValidationError
)
.
Field
if
!
strings
.
HasPrefix
(
field
,
"
desiredState.podT
emplate."
)
&&
if
!
strings
.
HasPrefix
(
field
,
"
spec.t
emplate."
)
&&
field
!=
"name"
&&
field
!=
"namespace"
&&
field
!=
"desiredState.replicaSelector"
&&
field
!=
"spec.selector"
&&
field
!=
"spec.template"
&&
field
!=
"GCEPersistentDisk.ReadOnly"
&&
field
!=
"
desiredState
.replicas"
&&
field
!=
"
desiredSt
ate.label"
&&
field
!=
"
spec
.replicas"
&&
field
!=
"
spec.templ
ate.label"
&&
field
!=
"label"
{
t
.
Errorf
(
"%s: missing prefix for: %v"
,
k
,
errs
[
i
])
}
...
...
pkg/client/client_test.go
View file @
0348a674
...
...
@@ -89,7 +89,7 @@ func (c *testClient) Validate(t *testing.T, received runtime.Object, err error)
c
.
ValidateCommon
(
t
,
err
)
if
c
.
Response
.
Body
!=
nil
&&
!
reflect
.
DeepEqual
(
c
.
Response
.
Body
,
received
)
{
t
.
Errorf
(
"bad response for request %#v: expected %
s, got %s
"
,
c
.
Request
,
c
.
Response
.
Body
,
received
)
t
.
Errorf
(
"bad response for request %#v: expected %
#v, got %#v
"
,
c
.
Request
,
c
.
Response
.
Body
,
received
)
}
}
...
...
@@ -97,7 +97,7 @@ func (c *testClient) ValidateRaw(t *testing.T, received []byte, err error) {
c
.
ValidateCommon
(
t
,
err
)
if
c
.
Response
.
Body
!=
nil
&&
!
reflect
.
DeepEqual
(
c
.
Response
.
Body
,
received
)
{
t
.
Errorf
(
"bad response for request %#v: expected %
s, got %s
"
,
c
.
Request
,
c
.
Response
.
Body
,
received
)
t
.
Errorf
(
"bad response for request %#v: expected %
#v, got %#v
"
,
c
.
Request
,
c
.
Response
.
Body
,
received
)
}
}
...
...
@@ -309,8 +309,9 @@ func TestListControllers(t *testing.T) {
"name"
:
"baz"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Template
:
&
api
.
PodTemplateSpec
{},
},
},
},
...
...
@@ -335,8 +336,9 @@ func TestGetController(t *testing.T) {
"name"
:
"baz"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Template
:
&
api
.
PodTemplateSpec
{},
},
},
},
...
...
@@ -361,8 +363,9 @@ func TestUpdateController(t *testing.T) {
"name"
:
"baz"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Template
:
&
api
.
PodTemplateSpec
{},
},
},
},
...
...
@@ -396,8 +399,9 @@ func TestCreateController(t *testing.T) {
"name"
:
"baz"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Template
:
&
api
.
PodTemplateSpec
{},
},
},
},
...
...
pkg/client/conditions.go
View file @
0348a674
...
...
@@ -26,10 +26,10 @@ import (
// for a controller's ReplicaSelector equals the Replicas count.
func
(
c
*
Client
)
ControllerHasDesiredReplicas
(
controller
api
.
ReplicationController
)
wait
.
ConditionFunc
{
return
func
()
(
bool
,
error
)
{
pods
,
err
:=
c
.
Pods
(
controller
.
Namespace
)
.
List
(
labels
.
Set
(
controller
.
DesiredState
.
Replica
Selector
)
.
AsSelector
())
pods
,
err
:=
c
.
Pods
(
controller
.
Namespace
)
.
List
(
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
())
if
err
!=
nil
{
return
false
,
err
}
return
len
(
pods
.
Items
)
==
controller
.
DesiredState
.
Replicas
,
nil
return
len
(
pods
.
Items
)
==
controller
.
Spec
.
Replicas
,
nil
}
}
pkg/controller/replication_controller.go
View file @
0348a674
...
...
@@ -35,14 +35,14 @@ type ReplicationManager struct {
syncTime
<-
chan
time
.
Time
// To allow injection of syncReplicationController for testing.
syncHandler
func
(
controller
Spec
api
.
ReplicationController
)
error
syncHandler
func
(
controller
api
.
ReplicationController
)
error
}
// PodControlInterface is an interface that knows how to add or delete pods
// created as an interface to allow testing.
type
PodControlInterface
interface
{
// createReplica creates new replicated pods according to the spec.
createReplica
(
namespace
string
,
controller
Spec
api
.
ReplicationController
)
createReplica
(
namespace
string
,
controller
api
.
ReplicationController
)
// deletePod deletes the pod identified by podID.
deletePod
(
namespace
string
,
podID
string
)
error
}
...
...
@@ -52,16 +52,23 @@ type RealPodControl struct {
kubeClient
client
.
Interface
}
func
(
r
RealPodControl
)
createReplica
(
namespace
string
,
controller
Spec
api
.
ReplicationController
)
{
func
(
r
RealPodControl
)
createReplica
(
namespace
string
,
controller
api
.
ReplicationController
)
{
desiredLabels
:=
make
(
labels
.
Set
)
for
k
,
v
:=
range
controller
Spec
.
DesiredState
.
Pod
Template
.
Labels
{
for
k
,
v
:=
range
controller
.
Spec
.
Template
.
Labels
{
desiredLabels
[
k
]
=
v
}
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
desiredLabels
,
},
DesiredState
:
controllerSpec
.
DesiredState
.
PodTemplate
.
DesiredState
,
}
if
err
:=
api
.
Scheme
.
Convert
(
&
controller
.
Spec
.
Template
.
Spec
,
&
pod
.
DesiredState
.
Manifest
);
err
!=
nil
{
glog
.
Errorf
(
"Unable to convert pod template: %v"
,
err
)
return
}
if
labels
.
Set
(
pod
.
Labels
)
.
AsSelector
()
.
Empty
()
{
glog
.
Errorf
(
"Unable to create pod replica, no labels"
)
return
}
if
_
,
err
:=
r
.
kubeClient
.
Pods
(
namespace
)
.
Create
(
pod
);
err
!=
nil
{
glog
.
Errorf
(
"Unable to create pod replica: %v"
,
err
)
...
...
@@ -144,14 +151,14 @@ func (rm *ReplicationManager) filterActivePods(pods []api.Pod) []api.Pod {
return
result
}
func
(
rm
*
ReplicationManager
)
syncReplicationController
(
controller
Spec
api
.
ReplicationController
)
error
{
s
:=
labels
.
Set
(
controller
Spec
.
DesiredState
.
Replica
Selector
)
.
AsSelector
()
podList
,
err
:=
rm
.
kubeClient
.
Pods
(
controller
Spec
.
Namespace
)
.
List
(
s
)
func
(
rm
*
ReplicationManager
)
syncReplicationController
(
controller
api
.
ReplicationController
)
error
{
s
:=
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
()
podList
,
err
:=
rm
.
kubeClient
.
Pods
(
controller
.
Namespace
)
.
List
(
s
)
if
err
!=
nil
{
return
err
}
filteredList
:=
rm
.
filterActivePods
(
podList
.
Items
)
diff
:=
len
(
filteredList
)
-
controller
Spec
.
DesiredState
.
Replicas
diff
:=
len
(
filteredList
)
-
controller
.
Spec
.
Replicas
if
diff
<
0
{
diff
*=
-
1
wait
:=
sync
.
WaitGroup
{}
...
...
@@ -160,7 +167,7 @@ func (rm *ReplicationManager) syncReplicationController(controllerSpec api.Repli
for
i
:=
0
;
i
<
diff
;
i
++
{
go
func
()
{
defer
wait
.
Done
()
rm
.
podControl
.
createReplica
(
controller
Spec
.
Namespace
,
controllerSpec
)
rm
.
podControl
.
createReplica
(
controller
.
Namespace
,
controller
)
}()
}
wait
.
Wait
()
...
...
@@ -171,7 +178,7 @@ func (rm *ReplicationManager) syncReplicationController(controllerSpec api.Repli
for
i
:=
0
;
i
<
diff
;
i
++
{
go
func
(
ix
int
)
{
defer
wait
.
Done
()
rm
.
podControl
.
deletePod
(
controller
Spec
.
Namespace
,
filteredList
[
ix
]
.
Name
)
rm
.
podControl
.
deletePod
(
controller
.
Namespace
,
filteredList
[
ix
]
.
Name
)
}(
i
)
}
wait
.
Wait
()
...
...
@@ -182,20 +189,20 @@ func (rm *ReplicationManager) syncReplicationController(controllerSpec api.Repli
func
(
rm
*
ReplicationManager
)
synchronize
()
{
// TODO: remove this method completely and rely on the watch.
// Add resource version tracking to watch to make this work.
var
controller
Spec
s
[]
api
.
ReplicationController
var
controllers
[]
api
.
ReplicationController
list
,
err
:=
rm
.
kubeClient
.
ReplicationControllers
(
api
.
NamespaceAll
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
glog
.
Errorf
(
"Synchronization error: %v (%#v)"
,
err
,
err
)
return
}
controller
Spec
s
=
list
.
Items
controllers
=
list
.
Items
wg
:=
sync
.
WaitGroup
{}
wg
.
Add
(
len
(
controller
Spec
s
))
for
ix
:=
range
controller
Spec
s
{
wg
.
Add
(
len
(
controllers
))
for
ix
:=
range
controllers
{
go
func
(
ix
int
)
{
defer
wg
.
Done
()
glog
.
V
(
4
)
.
Infof
(
"periodic sync of %v"
,
controller
Spec
s
[
ix
]
.
Name
)
err
:=
rm
.
syncHandler
(
controller
Spec
s
[
ix
])
glog
.
V
(
4
)
.
Infof
(
"periodic sync of %v"
,
controllers
[
ix
]
.
Name
)
err
:=
rm
.
syncHandler
(
controllers
[
ix
])
if
err
!=
nil
{
glog
.
Errorf
(
"Error synchronizing: %#v"
,
err
)
}
...
...
pkg/controller/replication_controller_test.go
View file @
0348a674
...
...
@@ -62,21 +62,21 @@ func (f *FakePodControl) deletePod(namespace string, podName string) error {
func
newReplicationController
(
replicas
int
)
api
.
ReplicationController
{
return
api
.
ReplicationController
{
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
replicas
,
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
},
},
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
},
},
},
...
...
@@ -188,21 +188,21 @@ func TestCreateReplica(t *testing.T) {
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"test"
,
},
DesiredState
:
api
.
ReplicationControllerState
{
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
Spec
:
api
.
ReplicationControllerSpec
{
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
"replicationController"
:
"test"
,
},
},
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
"replicationController"
:
"test"
,
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
},
},
},
...
...
@@ -210,11 +210,18 @@ func TestCreateReplica(t *testing.T) {
podControl
.
createReplica
(
ns
,
controllerSpec
)
manifest
:=
api
.
ContainerManifest
{}
if
err
:=
api
.
Scheme
.
Convert
(
&
controllerSpec
.
Spec
.
Template
.
Spec
,
&
manifest
);
err
!=
nil
{
t
.
Fatalf
(
"unexpected error"
,
err
)
}
expectedPod
:=
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
controllerSpec
.
DesiredState
.
PodTemplate
.
Labels
,
Labels
:
controllerSpec
.
Spec
.
Template
.
Labels
,
},
DesiredState
:
api
.
PodState
{
Manifest
:
manifest
,
},
DesiredState
:
controllerSpec
.
DesiredState
.
PodTemplate
.
DesiredState
,
}
fakeHandler
.
ValidateRequest
(
t
,
makeURL
(
"/pods?namespace=default"
),
"POST"
,
nil
)
actualPod
,
err
:=
client
.
Codec
.
Decode
([]
byte
(
fakeHandler
.
RequestBody
))
...
...
@@ -230,42 +237,42 @@ func TestCreateReplica(t *testing.T) {
func
TestSynchonize
(
t
*
testing
.
T
)
{
controllerSpec1
:=
api
.
ReplicationController
{
TypeMeta
:
api
.
TypeMeta
{
APIVersion
:
testapi
.
Version
()},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
4
,
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
},
},
Labels
:
map
[
string
]
string
{
"name"
:
"foo"
,
"type"
:
"production"
,
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"foo/bar"
,
},
},
},
},
},
}
controllerSpec2
:=
api
.
ReplicationController
{
TypeMeta
:
api
.
TypeMeta
{
APIVersion
:
testapi
.
Version
()},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
3
,
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"bar/baz"
,
},
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"bar"
,
"type"
:
"production"
,
},
},
Labels
:
map
[
string
]
string
{
"name"
:
"bar"
,
"type"
:
"production"
,
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"bar/baz"
,
},
},
},
},
},
...
...
pkg/conversion/meta.go
View file @
0348a674
...
...
@@ -116,7 +116,7 @@ func EnforcePtr(obj interface{}) (reflect.Value, error) {
if
v
.
Kind
()
==
reflect
.
Invalid
{
return
reflect
.
Value
{},
fmt
.
Errorf
(
"expected pointer, but got invalid kind"
)
}
return
reflect
.
Value
{},
fmt
.
Errorf
(
"expected pointer, but got %v type"
,
v
.
Type
()
.
Name
()
)
return
reflect
.
Value
{},
fmt
.
Errorf
(
"expected pointer, but got %v type"
,
v
.
Type
())
}
if
v
.
IsNil
()
{
return
reflect
.
Value
{},
fmt
.
Errorf
(
"expected pointer, but got nil"
)
...
...
pkg/conversion/scheme.go
View file @
0348a674
...
...
@@ -208,7 +208,7 @@ func (s *Scheme) Convert(in, out interface{}) error {
if
v
,
_
,
err
:=
s
.
ObjectVersionAndKind
(
out
);
err
==
nil
{
outVersion
=
v
}
return
s
.
converter
.
Convert
(
in
,
out
,
0
,
s
.
generateConvertMeta
(
inVersion
,
outVersion
))
return
s
.
converter
.
Convert
(
in
,
out
,
AllowDifferentFieldTypeNames
,
s
.
generateConvertMeta
(
inVersion
,
outVersion
))
}
// ConvertToVersion attempts to convert an input object to its matching Kind in another
...
...
pkg/kubecfg/kubecfg.go
View file @
0348a674
...
...
@@ -134,14 +134,14 @@ func Update(ctx api.Context, name string, client client.Interface, updatePeriod
}
if
len
(
imageName
)
!=
0
{
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
Containers
[
0
]
.
Image
=
imageName
controller
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
=
imageName
controller
,
err
=
client
.
ReplicationControllers
(
controller
.
Namespace
)
.
Update
(
controller
)
if
err
!=
nil
{
return
err
}
}
s
:=
labels
.
Set
(
controller
.
DesiredState
.
Replica
Selector
)
.
AsSelector
()
s
:=
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
()
podList
,
err
:=
client
.
Pods
(
api
.
Namespace
(
ctx
))
.
List
(
s
)
if
err
!=
nil
{
...
...
@@ -181,7 +181,7 @@ func ResizeController(ctx api.Context, name string, replicas int, client client.
if
err
!=
nil
{
return
err
}
controller
.
DesiredState
.
Replicas
=
replicas
controller
.
Spec
.
Replicas
=
replicas
controllerOut
,
err
:=
client
.
ReplicationControllers
(
api
.
Namespace
(
ctx
))
.
Update
(
controller
)
if
err
!=
nil
{
return
err
...
...
@@ -251,26 +251,25 @@ func RunController(ctx api.Context, image, name string, replicas int, client cli
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
name
,
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
replicas
,
Replica
Selector
:
map
[
string
]
string
{
Selector
:
map
[
string
]
string
{
"name"
:
name
,
},
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Version
:
"v1beta2"
,
Containers
:
[]
api
.
Container
{
{
Name
:
strings
.
ToLower
(
name
),
Image
:
image
,
Ports
:
ports
,
},
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
name
,
},
},
Labels
:
map
[
string
]
string
{
"name"
:
name
,
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Name
:
strings
.
ToLower
(
name
),
Image
:
image
,
Ports
:
ports
,
},
},
},
},
},
...
...
@@ -328,8 +327,8 @@ func DeleteController(ctx api.Context, name string, client client.Interface) err
if
err
!=
nil
{
return
err
}
if
controller
.
DesiredState
.
Replicas
!=
0
{
return
fmt
.
Errorf
(
"controller has non-zero replicas (%d), please stop it first"
,
controller
.
DesiredState
.
Replicas
)
if
controller
.
Spec
.
Replicas
!=
0
{
return
fmt
.
Errorf
(
"controller has non-zero replicas (%d), please stop it first"
,
controller
.
Spec
.
Replicas
)
}
return
client
.
ReplicationControllers
(
api
.
Namespace
(
ctx
))
.
Delete
(
name
)
}
pkg/kubecfg/kubecfg_test.go
View file @
0348a674
...
...
@@ -74,13 +74,11 @@ func TestUpdateWithNewImage(t *testing.T) {
},
},
Ctrl
:
api
.
ReplicationController
{
DesiredState
:
api
.
ReplicationControllerState
{
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"fooImage:1"
},
},
Spec
:
api
.
ReplicationControllerSpec
{
Template
:
&
api
.
PodTemplateSpec
{
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"fooImage:1"
},
},
},
},
...
...
@@ -94,7 +92,7 @@ func TestUpdateWithNewImage(t *testing.T) {
validateAction
(
client
.
FakeAction
{
Action
:
"get-controller"
,
Value
:
"foo"
},
fakeClient
.
Actions
[
0
],
t
)
newCtrl
:=
api
.
Scheme
.
CopyOrDie
(
&
fakeClient
.
Ctrl
)
.
(
*
api
.
ReplicationController
)
newCtrl
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
Containers
[
0
]
.
Image
=
"fooImage:2"
newCtrl
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
=
"fooImage:2"
validateAction
(
client
.
FakeAction
{
Action
:
"update-controller"
,
Value
:
newCtrl
},
fakeClient
.
Actions
[
1
],
t
)
validateAction
(
client
.
FakeAction
{
Action
:
"list-pods"
},
fakeClient
.
Actions
[
2
],
t
)
...
...
@@ -115,8 +113,8 @@ func TestRunController(t *testing.T) {
}
controller
:=
fakeClient
.
Actions
[
0
]
.
Value
.
(
*
api
.
ReplicationController
)
if
controller
.
Name
!=
name
||
controller
.
DesiredState
.
Replicas
!=
replicas
||
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
Containers
[
0
]
.
Image
!=
image
{
controller
.
Spec
.
Replicas
!=
replicas
||
controller
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
!=
image
{
t
.
Errorf
(
"Unexpected controller: %#v"
,
controller
)
}
}
...
...
@@ -136,8 +134,8 @@ func TestRunControllerWithWrongArgs(t *testing.T) {
}
controller
:=
fakeClient
.
Actions
[
0
]
.
Value
.
(
*
api
.
ReplicationController
)
if
controller
.
Name
!=
name
||
controller
.
DesiredState
.
Replicas
!=
replicas
||
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
Containers
[
0
]
.
Image
!=
image
{
controller
.
Spec
.
Replicas
!=
replicas
||
controller
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
!=
image
{
t
.
Errorf
(
"Unexpected controller: %#v"
,
controller
)
}
}
...
...
@@ -155,8 +153,8 @@ func TestRunControllerWithService(t *testing.T) {
}
controller
:=
fakeClient
.
Actions
[
0
]
.
Value
.
(
*
api
.
ReplicationController
)
if
controller
.
Name
!=
name
||
controller
.
DesiredState
.
Replicas
!=
replicas
||
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
Containers
[
0
]
.
Image
!=
image
{
controller
.
Spec
.
Replicas
!=
replicas
||
controller
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
Image
!=
image
{
t
.
Errorf
(
"Unexpected controller: %#v"
,
controller
)
}
}
...
...
@@ -174,7 +172,7 @@ func TestStopController(t *testing.T) {
}
controller
:=
fakeClient
.
Actions
[
1
]
.
Value
.
(
*
api
.
ReplicationController
)
if
fakeClient
.
Actions
[
1
]
.
Action
!=
"update-controller"
||
controller
.
DesiredState
.
Replicas
!=
0
{
controller
.
Spec
.
Replicas
!=
0
{
t
.
Errorf
(
"Unexpected Action: %#v"
,
fakeClient
.
Actions
[
1
])
}
}
...
...
@@ -193,7 +191,7 @@ func TestResizeController(t *testing.T) {
}
controller
:=
fakeClient
.
Actions
[
1
]
.
Value
.
(
*
api
.
ReplicationController
)
if
fakeClient
.
Actions
[
1
]
.
Action
!=
"update-controller"
||
controller
.
DesiredState
.
Replicas
!=
17
{
controller
.
Spec
.
Replicas
!=
17
{
t
.
Errorf
(
"Unexpected Action: %#v"
,
fakeClient
.
Actions
[
1
])
}
}
...
...
@@ -221,7 +219,7 @@ func TestCloudCfgDeleteController(t *testing.T) {
func
TestCloudCfgDeleteControllerWithReplicas
(
t
*
testing
.
T
)
{
fakeClient
:=
client
.
Fake
{
Ctrl
:
api
.
ReplicationController
{
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
},
},
...
...
pkg/kubecfg/parse_test.go
View file @
0348a674
...
...
@@ -107,18 +107,15 @@ func TestParseController(t *testing.T) {
DoParseTest
(
t
,
"replicationControllers"
,
&
api
.
ReplicationController
{
TypeMeta
:
api
.
TypeMeta
{
APIVersion
:
"v1beta1"
,
Kind
:
"ReplicationController"
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"my controller"
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
9001
,
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
ID
:
"My manifest"
,
Containers
:
[]
api
.
Container
{
{
Name
:
"my container"
},
},
Volumes
:
[]
api
.
Volume
{
{
Name
:
"volume"
},
},
Template
:
&
api
.
PodTemplateSpec
{
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Name
:
"my container"
},
},
Volumes
:
[]
api
.
Volume
{
{
Name
:
"volume"
},
},
},
},
...
...
pkg/kubecfg/resource_printer.go
View file @
0348a674
...
...
@@ -185,6 +185,14 @@ func makeImageList(manifest api.ContainerManifest) string {
return
strings
.
Join
(
images
,
","
)
}
func
makeImageListPodSpec
(
spec
api
.
PodSpec
)
string
{
var
images
[]
string
for
_
,
container
:=
range
spec
.
Containers
{
images
=
append
(
images
,
container
.
Image
)
}
return
strings
.
Join
(
images
,
","
)
}
func
podHostString
(
host
,
ip
string
)
string
{
if
host
==
""
&&
ip
==
""
{
return
"<unassigned>"
...
...
@@ -211,8 +219,8 @@ func printPodList(podList *api.PodList, w io.Writer) error {
func
printReplicationController
(
controller
*
api
.
ReplicationController
,
w
io
.
Writer
)
error
{
_
,
err
:=
fmt
.
Fprintf
(
w
,
"%s
\t
%s
\t
%s
\t
%d
\n
"
,
controller
.
Name
,
makeImageList
(
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
),
labels
.
Set
(
controller
.
DesiredState
.
ReplicaSelector
),
controller
.
DesiredState
.
Replicas
)
controller
.
Name
,
makeImageList
PodSpec
(
controller
.
Spec
.
Template
.
Spec
),
labels
.
Set
(
controller
.
Spec
.
Selector
),
controller
.
Spec
.
Replicas
)
return
err
}
...
...
pkg/kubectl/describe.go
View file @
0348a674
...
...
@@ -87,9 +87,15 @@ func (d *PodDescriber) Describe(namespace, name string) (string, error) {
return
""
,
err
}
// TODO: remove me when pods are converted
spec
:=
&
api
.
PodSpec
{}
if
err
:=
api
.
Scheme
.
Convert
(
&
pod
.
DesiredState
.
Manifest
,
spec
);
err
!=
nil
{
glog
.
Errorf
(
"Unable to convert pod manifest: %v"
,
err
)
}
return
tabbedString
(
func
(
out
*
tabwriter
.
Writer
)
error
{
fmt
.
Fprintf
(
out
,
"Name:
\t
%s
\n
"
,
pod
.
Name
)
fmt
.
Fprintf
(
out
,
"Image(s):
\t
%s
\n
"
,
makeImageList
(
pod
.
DesiredState
.
Manifest
))
fmt
.
Fprintf
(
out
,
"Image(s):
\t
%s
\n
"
,
makeImageList
(
spec
))
fmt
.
Fprintf
(
out
,
"Host:
\t
%s
\n
"
,
pod
.
CurrentState
.
Host
+
"/"
+
pod
.
CurrentState
.
HostIP
)
fmt
.
Fprintf
(
out
,
"Labels:
\t
%s
\n
"
,
formatLabels
(
pod
.
Labels
))
fmt
.
Fprintf
(
out
,
"Status:
\t
%s
\n
"
,
string
(
pod
.
CurrentState
.
Status
))
...
...
@@ -127,10 +133,10 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string) (strin
return
tabbedString
(
func
(
out
*
tabwriter
.
Writer
)
error
{
fmt
.
Fprintf
(
out
,
"Name:
\t
%s
\n
"
,
controller
.
Name
)
fmt
.
Fprintf
(
out
,
"Image(s):
\t
%s
\n
"
,
makeImageList
(
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
))
fmt
.
Fprintf
(
out
,
"Selector:
\t
%s
\n
"
,
formatLabels
(
controller
.
DesiredState
.
Replica
Selector
))
fmt
.
Fprintf
(
out
,
"Image(s):
\t
%s
\n
"
,
makeImageList
(
&
controller
.
Spec
.
Template
.
Spec
))
fmt
.
Fprintf
(
out
,
"Selector:
\t
%s
\n
"
,
formatLabels
(
controller
.
Spec
.
Selector
))
fmt
.
Fprintf
(
out
,
"Labels:
\t
%s
\n
"
,
formatLabels
(
controller
.
Labels
))
fmt
.
Fprintf
(
out
,
"Replicas:
\t
%d current / %d desired
\n
"
,
controller
.
CurrentState
.
Replicas
,
controller
.
DesiredState
.
Replicas
)
fmt
.
Fprintf
(
out
,
"Replicas:
\t
%d current / %d desired
\n
"
,
controller
.
Status
.
Replicas
,
controller
.
Spec
.
Replicas
)
fmt
.
Fprintf
(
out
,
"Pods Status:
\t
%d Running / %d Waiting / %d Succeeded / %d Failed
\n
"
,
running
,
waiting
,
succeeded
,
failed
)
return
nil
})
...
...
@@ -197,7 +203,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface,
// Find the ones that match labelsToMatch.
var
matchingRCs
[]
api
.
ReplicationController
for
_
,
controller
:=
range
rcs
.
Items
{
selector
:=
labels
.
SelectorFromSet
(
controller
.
DesiredState
.
Replica
Selector
)
selector
:=
labels
.
SelectorFromSet
(
controller
.
Spec
.
Selector
)
if
selector
.
Matches
(
labelsToMatch
)
{
matchingRCs
=
append
(
matchingRCs
,
controller
)
}
...
...
@@ -206,7 +212,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface,
// Format the matching RC's into strings.
var
rcStrings
[]
string
for
_
,
controller
:=
range
matchingRCs
{
rcStrings
=
append
(
rcStrings
,
fmt
.
Sprintf
(
"%s (%d/%d replicas created)"
,
controller
.
Name
,
controller
.
CurrentState
.
Replicas
,
controller
.
DesiredState
.
Replicas
))
rcStrings
=
append
(
rcStrings
,
fmt
.
Sprintf
(
"%s (%d/%d replicas created)"
,
controller
.
Name
,
controller
.
Status
.
Replicas
,
controller
.
Spec
.
Replicas
))
}
list
:=
strings
.
Join
(
rcStrings
,
", "
)
...
...
@@ -217,7 +223,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface,
}
func
getPodStatusForReplicationController
(
c
client
.
PodInterface
,
controller
*
api
.
ReplicationController
)
(
running
,
waiting
,
succeeded
,
failed
int
,
err
error
)
{
rcPods
,
err
:=
c
.
List
(
labels
.
SelectorFromSet
(
controller
.
DesiredState
.
Replica
Selector
))
rcPods
,
err
:=
c
.
List
(
labels
.
SelectorFromSet
(
controller
.
Spec
.
Selector
))
if
err
!=
nil
{
return
}
...
...
pkg/kubectl/kubectl.go
View file @
0348a674
...
...
@@ -139,9 +139,9 @@ func formatLabels(labelMap map[string]string) string {
return
l
}
func
makeImageList
(
manifest
api
.
ContainerManifest
)
string
{
func
makeImageList
(
spec
*
api
.
PodSpec
)
string
{
var
images
[]
string
for
_
,
container
:=
range
manifest
.
Containers
{
for
_
,
container
:=
range
spec
.
Containers
{
images
=
append
(
images
,
container
.
Image
)
}
return
strings
.
Join
(
images
,
","
)
...
...
pkg/kubectl/resource_printer.go
View file @
0348a674
...
...
@@ -251,8 +251,14 @@ func podHostString(host, ip string) string {
}
func
printPod
(
pod
*
api
.
Pod
,
w
io
.
Writer
)
error
{
// TODO: remove me when pods are converted
spec
:=
&
api
.
PodSpec
{}
if
err
:=
api
.
Scheme
.
Convert
(
&
pod
.
DesiredState
.
Manifest
,
spec
);
err
!=
nil
{
glog
.
Errorf
(
"Unable to convert pod manifest: %v"
,
err
)
}
_
,
err
:=
fmt
.
Fprintf
(
w
,
"%s
\t
%s
\t
%s
\t
%s
\t
%s
\n
"
,
pod
.
Name
,
makeImageList
(
pod
.
DesiredState
.
Manifest
),
pod
.
Name
,
makeImageList
(
spec
),
podHostString
(
pod
.
CurrentState
.
Host
,
pod
.
CurrentState
.
HostIP
),
labels
.
Set
(
pod
.
Labels
),
pod
.
CurrentState
.
Status
)
return
err
...
...
@@ -269,8 +275,8 @@ func printPodList(podList *api.PodList, w io.Writer) error {
func
printReplicationController
(
controller
*
api
.
ReplicationController
,
w
io
.
Writer
)
error
{
_
,
err
:=
fmt
.
Fprintf
(
w
,
"%s
\t
%s
\t
%s
\t
%d
\n
"
,
controller
.
Name
,
makeImageList
(
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
),
labels
.
Set
(
controller
.
DesiredState
.
ReplicaSelector
),
controller
.
DesiredState
.
Replicas
)
controller
.
Name
,
makeImageList
(
&
controller
.
Spec
.
Template
.
Spec
),
labels
.
Set
(
controller
.
Spec
.
Selector
),
controller
.
Spec
.
Replicas
)
return
err
}
...
...
pkg/registry/controller/rest.go
View file @
0348a674
...
...
@@ -64,8 +64,6 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
if
len
(
controller
.
Name
)
==
0
{
controller
.
Name
=
util
.
NewUUID
()
.
String
()
}
// Pod Manifest ID should be assigned by the pod API
controller
.
DesiredState
.
PodTemplate
.
DesiredState
.
Manifest
.
ID
=
""
if
errs
:=
validation
.
ValidateReplicationController
(
controller
);
len
(
errs
)
>
0
{
return
nil
,
errors
.
NewInvalid
(
"replicationController"
,
controller
.
Name
,
errs
)
}
...
...
@@ -158,41 +156,41 @@ func (rs *REST) Watch(ctx api.Context, label, field labels.Selector, resourceVer
// TODO(lavalamp): remove watch.Filter, which is broken. Implement consistent way of filtering.
// TODO(lavalamp): this watch method needs a test.
return
watch
.
Filter
(
incoming
,
func
(
e
watch
.
Event
)
(
watch
.
Event
,
bool
)
{
repC
ontroller
,
ok
:=
e
.
Object
.
(
*
api
.
ReplicationController
)
c
ontroller
,
ok
:=
e
.
Object
.
(
*
api
.
ReplicationController
)
if
!
ok
{
// must be an error event-- pass it on
return
e
,
true
}
match
:=
label
.
Matches
(
labels
.
Set
(
repC
ontroller
.
Labels
))
match
:=
label
.
Matches
(
labels
.
Set
(
c
ontroller
.
Labels
))
if
match
{
rs
.
fillCurrentState
(
ctx
,
repC
ontroller
)
rs
.
fillCurrentState
(
ctx
,
c
ontroller
)
}
return
e
,
match
}),
nil
}
func
(
rs
*
REST
)
waitForController
(
ctx
api
.
Context
,
c
trl
*
api
.
ReplicationController
)
(
runtime
.
Object
,
error
)
{
func
(
rs
*
REST
)
waitForController
(
ctx
api
.
Context
,
c
ontroller
*
api
.
ReplicationController
)
(
runtime
.
Object
,
error
)
{
for
{
pods
,
err
:=
rs
.
podLister
.
ListPods
(
ctx
,
labels
.
Set
(
c
trl
.
DesiredState
.
Replica
Selector
)
.
AsSelector
())
pods
,
err
:=
rs
.
podLister
.
ListPods
(
ctx
,
labels
.
Set
(
c
ontroller
.
Spec
.
Selector
)
.
AsSelector
())
if
err
!=
nil
{
return
c
trl
,
err
return
c
ontroller
,
err
}
if
len
(
pods
.
Items
)
==
c
trl
.
DesiredState
.
Replicas
{
if
len
(
pods
.
Items
)
==
c
ontroller
.
Spec
.
Replicas
{
break
}
time
.
Sleep
(
rs
.
pollPeriod
)
}
return
c
trl
,
nil
return
c
ontroller
,
nil
}
func
(
rs
*
REST
)
fillCurrentState
(
ctx
api
.
Context
,
c
trl
*
api
.
ReplicationController
)
error
{
func
(
rs
*
REST
)
fillCurrentState
(
ctx
api
.
Context
,
c
ontroller
*
api
.
ReplicationController
)
error
{
if
rs
.
podLister
==
nil
{
return
nil
}
list
,
err
:=
rs
.
podLister
.
ListPods
(
ctx
,
labels
.
Set
(
c
trl
.
DesiredState
.
Replica
Selector
)
.
AsSelector
())
list
,
err
:=
rs
.
podLister
.
ListPods
(
ctx
,
labels
.
Set
(
c
ontroller
.
Spec
.
Selector
)
.
AsSelector
())
if
err
!=
nil
{
return
err
}
c
trl
.
CurrentState
.
Replicas
=
len
(
list
.
Items
)
c
ontroller
.
Status
.
Replicas
=
len
(
list
.
Items
)
return
nil
}
pkg/registry/controller/rest_test.go
View file @
0348a674
...
...
@@ -116,6 +116,15 @@ func TestControllerDecode(t *testing.T) {
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
},
Spec
:
api
.
ReplicationControllerSpec
{
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"nginx"
,
},
},
},
},
}
body
,
err
:=
latest
.
Codec
.
Encode
(
controller
)
if
err
!=
nil
{
...
...
@@ -140,30 +149,30 @@ func TestControllerParsing(t *testing.T) {
"name"
:
"nginx"
,
},
},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Replica
Selector
:
map
[
string
]
string
{
Selector
:
map
[
string
]
string
{
"name"
:
"nginx"
,
},
PodTemplate
:
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
Image
:
"dockerfile/nginx"
,
Ports
:
[]
api
.
Port
{
{
ContainerPort
:
80
,
HostPort
:
8080
,
},
Template
:
&
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"name"
:
"nginx"
,
},
},
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Image
:
"dockerfile/nginx"
,
Ports
:
[]
api
.
Port
{
{
ContainerPort
:
80
,
HostPort
:
8080
,
},
},
},
},
},
Labels
:
map
[
string
]
string
{
"name"
:
"nginx"
,
},
},
},
}
...
...
@@ -205,9 +214,11 @@ func TestControllerParsing(t *testing.T) {
}
var
validPodTemplate
=
api
.
PodTemplate
{
DesiredState
:
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Version
:
"v1beta1"
,
Spec
:
api
.
PodTemplateSpec
{
ObjectMeta
:
api
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
"a"
:
"b"
},
},
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Name
:
"test"
,
...
...
@@ -216,7 +227,6 @@ var validPodTemplate = api.PodTemplate{
},
},
},
Labels
:
map
[
string
]
string
{
"a"
:
"b"
},
}
func
TestCreateController
(
t
*
testing
.
T
)
{
...
...
@@ -240,10 +250,10 @@ func TestCreateController(t *testing.T) {
}
controller
:=
&
api
.
ReplicationController
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"test"
},
DesiredState
:
api
.
ReplicationControllerState
{
Replicas
:
2
,
Replica
Selector
:
map
[
string
]
string
{
"a"
:
"b"
},
PodTemplate
:
validPodTemplate
,
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
Selector
:
map
[
string
]
string
{
"a"
:
"b"
},
Template
:
&
validPodTemplate
.
Spec
,
},
}
ctx
:=
api
.
NewDefaultContext
()
...
...
@@ -273,13 +283,13 @@ func TestControllerStorageValidatesCreate(t *testing.T) {
failureCases
:=
map
[
string
]
api
.
ReplicationController
{
"empty ID"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
""
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
map
[
string
]
string
{
"bar"
:
"baz"
},
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"bar"
:
"baz"
},
},
},
"empty selector"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
},
DesiredState
:
api
.
ReplicationControllerState
{},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
},
Spec
:
api
.
ReplicationControllerSpec
{},
},
}
ctx
:=
api
.
NewDefaultContext
()
...
...
@@ -304,13 +314,13 @@ func TestControllerStorageValidatesUpdate(t *testing.T) {
failureCases
:=
map
[
string
]
api
.
ReplicationController
{
"empty ID"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
""
},
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
map
[
string
]
string
{
"bar"
:
"baz"
},
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"bar"
:
"baz"
},
},
},
"empty selector"
:
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
},
DesiredState
:
api
.
ReplicationControllerState
{},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
},
Spec
:
api
.
ReplicationControllerSpec
{},
},
}
ctx
:=
api
.
NewDefaultContext
()
...
...
@@ -351,19 +361,19 @@ func TestFillCurrentState(t *testing.T) {
podLister
:
&
fakeLister
,
}
controller
:=
api
.
ReplicationController
{
DesiredState
:
api
.
ReplicationControllerState
{
Replica
Selector
:
map
[
string
]
string
{
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"foo"
:
"bar"
,
},
},
}
ctx
:=
api
.
NewContext
()
storage
.
fillCurrentState
(
ctx
,
&
controller
)
if
controller
.
CurrentState
.
Replicas
!=
2
{
t
.
Errorf
(
"expected 2, got: %d"
,
controller
.
CurrentState
.
Replicas
)
if
controller
.
Status
.
Replicas
!=
2
{
t
.
Errorf
(
"expected 2, got: %d"
,
controller
.
Status
.
Replicas
)
}
if
!
reflect
.
DeepEqual
(
fakeLister
.
s
,
labels
.
Set
(
controller
.
DesiredState
.
Replica
Selector
)
.
AsSelector
())
{
t
.
Errorf
(
"unexpected output: %#v %#v"
,
labels
.
Set
(
controller
.
DesiredState
.
Replica
Selector
)
.
AsSelector
(),
fakeLister
.
s
)
if
!
reflect
.
DeepEqual
(
fakeLister
.
s
,
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
())
{
t
.
Errorf
(
"unexpected output: %#v %#v"
,
labels
.
Set
(
controller
.
Spec
.
Selector
)
.
AsSelector
(),
fakeLister
.
s
)
}
}
...
...
pkg/registry/etcd/etcd_test.go
View file @
0348a674
...
...
@@ -960,7 +960,7 @@ func TestEtcdUpdateController(t *testing.T) {
registry
:=
NewTestEtcdRegistry
(
fakeClient
)
err
:=
registry
.
UpdateController
(
ctx
,
&
api
.
ReplicationController
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
ResourceVersion
:
strconv
.
FormatUint
(
resp
.
Node
.
ModifiedIndex
,
10
)},
DesiredState
:
api
.
ReplicationControllerState
{
Spec
:
api
.
ReplicationControllerSpec
{
Replicas
:
2
,
},
})
...
...
@@ -969,7 +969,7 @@ func TestEtcdUpdateController(t *testing.T) {
}
ctrl
,
err
:=
registry
.
GetController
(
ctx
,
"foo"
)
if
ctrl
.
DesiredState
.
Replicas
!=
2
{
if
ctrl
.
Spec
.
Replicas
!=
2
{
t
.
Errorf
(
"Unexpected controller: %#v"
,
ctrl
)
}
}
...
...
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