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
7adb463d
Commit
7adb463d
authored
Sep 30, 2015
by
Nikhil Jindal
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14199 from nikhiljindal/deploymentDescribe
Adding a DeploymentDescriber to kubectl
parents
ff5c0f95
153c57ff
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
184 additions
and
72 deletions
+184
-72
deployment_controller.go
pkg/controller/deployment/deployment_controller.go
+8
-70
describe.go
pkg/kubectl/describe.go
+46
-2
describe_test.go
pkg/kubectl/describe_test.go
+21
-0
deployment.go
pkg/util/deployment/deployment.go
+109
-0
No files found.
pkg/controller/deployment/deployment_controller.go
View file @
7adb463d
...
...
@@ -18,7 +18,6 @@ package deployment
import
(
"fmt"
"hash/adler32"
"math"
"time"
...
...
@@ -28,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util"
deploymentUtil
"k8s.io/kubernetes/pkg/util/deployment"
)
type
DeploymentController
struct
{
...
...
@@ -116,59 +116,21 @@ func (d *DeploymentController) reconcileRollingUpdateDeployment(deployment exper
}
func
(
d
*
DeploymentController
)
getOldRCs
(
deployment
experimental
.
Deployment
)
([]
*
api
.
ReplicationController
,
error
)
{
namespace
:=
deployment
.
ObjectMeta
.
Namespace
// 1. Find all pods whose labels match deployment.Spec.Selector
podList
,
err
:=
d
.
client
.
Pods
(
namespace
)
.
List
(
labels
.
SelectorFromSet
(
deployment
.
Spec
.
Selector
),
fields
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing pods: %v"
,
err
)
}
// 2. Find the corresponding RCs for pods in podList.
// TODO: Right now we list all RCs and then filter. We should add an API for this.
oldRCs
:=
map
[
string
]
api
.
ReplicationController
{}
rcList
,
err
:=
d
.
client
.
ReplicationControllers
(
namespace
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing replication controllers: %v"
,
err
)
}
for
_
,
pod
:=
range
podList
.
Items
{
podLabelsSelector
:=
labels
.
Set
(
pod
.
ObjectMeta
.
Labels
)
for
_
,
rc
:=
range
rcList
.
Items
{
rcLabelsSelector
:=
labels
.
SelectorFromSet
(
rc
.
Spec
.
Selector
)
if
rcLabelsSelector
.
Matches
(
podLabelsSelector
)
{
// Filter out RC that has the same pod template spec as the deployment - that is the new RC.
if
api
.
Semantic
.
DeepEqual
(
rc
.
Spec
.
Template
,
getNewRCTemplate
(
deployment
))
{
continue
}
oldRCs
[
rc
.
ObjectMeta
.
Name
]
=
rc
}
}
}
requiredRCs
:=
[]
*
api
.
ReplicationController
{}
for
_
,
value
:=
range
oldRCs
{
requiredRCs
=
append
(
requiredRCs
,
&
value
)
}
return
requiredRCs
,
nil
return
deploymentUtil
.
GetOldRCs
(
deployment
,
d
.
client
)
}
// Returns an RC that matches the intent of the given deployment.
// It creates a new RC if required.
func
(
d
*
DeploymentController
)
getNewRC
(
deployment
experimental
.
Deployment
)
(
*
api
.
ReplicationController
,
error
)
{
namespace
:=
deployment
.
ObjectMeta
.
Namespace
// Find if the required RC exists already.
rcList
,
err
:=
d
.
client
.
ReplicationControllers
(
namespace
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing replication controllers: %v"
,
err
)
}
newRCTemplate
:=
getNewRCTemplate
(
deployment
)
for
_
,
rc
:=
range
rcList
.
Items
{
if
api
.
Semantic
.
DeepEqual
(
rc
.
Spec
.
Template
,
newRCTemplate
)
{
// This is the new RC.
return
&
rc
,
nil
}
existingNewRC
,
err
:=
deploymentUtil
.
GetNewRC
(
deployment
,
d
.
client
)
if
err
!=
nil
||
existingNewRC
!=
nil
{
return
existingNewRC
,
err
}
// new RC does not exist, create one.
podTemplateSpecHash
:=
getPodTemplateSpecHash
(
deployment
.
Spec
.
Template
)
namespace
:=
deployment
.
ObjectMeta
.
Namespace
podTemplateSpecHash
:=
deploymentUtil
.
GetPodTemplateSpecHash
(
deployment
.
Spec
.
Template
)
rcName
:=
fmt
.
Sprintf
(
"deploymentrc-%d"
,
podTemplateSpecHash
)
newRCTemplate
:=
deploymentUtil
.
GetNewRCTemplate
(
deployment
)
newRC
:=
api
.
ReplicationController
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
rcName
,
...
...
@@ -187,30 +149,6 @@ func (d *DeploymentController) getNewRC(deployment experimental.Deployment) (*ap
return
createdRC
,
nil
}
func
getNewRCTemplate
(
deployment
experimental
.
Deployment
)
*
api
.
PodTemplateSpec
{
// newRC will have the same template as in deployment spec, plus a unique label in some cases.
newRCTemplate
:=
&
api
.
PodTemplateSpec
{
ObjectMeta
:
deployment
.
Spec
.
Template
.
ObjectMeta
,
Spec
:
deployment
.
Spec
.
Template
.
Spec
,
}
podTemplateSpecHash
:=
getPodTemplateSpecHash
(
newRCTemplate
)
if
deployment
.
Spec
.
UniqueLabelKey
!=
""
{
newLabels
:=
map
[
string
]
string
{}
for
key
,
value
:=
range
deployment
.
Spec
.
Template
.
ObjectMeta
.
Labels
{
newLabels
[
key
]
=
value
}
newLabels
[
deployment
.
Spec
.
UniqueLabelKey
]
=
fmt
.
Sprintf
(
"%d"
,
podTemplateSpecHash
)
newRCTemplate
.
ObjectMeta
.
Labels
=
newLabels
}
return
newRCTemplate
}
func
getPodTemplateSpecHash
(
template
*
api
.
PodTemplateSpec
)
uint32
{
podTemplateSpecHasher
:=
adler32
.
New
()
util
.
DeepHashObject
(
podTemplateSpecHasher
,
template
)
return
podTemplateSpecHasher
.
Sum32
()
}
func
(
d
*
DeploymentController
)
getPodsForRCs
(
replicationControllers
[]
*
api
.
ReplicationController
)
([]
api
.
Pod
,
error
)
{
allPods
:=
[]
api
.
Pod
{}
for
_
,
rc
:=
range
replicationControllers
{
...
...
pkg/kubectl/describe.go
View file @
7adb463d
...
...
@@ -35,6 +35,7 @@ import (
qosutil
"k8s.io/kubernetes/pkg/kubelet/qos/util"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/types"
deploymentUtil
"k8s.io/kubernetes/pkg/util/deployment"
"k8s.io/kubernetes/pkg/util/sets"
)
...
...
@@ -88,6 +89,7 @@ func expDescriberMap(c *client.Client) map[string]Describer {
"HorizontalPodAutoscaler"
:
&
HorizontalPodAutoscalerDescriber
{
c
},
"DaemonSet"
:
&
DaemonSetDescriber
{
c
},
"Job"
:
&
JobDescriber
{
c
},
"Deployment"
:
&
DeploymentDescriber
{
c
},
}
}
...
...
@@ -478,7 +480,11 @@ func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.Even
fmt
.
Fprintf
(
out
,
"Reason:
\t
%s
\n
"
,
pod
.
Status
.
Reason
)
fmt
.
Fprintf
(
out
,
"Message:
\t
%s
\n
"
,
pod
.
Status
.
Message
)
fmt
.
Fprintf
(
out
,
"IP:
\t
%s
\n
"
,
pod
.
Status
.
PodIP
)
fmt
.
Fprintf
(
out
,
"Replication Controllers:
\t
%s
\n
"
,
printReplicationControllersByLabels
(
rcs
))
var
matchingRCs
[]
*
api
.
ReplicationController
for
_
,
rc
:=
range
rcs
{
matchingRCs
=
append
(
matchingRCs
,
&
rc
)
}
fmt
.
Fprintf
(
out
,
"Replication Controllers:
\t
%s
\n
"
,
printReplicationControllersByLabels
(
matchingRCs
))
fmt
.
Fprintf
(
out
,
"Containers:
\n
"
)
describeContainers
(
pod
,
out
)
if
len
(
pod
.
Status
.
Conditions
)
>
0
{
...
...
@@ -1395,6 +1401,44 @@ func DescribeEvents(el *api.EventList, w io.Writer) {
}
}
// DeploymentDescriber generates information about a deployment.
type
DeploymentDescriber
struct
{
client
.
Interface
}
func
(
dd
*
DeploymentDescriber
)
Describe
(
namespace
,
name
string
)
(
string
,
error
)
{
d
,
err
:=
dd
.
Experimental
()
.
Deployments
(
namespace
)
.
Get
(
name
)
if
err
!=
nil
{
return
""
,
err
}
return
tabbedString
(
func
(
out
io
.
Writer
)
error
{
fmt
.
Fprintf
(
out
,
"Name:
\t
%s
\n
"
,
d
.
ObjectMeta
.
Name
)
fmt
.
Fprintf
(
out
,
"Namespace:
\t
%s
\n
"
,
d
.
ObjectMeta
.
Namespace
)
fmt
.
Fprintf
(
out
,
"CreationTimestamp:
\t
%s
\n
"
,
d
.
CreationTimestamp
.
Time
.
Format
(
time
.
RFC1123Z
))
fmt
.
Fprintf
(
out
,
"Labels:
\t
%s
\n
"
,
labels
.
FormatLabels
(
d
.
Labels
))
fmt
.
Fprintf
(
out
,
"Selector:
\t
%s
\n
"
,
labels
.
FormatLabels
(
d
.
Spec
.
Selector
))
fmt
.
Fprintf
(
out
,
"Replicas:
\t
%d updated / %d total
\n
"
,
d
.
Status
.
UpdatedReplicas
,
d
.
Spec
.
Replicas
)
fmt
.
Fprintf
(
out
,
"StrategyType:
\t
%s
\n
"
,
d
.
Spec
.
Strategy
.
Type
)
if
d
.
Spec
.
Strategy
.
RollingUpdate
!=
nil
{
ru
:=
d
.
Spec
.
Strategy
.
RollingUpdate
fmt
.
Fprintf
(
out
,
"RollingUpdateStrategy:
\t
%s max unavailable, %s max surge, %d min ready seconds
\n
"
,
ru
.
MaxUnavailable
.
String
(),
ru
.
MaxSurge
.
String
(),
ru
.
MinReadySeconds
)
}
oldRCs
,
err
:=
deploymentUtil
.
GetOldRCs
(
*
d
,
dd
)
if
err
==
nil
{
fmt
.
Fprintf
(
out
,
"OldReplicationControllers:
\t
%s
\n
"
,
printReplicationControllersByLabels
(
oldRCs
))
}
newRC
,
err
:=
deploymentUtil
.
GetNewRC
(
*
d
,
dd
)
if
err
==
nil
{
var
newRCs
[]
*
api
.
ReplicationController
if
newRC
!=
nil
{
newRCs
=
append
(
newRCs
,
newRC
)
}
fmt
.
Fprintf
(
out
,
"NewReplicationController:
\t
%s
\n
"
,
printReplicationControllersByLabels
(
newRCs
))
}
return
nil
})
}
// Get all daemon set whose selectors would match a given set of labels.
// TODO: Move this to pkg/client and ideally implement it server-side (instead
// of getting all DS's and searching through them manually).
...
...
@@ -1442,7 +1486,7 @@ func getReplicationControllersForLabels(c client.ReplicationControllerInterface,
return
matchingRCs
,
nil
}
func
printReplicationControllersByLabels
(
matchingRCs
[]
api
.
ReplicationController
)
string
{
func
printReplicationControllersByLabels
(
matchingRCs
[]
*
api
.
ReplicationController
)
string
{
// Format the matching RC's into strings.
var
rcStrings
[]
string
for
_
,
controller
:=
range
matchingRCs
{
...
...
pkg/kubectl/describe_test.go
View file @
7adb463d
...
...
@@ -27,6 +27,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/experimental"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
)
...
...
@@ -476,6 +477,26 @@ func TestPersistentVolumeDescriber(t *testing.T) {
if
str
==
""
{
t
.
Errorf
(
"Unexpected empty string for test %s. Expected PV Describer output"
,
name
)
}
}
}
func
TestDescribeDeployment
(
t
*
testing
.
T
)
{
fake
:=
testclient
.
NewSimpleFake
(
&
experimental
.
Deployment
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"bar"
,
Namespace
:
"foo"
,
},
Spec
:
experimental
.
DeploymentSpec
{
Template
:
&
api
.
PodTemplateSpec
{},
},
})
c
:=
&
describeClient
{
T
:
t
,
Namespace
:
"foo"
,
Interface
:
fake
}
d
:=
DeploymentDescriber
{
c
}
out
,
err
:=
d
.
Describe
(
"foo"
,
"bar"
)
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
if
!
strings
.
Contains
(
out
,
"bar"
)
||
!
strings
.
Contains
(
out
,
"foo"
)
{
t
.
Errorf
(
"unexpected out: %s"
,
out
)
}
}
pkg/util/deployment/deployment.go
0 → 100644
View file @
7adb463d
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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
deployment
import
(
"fmt"
"hash/adler32"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/experimental"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util"
)
// Returns the old RCs targetted by the given Deployment.
func
GetOldRCs
(
deployment
experimental
.
Deployment
,
c
client
.
Interface
)
([]
*
api
.
ReplicationController
,
error
)
{
namespace
:=
deployment
.
ObjectMeta
.
Namespace
// 1. Find all pods whose labels match deployment.Spec.Selector
podList
,
err
:=
c
.
Pods
(
namespace
)
.
List
(
labels
.
SelectorFromSet
(
deployment
.
Spec
.
Selector
),
fields
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing pods: %v"
,
err
)
}
// 2. Find the corresponding RCs for pods in podList.
// TODO: Right now we list all RCs and then filter. We should add an API for this.
oldRCs
:=
map
[
string
]
api
.
ReplicationController
{}
rcList
,
err
:=
c
.
ReplicationControllers
(
namespace
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing replication controllers: %v"
,
err
)
}
for
_
,
pod
:=
range
podList
.
Items
{
podLabelsSelector
:=
labels
.
Set
(
pod
.
ObjectMeta
.
Labels
)
for
_
,
rc
:=
range
rcList
.
Items
{
rcLabelsSelector
:=
labels
.
SelectorFromSet
(
rc
.
Spec
.
Selector
)
if
rcLabelsSelector
.
Matches
(
podLabelsSelector
)
{
// Filter out RC that has the same pod template spec as the deployment - that is the new RC.
if
api
.
Semantic
.
DeepEqual
(
rc
.
Spec
.
Template
,
GetNewRCTemplate
(
deployment
))
{
continue
}
oldRCs
[
rc
.
ObjectMeta
.
Name
]
=
rc
}
}
}
requiredRCs
:=
[]
*
api
.
ReplicationController
{}
for
_
,
value
:=
range
oldRCs
{
requiredRCs
=
append
(
requiredRCs
,
&
value
)
}
return
requiredRCs
,
nil
}
// Returns an RC that matches the intent of the given deployment.
// Returns nil if the new RC doesnt exist yet.
func
GetNewRC
(
deployment
experimental
.
Deployment
,
c
client
.
Interface
)
(
*
api
.
ReplicationController
,
error
)
{
namespace
:=
deployment
.
ObjectMeta
.
Namespace
rcList
,
err
:=
c
.
ReplicationControllers
(
namespace
)
.
List
(
labels
.
Everything
())
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error listing replication controllers: %v"
,
err
)
}
newRCTemplate
:=
GetNewRCTemplate
(
deployment
)
for
_
,
rc
:=
range
rcList
.
Items
{
if
api
.
Semantic
.
DeepEqual
(
rc
.
Spec
.
Template
,
newRCTemplate
)
{
// This is the new RC.
return
&
rc
,
nil
}
}
// new RC does not exist.
return
nil
,
nil
}
// Returns the desired PodTemplateSpec for the new RC corresponding to the given RC.
func
GetNewRCTemplate
(
deployment
experimental
.
Deployment
)
*
api
.
PodTemplateSpec
{
// newRC will have the same template as in deployment spec, plus a unique label in some cases.
newRCTemplate
:=
&
api
.
PodTemplateSpec
{
ObjectMeta
:
deployment
.
Spec
.
Template
.
ObjectMeta
,
Spec
:
deployment
.
Spec
.
Template
.
Spec
,
}
podTemplateSpecHash
:=
GetPodTemplateSpecHash
(
newRCTemplate
)
if
deployment
.
Spec
.
UniqueLabelKey
!=
""
{
newLabels
:=
map
[
string
]
string
{}
for
key
,
value
:=
range
deployment
.
Spec
.
Template
.
ObjectMeta
.
Labels
{
newLabels
[
key
]
=
value
}
newLabels
[
deployment
.
Spec
.
UniqueLabelKey
]
=
fmt
.
Sprintf
(
"%d"
,
podTemplateSpecHash
)
newRCTemplate
.
ObjectMeta
.
Labels
=
newLabels
}
return
newRCTemplate
}
func
GetPodTemplateSpecHash
(
template
*
api
.
PodTemplateSpec
)
uint32
{
podTemplateSpecHasher
:=
adler32
.
New
()
util
.
DeepHashObject
(
podTemplateSpecHasher
,
template
)
return
podTemplateSpecHasher
.
Sum32
()
}
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