Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
凌波微步_大先生
dashboard
提交
d10182e4
D
dashboard
项目概览
凌波微步_大先生
/
dashboard
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dashboard
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d10182e4
编写于
1月 19, 2016
作者:
P
Piotr Bryk
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into fix-go-command
上级
6b26b6dc
4a27b78e
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
323 addition
and
126 deletion
+323
-126
src/app/backend/apihandler.go
src/app/backend/apihandler.go
+9
-1
src/app/backend/logs.go
src/app/backend/logs.go
+17
-7
src/app/backend/replicasetlist.go
src/app/backend/replicasetlist.go
+75
-32
src/app/backend/replicasetpods.go
src/app/backend/replicasetpods.go
+3
-1
src/app/externs/backendapi.js
src/app/externs/backendapi.js
+3
-3
src/app/frontend/chrome/chrome.scss
src/app/frontend/chrome/chrome.scss
+12
-0
src/app/frontend/logs/logs_controller.js
src/app/frontend/logs/logs_controller.js
+8
-8
src/app/frontend/logs/logs_state.js
src/app/frontend/logs/logs_state.js
+2
-2
src/app/frontend/logs/logs_stateconfig.js
src/app/frontend/logs/logs_stateconfig.js
+4
-3
src/app/frontend/logs/logstoolbar/logstoolbar_controller.js
src/app/frontend/logs/logstoolbar/logstoolbar_controller.js
+30
-26
src/app/frontend/replicasetdetail/replicasetdetail.html
src/app/frontend/replicasetdetail/replicasetdetail.html
+5
-3
src/app/frontend/replicasetdetail/replicasetdetail.scss
src/app/frontend/replicasetdetail/replicasetdetail.scss
+0
-3
src/app/frontend/replicasetdetail/replicasetdetail_controller.js
.../frontend/replicasetdetail/replicasetdetail_controller.js
+11
-0
src/app/frontend/replicasetdetail/replicasetdetail_module.js
src/app/frontend/replicasetdetail/replicasetdetail_module.js
+3
-1
src/app/frontend/replicasetdetail/sortedheader.html
src/app/frontend/replicasetdetail/sortedheader.html
+3
-3
src/app/frontend/replicasetdetail/sortedheader.scss
src/app/frontend/replicasetdetail/sortedheader.scss
+0
-7
src/app/frontend/replicasetlist/logsmenu.html
src/app/frontend/replicasetlist/logsmenu.html
+3
-3
src/app/frontend/replicasetlist/logsmenu_controller.js
src/app/frontend/replicasetlist/logsmenu_controller.js
+2
-4
src/app/frontend/replicasetlist/replicasetcard.html
src/app/frontend/replicasetlist/replicasetcard.html
+13
-2
src/app/frontend/replicasetlist/replicasetcard.scss
src/app/frontend/replicasetlist/replicasetcard.scss
+9
-6
src/test/backend/replicasetlist_test.go
src/test/backend/replicasetlist_test.go
+90
-6
src/test/backend/replicasetpods_test.go
src/test/backend/replicasetpods_test.go
+1
-1
src/test/frontend/logs/logstoolbar/logstoolbar_controller_test.js
.../frontend/logs/logstoolbar/logstoolbar_controller_test.js
+7
-2
src/test/frontend/replicasetdetail/replicasetdetail_controller_test.js
...tend/replicasetdetail/replicasetdetail_controller_test.js
+13
-2
未找到文件。
src/app/backend/apihandler.go
浏览文件 @
d10182e4
...
...
@@ -87,6 +87,10 @@ func CreateHttpApiHandler(client *client.Client) http.Handler {
logsWs
:=
new
(
restful
.
WebService
)
logsWs
.
Path
(
"/api/logs"
)
.
Produces
(
restful
.
MIME_JSON
)
logsWs
.
Route
(
logsWs
.
GET
(
"/{namespace}/{podId}"
)
.
To
(
apiHandler
.
handleLogs
)
.
Writes
(
Logs
{}))
logsWs
.
Route
(
logsWs
.
GET
(
"/{namespace}/{podId}/{container}"
)
.
To
(
apiHandler
.
handleLogs
)
.
...
...
@@ -259,7 +263,11 @@ func (apiHandler *ApiHandler) handleLogs(request *restful.Request, response *res
namespace
:=
request
.
PathParameter
(
"namespace"
)
podId
:=
request
.
PathParameter
(
"podId"
)
container
:=
request
.
PathParameter
(
"container"
)
result
,
err
:=
GetPodLogs
(
apiHandler
.
client
,
namespace
,
podId
,
container
)
var
containerPtr
*
string
=
nil
if
len
(
container
)
>
0
{
containerPtr
=
&
container
}
result
,
err
:=
GetPodLogs
(
apiHandler
.
client
,
namespace
,
podId
,
containerPtr
)
if
err
!=
nil
{
handleInternalError
(
response
,
err
)
return
...
...
src/app/backend/logs.go
浏览文件 @
d10182e4
...
...
@@ -26,17 +26,23 @@ import (
// Log response structure
type
Logs
struct
{
// Pod
id
// Pod
name.
PodId
string
`json:"podId"`
// Specific time when logs started
// Specific time when logs started.
SinceTime
unversioned
.
Time
`json:"sinceTime"`
// Logs string
// Logs string lines.
Logs
[]
string
`json:"logs"`
// The name of the container the logs are for.
Container
string
`json:"container"`
}
// Return logs for particular pod and container or error when occurred.
func
GetPodLogs
(
client
*
client
.
Client
,
namespace
,
podId
,
container
string
)
(
*
Logs
,
error
)
{
log
.
Printf
(
"Getting logs from %s container from %s pod in %s namespace"
,
container
,
podId
,
// Return logs for particular pod and container or error when occurred. When container is null,
// logs for the first one are returned.
func
GetPodLogs
(
client
*
client
.
Client
,
namespace
,
podId
string
,
container
*
string
)
(
*
Logs
,
error
)
{
log
.
Printf
(
"Getting logs from %v container from %s pod in %s namespace"
,
container
,
podId
,
namespace
)
pod
,
err
:=
client
.
Pods
(
namespace
)
.
Get
(
podId
)
...
...
@@ -44,8 +50,12 @@ func GetPodLogs(client *client.Client, namespace, podId, container string) (*Log
return
nil
,
err
}
if
container
==
nil
{
container
=
&
pod
.
Spec
.
Containers
[
0
]
.
Name
}
logOptions
:=
&
api
.
PodLogOptions
{
Container
:
container
,
Container
:
*
container
,
Follow
:
false
,
Previous
:
false
,
Timestamps
:
true
,
...
...
src/app/backend/replicasetlist.go
浏览文件 @
d10182e4
...
...
@@ -24,13 +24,13 @@ import (
"k8s.io/kubernetes/pkg/labels"
)
//
L
ist of Replica Sets in the cluster.
//
ReplicaSetList contains a l
ist of Replica Sets in the cluster.
type
ReplicaSetList
struct
{
// Unordered list of Replica Sets.
ReplicaSets
[]
ReplicaSet
`json:"replicaSets"`
}
//
Kubernetes Replica
Set (aka. Replication Controller) plus zero or more Kubernetes services that
//
Replica
Set (aka. Replication Controller) plus zero or more Kubernetes services that
// target the Replica Set.
type
ReplicaSet
struct
{
// Name of the Replica Set.
...
...
@@ -45,11 +45,8 @@ type ReplicaSet struct {
// Label of this Replica Set.
Labels
map
[
string
]
string
`json:"labels"`
// Number of pods that are currently running.
PodsRunning
int
`json:"podsRunning"`
// Number of pods that are pending in this Replica Set.
PodsPending
int
`json:"podsPending"`
// Aggergate information about pods belonging to this repolica set.
Pods
ReplicaSetPodInfo
`json:"pods"`
// Container images of the Replica Set.
ContainerImages
[]
string
`json:"containerImages"`
...
...
@@ -64,38 +61,59 @@ type ReplicaSet struct {
ExternalEndpoints
[]
Endpoint
`json:"externalEndpoints"`
}
// Returns a list of all Replica Sets in the cluster.
// ReplicaSetPodInfo represents aggregate information about replica set pods.
type
ReplicaSetPodInfo
struct
{
// Number of pods that are created.
Curret
int
`json:"current"`
// Number of pods that are desired in this Replica Set.
Desired
int
`json:"desired"`
// Number of pods that are currently running.
Running
int
`json:"running"`
// Number of pods that are currently waiting.
Waiting
int
`json:"waiting"`
// Number of pods that are failed.
Failed
int
`json:"failed"`
}
// GetReplicaSetList returns a list of all Replica Sets in the cluster.
func
GetReplicaSetList
(
client
*
client
.
Client
)
(
*
ReplicaSetList
,
error
)
{
log
.
Printf
(
"Getting list of all replica sets in the cluster"
)
replicaSets
,
err
:=
client
.
ReplicationControllers
(
api
.
NamespaceAll
)
.
List
(
unversioned
.
ListOptions
{
LabelSelector
:
unversioned
.
LabelSelector
{
labels
.
Everything
()},
FieldSelector
:
unversioned
.
FieldSelector
{
fields
.
Everything
()},
})
listEverything
:=
unversioned
.
ListOptions
{
LabelSelector
:
unversioned
.
LabelSelector
{
labels
.
Everything
()},
FieldSelector
:
unversioned
.
FieldSelector
{
fields
.
Everything
()},
}
replicaSets
,
err
:=
client
.
ReplicationControllers
(
api
.
NamespaceAll
)
.
List
(
listEverything
)
if
err
!=
nil
{
return
nil
,
err
}
services
,
err
:=
client
.
Services
(
api
.
NamespaceAll
)
.
List
(
unversioned
.
ListOptions
{
LabelSelector
:
unversioned
.
LabelSelector
{
labels
.
Everything
()},
FieldSelector
:
unversioned
.
FieldSelector
{
fields
.
Everything
()},
})
services
,
err
:=
client
.
Services
(
api
.
NamespaceAll
)
.
List
(
listEverything
)
if
err
!=
nil
{
return
nil
,
err
}
pods
,
err
:=
client
.
Pods
(
api
.
NamespaceAll
)
.
List
(
listEverything
)
if
err
!=
nil
{
return
nil
,
err
}
return
getReplicaSetList
(
replicaSets
.
Items
,
services
.
Items
),
nil
return
getReplicaSetList
(
replicaSets
.
Items
,
services
.
Items
,
pods
.
Items
),
nil
}
// Returns a list of all Replica Set model objects in the cluster, based on all Kubernetes
// Replica Set and Service API objects.
// The function processes all Replica Sets API objects and finds matching Services for them.
func
getReplicaSetList
(
replicaSets
[]
api
.
ReplicationController
,
services
[]
api
.
Service
)
*
ReplicaSetList
{
func
getReplicaSetList
(
replicaSets
[]
api
.
ReplicationController
,
services
[]
api
.
Service
,
pods
[]
api
.
Pod
)
*
ReplicaSetList
{
replicaSetList
:=
&
ReplicaSetList
{
ReplicaSets
:
make
([]
ReplicaSet
,
0
)}
...
...
@@ -111,19 +129,20 @@ func getReplicaSetList(
for
_
,
service
:=
range
matchingServices
{
internalEndpoints
=
append
(
internalEndpoints
,
getInternalEndpoint
(
service
.
Name
,
service
.
Namespace
,
service
.
Spec
.
Ports
))
for
_
,
externalI
p
:=
range
service
.
Status
.
LoadBalancer
.
Ingress
{
for
_
,
externalI
P
:=
range
service
.
Status
.
LoadBalancer
.
Ingress
{
externalEndpoints
=
append
(
externalEndpoints
,
getExternalEndpoint
(
externalI
p
,
service
.
Spec
.
Ports
))
getExternalEndpoint
(
externalI
P
,
service
.
Spec
.
Ports
))
}
}
podInfo
:=
getReplicaSetPodInfo
(
&
replicaSet
,
pods
)
replicaSetList
.
ReplicaSets
=
append
(
replicaSetList
.
ReplicaSets
,
ReplicaSet
{
Name
:
replicaSet
.
ObjectMeta
.
Name
,
Namespace
:
replicaSet
.
ObjectMeta
.
Namespace
,
Description
:
replicaSet
.
Annotations
[
DescriptionAnnotationKey
],
Labels
:
replicaSet
.
ObjectMeta
.
Labels
,
PodsRunning
:
replicaSet
.
Status
.
Replicas
,
PodsPending
:
replicaSet
.
Spec
.
Replicas
-
replicaSet
.
Status
.
Replicas
,
Pods
:
podInfo
,
ContainerImages
:
containerImages
,
CreationTime
:
replicaSet
.
ObjectMeta
.
CreationTimestamp
,
InternalEndpoints
:
internalEndpoints
,
...
...
@@ -134,14 +153,38 @@ func getReplicaSetList(
return
replicaSetList
}
func
getReplicaSetPodInfo
(
replicaSet
*
api
.
ReplicationController
,
pods
[]
api
.
Pod
)
ReplicaSetPodInfo
{
result
:=
ReplicaSetPodInfo
{
Curret
:
replicaSet
.
Status
.
Replicas
,
Desired
:
replicaSet
.
Spec
.
Replicas
,
}
for
_
,
pod
:=
range
pods
{
if
pod
.
ObjectMeta
.
Namespace
==
replicaSet
.
ObjectMeta
.
Namespace
&&
isLabelSelectorMatching
(
replicaSet
.
Spec
.
Selector
,
pod
.
ObjectMeta
.
Labels
)
{
switch
pod
.
Status
.
Phase
{
case
api
.
PodRunning
:
result
.
Running
++
case
api
.
PodPending
:
result
.
Waiting
++
case
api
.
PodFailed
:
result
.
Failed
++
}
}
}
return
result
}
// Returns all services that target the same Pods (or subset) as the given Replica Set.
func
getMatchingServices
(
services
[]
api
.
Service
,
replicaSet
*
api
.
ReplicationController
)
[]
api
.
Service
{
// TODO(bryk): Match namespace too.
var
matchingServices
[]
api
.
Service
for
_
,
service
:=
range
services
{
if
isServiceMatchingReplicaSet
(
service
.
Spec
.
Selector
,
replicaSet
.
Spec
.
Selector
)
{
if
service
.
ObjectMeta
.
Namespace
==
replicaSet
.
ObjectMeta
.
Namespace
&&
isLabelSelectorMatching
(
service
.
Spec
.
Selector
,
replicaSet
.
Spec
.
Selector
)
{
matchingServices
=
append
(
matchingServices
,
service
)
}
}
...
...
@@ -150,15 +193,15 @@ func getMatchingServices(services []api.Service,
// Returns true when a Service with the given selector targets the same Pods (or subset) that
// a Replica Set with the given selector.
func
is
ServiceMatchingReplicaSet
(
service
Selector
map
[
string
]
string
,
replicaSetSpecSelector
map
[
string
]
string
)
bool
{
func
is
LabelSelectorMatching
(
label
Selector
map
[
string
]
string
,
testedObjectLabels
map
[
string
]
string
)
bool
{
// If service has no selectors, then assume it targets different Pods.
if
len
(
service
Selector
)
==
0
{
if
len
(
label
Selector
)
==
0
{
return
false
}
for
label
,
value
:=
range
service
Selector
{
if
rsValue
,
ok
:=
replicaSetSpecSelector
[
label
];
!
ok
||
rsValue
!=
value
{
for
label
,
value
:=
range
label
Selector
{
if
rsValue
,
ok
:=
testedObjectLabels
[
label
];
!
ok
||
rsValue
!=
value
{
return
false
}
}
...
...
src/app/backend/replicasetpods.go
浏览文件 @
d10182e4
...
...
@@ -81,7 +81,9 @@ func GetReplicaSetPods(client *client.Client, namespace, name string, limit int)
// Data is sorted by total number of restarts for replica set pod.
// Result set can be limited
func
getReplicaSetPods
(
pods
[]
api
.
Pod
,
limit
int
)
*
ReplicaSetPods
{
replicaSetPods
:=
&
ReplicaSetPods
{}
replicaSetPods
:=
&
ReplicaSetPods
{
Pods
:
make
([]
ReplicaSetPodWithContainers
,
0
),
}
for
_
,
pod
:=
range
pods
{
totalRestartCount
:=
0
replicaSetPodWithContainers
:=
ReplicaSetPodWithContainers
{
...
...
src/app/externs/backendapi.js
浏览文件 @
d10182e4
...
...
@@ -96,8 +96,7 @@ backendApi.ReplicaSetList;
* namespace: string,
* description: string,
* labels: !Object<string, string>,
* podsRunning: number,
* podsPending: number,
* pods: {current: number, running: number, desired: number, waiting: number, failed: number},
* containerImages: !Array<string>,
* creationTime: string,
* internalEndpoints: !Array<!backendApi.Endpoint>,
...
...
@@ -200,7 +199,8 @@ backendApi.ReplicaSetPods;
* @typedef {{
* podId: string,
* sinceTime: string,
* logs: !Array<string>
* logs: !Array<string>,
* container: string
* }}
*/
backendApi
.
Logs
;
...
...
src/app/frontend/chrome/chrome.scss
浏览文件 @
d10182e4
...
...
@@ -30,7 +30,12 @@ body {
}
a
{
color
:
$primary
;
text-decoration
:
inherit
;
&
:visited
{
color
:
$primary
;
}
}
.kd-toolbar-tools
,
...
...
@@ -53,3 +58,10 @@ a {
right
:
0
;
top
:
0
;
}
.kd-text-icon
{
font-size
:
inherit
;
height
:
inherit
;
vertical-align
:
middle
;
}
src/app/frontend/logs/logs_controller.js
浏览文件 @
d10182e4
...
...
@@ -29,16 +29,16 @@ export class LogsController {
/** @private {!./logs_service.LogColorInversionService} */
this
.
logsColorInversionService_
=
logsColorInversionService
;
/**
* Indicates color state of log area.
* If false: black text is placed on white area. Otherwise colors are inverted.
* @export
* @return {boolean}
*/
this
.
isTextColorInverted
=
function
()
{
return
this
.
logsColorInversionService_
.
getInverted
();
};
}
/**
* Indicates state of log area color.
* If false: black text is placed on white area. Otherwise colors are inverted.
* @export
* @return {boolean}
*/
isTextColorInverted
()
{
return
this
.
logsColorInversionService_
.
getInverted
();
}
/**
* Return proper style class for logs content.
* @export
...
...
src/app/frontend/logs/logs_state.js
浏览文件 @
d10182e4
...
...
@@ -26,7 +26,7 @@ export class StateParams {
* @param {string} namespace
* @param {string} replicaSet
* @param {string} podId
* @param {string
} container
* @param {string
=} [container]
*/
constructor
(
namespace
,
replicaSet
,
podId
,
container
)
{
/** @export {string} Namespace of this Replica Set. */
...
...
@@ -38,7 +38,7 @@ export class StateParams {
/** @export {string} Id of this Pod. */
this
.
podId
=
podId
;
/** @export {string} Name of this pod container. */
/** @export {string
|undefined
} Name of this pod container. */
this
.
container
=
container
;
}
}
src/app/frontend/logs/logs_stateconfig.js
浏览文件 @
d10182e4
...
...
@@ -38,7 +38,7 @@ export default function stateConfig($stateProvider) {
};
$stateProvider
.
state
(
stateName
,
{
url
:
'
/logs/:namespace/:replicaSet/:podId/:container
'
,
url
:
'
/logs/:namespace/:replicaSet/:podId/:container
?
'
,
resolve
:
{
'
replicaSetPods
'
:
resolveReplicaSetPods
,
'
podLogs
'
:
resolvePodLogs
,
...
...
@@ -55,7 +55,8 @@ export default function stateConfig($stateProvider) {
*/
function
resolveReplicaSetPods
(
$stateParams
,
$resource
)
{
/** @type {!angular.Resource<!backendApi.ReplicaSetPods>} */
let
resource
=
$resource
(
'
/api/replicasets/pods/:namespace/:replicaSet
'
,
$stateParams
);
let
resource
=
$resource
(
`/api/replicasets/pods/
${
$stateParams
.
namespace
}
/
${
$stateParams
.
replicaSet
}
`
);
return
resource
.
get
().
$promise
;
}
...
...
@@ -68,7 +69,7 @@ function resolveReplicaSetPods($stateParams, $resource) {
*/
function
resolvePodLogs
(
$stateParams
,
$resource
)
{
/** @type {!angular.Resource<!backendApi.Logs>} */
let
resource
=
$resource
(
'
/api/logs/:namespace/:podId/:container
'
,
$stateParams
);
let
resource
=
$resource
(
`/api/logs/
${
$stateParams
.
namespace
}
/
${
$stateParams
.
podId
}
/
${
$stateParams
.
container
}
`
);
return
resource
.
get
().
$promise
;
}
src/app/frontend/logs/logstoolbar/logstoolbar_controller.js
浏览文件 @
d10182e4
...
...
@@ -23,36 +23,34 @@ export default class LogsToolbarController {
* @param {!ui.router.$state} $state
* @param {!StateParams} $stateParams
* @param {!backendApi.ReplicaSetPods} replicaSetPods
* @param {!backendApi.Logs} podLogs
* @param {!../logs_service.LogColorInversionService} logsColorInversionService
* @ngInject
*/
constructor
(
$state
,
$stateParams
,
replicaSetPods
,
logsColorInversionService
)
{
constructor
(
$state
,
$stateParams
,
replicaSetPods
,
podLogs
,
logsColorInversionService
)
{
/** @private {!ui.router.$state} */
this
.
state_
=
$state
;
/** @private {!StateParams} */
this
.
params
=
$stateParams
;
/**
* Service to notify logs controller if any changes on toolbar.
* @private {!../logs_service.LogColorInversionService}
*/
this
.
logsColorInversionService
=
logsColorInversionService
;
this
.
logsColorInversionService
_
=
logsColorInversionService
;
/** @export {!Array<!backendApi.ReplicaSetPodWithContainers>} */
this
.
pods
=
replicaSetPods
.
pods
||
[]
;
this
.
pods
=
replicaSetPods
.
pods
;
/**
* Currently chosen pod.
* @export {!backendApi.ReplicaSetPodWithContainers|undefined}
*/
this
.
pod
=
this
.
findPodByName_
(
this
.
pods
,
this
.
p
arams
.
podId
);
this
.
pod
=
this
.
findPodByName_
(
this
.
pods
,
$stateP
arams
.
podId
);
/** @export {!Array<!backendApi.PodContainer>} */
this
.
containers
=
this
.
pod
.
podContainers
||
[]
;
this
.
containers
=
this
.
pod
.
podContainers
;
/** @export {!backendApi.PodContainer
|undefined
} */
this
.
container
=
this
.
findContainerByName_
(
this
.
containers
,
this
.
param
s
.
container
);
/** @export {!backendApi.PodContainer} */
this
.
container
=
this
.
initializeContainer_
(
this
.
containers
,
podLog
s
.
container
);
/**
* Pod creation time.
...
...
@@ -64,23 +62,23 @@ export default class LogsToolbarController {
* Namespace.
* @private {string}
*/
this
.
namespace
=
this
.
p
arams
.
namespace
;
this
.
namespace
_
=
$stateP
arams
.
namespace
;
/**
* Replica Set name.
* @private {string}
*/
this
.
replicaSetName
=
this
.
params
.
replicaSet
;
/**
* Indicates state of log area color.
* If false: black text is placed on white area. Otherwise colors are inverted.
* @export
* @return {boolean}
*/
this
.
isTextColorInverted
=
function
()
{
return
this
.
logsColorInversionService
.
getInverted
();
};
this
.
replicaSetName_
=
$stateParams
.
replicaSet
;
}
/**
* Indicates state of log area color.
* If false: black text is placed on white area. Otherwise colors are inverted.
* @export
* @return {boolean}
*/
isTextColorInverted
()
{
return
this
.
logsColorInversionService_
.
getInverted
();
}
/**
* Execute a code when a user changes the selected option of a pod element.
* @param {string} podId
...
...
@@ -89,7 +87,7 @@ export default class LogsToolbarController {
*/
onPodChange
(
podId
)
{
return
this
.
state_
.
transitionTo
(
logs
,
new
StateParams
(
this
.
namespace
,
this
.
replicaSetName
,
podId
,
this
.
container
.
name
));
logs
,
new
StateParams
(
this
.
namespace
_
,
this
.
replicaSetName_
,
podId
,
this
.
container
.
name
));
}
/**
...
...
@@ -100,7 +98,7 @@ export default class LogsToolbarController {
*/
onContainerChange
(
container
)
{
return
this
.
state_
.
transitionTo
(
logs
,
new
StateParams
(
this
.
namespace
,
this
.
replicaSetName
,
this
.
pod
.
name
,
container
));
logs
,
new
StateParams
(
this
.
namespace
_
,
this
.
replicaSetName_
,
this
.
pod
.
name
,
container
));
}
/**
...
...
@@ -120,7 +118,7 @@ export default class LogsToolbarController {
* Execute a code when a user changes the selected option for console color.
* @export
*/
onTextColorChange
()
{
this
.
logsColorInversionService
.
invert
();
}
onTextColorChange
()
{
this
.
logsColorInversionService
_
.
invert
();
}
/**
* Find Pod by name.
...
...
@@ -136,9 +134,15 @@ export default class LogsToolbarController {
* Find Container by name.
* Return object or undefined if can not find a object.
* @param {!Array<!backendApi.PodContainer>} array
* @param {
!
string} name
* @return {!backendApi.PodContainer
|undefined
}
* @param {string} name
* @return {!backendApi.PodContainer}
* @private
*/
findContainerByName_
(
array
,
name
)
{
return
array
.
find
((
element
)
=>
element
.
name
===
name
);
}
initializeContainer_
(
array
,
name
)
{
let
container
=
array
.
find
((
element
)
=>
element
.
name
===
name
);
if
(
!
container
)
{
container
=
array
[
0
];
}
return
container
;
}
}
src/app/frontend/replicasetdetail/replicasetdetail.html
浏览文件 @
d10182e4
...
...
@@ -157,7 +157,7 @@ limitations under the License.
</th>
<th
class=
"kd-replicasetdetail-table-header"
>
<span>
Logs
<i
class=
"material-icons kd-
replicasetdetail-help
-icon"
>
<i
class=
"material-icons kd-
text
-icon"
>
help
<md-tooltip>
Display logs from the pod
</md-tooltip>
</i>
...
...
@@ -208,9 +208,11 @@ limitations under the License.
</td>
<td
class=
"kd-replicasetdetail-table-cell"
>
<span>
Logs
<i
class=
"material-icons kd-replicasetdetail-table-icon"
>
arrow_drop_down
</i>
<a
ng-href=
"{{::ctrl.getPodLogsHref(pod)}}"
class=
"md-primary"
>
Logs
<i
class=
"material-icons kd-text-icon"
>
open_in_new
</i>
</a>
</span>
<!-- TODO(maciaszczykm): Handle it. -->
</td>
<td
class=
"kd-replicasetdetail-table-cell"
>
<md-button
class=
"md-icon-button"
>
...
...
src/app/frontend/replicasetdetail/replicasetdetail.scss
浏览文件 @
d10182e4
...
...
@@ -119,7 +119,4 @@ $table-cell-height-half: $table-cell-height / 2;
.kd-replicasetdetail-help-icon
{
color
:
$foreground-2
;
cursor
:
default
;
font-size
:
inherit
;
height
:
inherit
;
vertical-align
:
text-top
;
}
src/app/frontend/replicasetdetail/replicasetdetail_controller.js
浏览文件 @
d10182e4
...
...
@@ -15,6 +15,8 @@
import
showUpdateReplicasDialog
from
'
replicasetdetail/updatereplicas_dialog
'
;
import
{
UPWARDS
,
DOWNWARDS
}
from
'
replicasetdetail/sortedheader_controller
'
;
import
{
stateName
as
replicasets
}
from
'
replicasetlist/replicasetlist_state
'
;
import
{
stateName
as
logsStateName
}
from
'
logs/logs_state
'
;
import
{
StateParams
as
LogsStateParams
}
from
'
logs/logs_state
'
;
// Filter type and source values for events.
const
EVENT_ALL
=
'
All
'
;
...
...
@@ -131,6 +133,15 @@ export default class ReplicaSetDetailController {
this
.
events
=
this
.
filterBySource
(
this
.
events
,
this
.
eventSource
);
}
/**
* @export
*/
getPodLogsHref
(
pod
)
{
return
this
.
state_
.
href
(
logsStateName
,
new
LogsStateParams
(
this
.
stateParams_
.
namespace
,
this
.
stateParams_
.
replicaSet
,
pod
.
name
));
}
/**
* Filters events by their type.
* @param {!Array<!backendApi.Event>} events
...
...
src/app/frontend/replicasetdetail/replicasetdetail_module.js
浏览文件 @
d10182e4
...
...
@@ -14,6 +14,7 @@
import
componentsModule
from
'
./../common/components/components_module
'
;
import
filtersModule
from
'
common/filters/filters_module
'
;
import
logsModule
from
'
logs/logs_module
'
;
import
serviceEndpointDirective
from
'
./serviceendpoint_directive
'
;
import
stateConfig
from
'
./replicasetdetail_stateconfig
'
;
import
sortedHeaderDirective
from
'
./sortedheader_directive
'
;
...
...
@@ -30,8 +31,9 @@ export default angular.module(
'
ngMaterial
'
,
'
ngResource
'
,
'
ui.router
'
,
filtersModule
.
name
,
componentsModule
.
name
,
filtersModule
.
name
,
logsModule
.
name
,
])
.
config
(
stateConfig
)
.
directive
(
'
kdServiceEndpoint
'
,
serviceEndpointDirective
)
...
...
src/app/frontend/replicasetdetail/sortedheader.html
浏览文件 @
d10182e4
...
...
@@ -16,17 +16,17 @@ limitations under the License.
<button
class=
"kd-replicaset-detail-table-header-button"
ng-click=
"sortCtrl.changeSorting()"
>
<md-icon
md-font-library=
"material-icons"
ng-show=
"sortCtrl.isArrowDown()"
class=
"kd-
sortedheader-sor
t-icon"
>
class=
"kd-
tex
t-icon"
>
arrow_downward
</md-icon>
<md-icon
md-font-library=
"material-icons"
ng-show=
"sortCtrl.isArrowUp()"
class=
"kd-
sortedheader-sor
t-icon"
>
class=
"kd-
tex
t-icon"
>
arrow_upward
</md-icon>
<ng-transclude></ng-transclude>
</button>
<md-icon
ng-show=
"sortCtrl.isTooltipAvailable()"
md-font-library=
"material-icons"
class=
"kd-replicasetdetail-help-icon"
>
class=
"kd-replicasetdetail-help-icon
kd-text-icon
"
>
help
<md-tooltip>
{{sortCtrl.tooltip}}
</md-tooltip>
</md-icon>
src/app/frontend/replicasetdetail/sortedheader.scss
浏览文件 @
d10182e4
...
...
@@ -24,10 +24,3 @@
outline
:
none
;
}
}
.kd-sortedheader-sort-icon
{
font-size
:
inherit
;
height
:
inherit
;
vertical-align
:
text-top
;
width
:
inherit
;
}
src/app/frontend/replicasetlist/logsmenu.html
浏览文件 @
d10182e4
...
...
@@ -30,7 +30,7 @@ limitations under the License.
{{::(pod.name | middleEllipsis:10)}}
</div>
<div
class=
"kd-menu-logs-item kd-menu-logs-item-since"
>
<a
ng-href=
"{{::ctrl.getLogsHref(pod.name
, pod.podContainers[0].name
)}}"
<a
ng-href=
"{{::ctrl.getLogsHref(pod.name)}}"
ng-if=
"::ctrl.podContainerExists(pod)"
>
<span
ng-if=
"::pod.startTime"
>
{{pod.startTime | date:"short"}}
...
...
@@ -38,13 +38,13 @@ limitations under the License.
<span
ng-if=
"::!pod.startTime"
>
Not running
</span>
<i
class=
"material-icons kd-
menu-logs-link
-icon"
>
open_in_new
</i>
<i
class=
"material-icons kd-
text
-icon"
>
open_in_new
</i>
</a>
<span
ng-if=
"::!ctrl.podContainerExists(pod)"
>
-
</span>
</div>
<div
class=
"kd-menu-logs-item kd-menu-logs-item-prior"
>
<a
ng-if=
"::ctrl.podContainersRestarted(pod)"
>
Logs
<i
class=
"material-icons kd-menu-logs-link
-icon"
>
open_in_new
</i>
Logs
<i
class=
"material-icons kd-text
-icon"
>
open_in_new
</i>
</a>
<span
ng-if=
"::!ctrl.podContainersRestarted(pod)"
>
-
</span>
</div>
...
...
src/app/frontend/replicasetlist/logsmenu_controller.js
浏览文件 @
d10182e4
...
...
@@ -90,14 +90,12 @@ export default class LogsMenuController {
/**
* @param {string} podName
* @param {string} containerName
* @return {string}
* @export
*/
getLogsHref
(
podName
,
containerName
)
{
getLogsHref
(
podName
)
{
return
this
.
state_
.
href
(
logsStateName
,
new
StateParams
(
this
.
namespace
,
this
.
replicaSetName
,
podName
,
containerName
));
logsStateName
,
new
StateParams
(
this
.
namespace
,
this
.
replicaSetName
,
podName
));
}
/**
...
...
src/app/frontend/replicasetlist/replicasetcard.html
浏览文件 @
d10182e4
...
...
@@ -24,7 +24,6 @@ limitations under the License.
{{::ctrl.replicaSet.name}}
</a>
</h3>
<kd-replica-set-card-menu
replica-set=
"::ctrl.replicaSet"
></kd-replica-set-card-menu>
</div>
<div
flex
class=
"md-caption"
>
...
...
@@ -34,7 +33,19 @@ limitations under the License.
<div
class=
"md-caption"
>
<div
layout=
"row"
layout-align=
"center end"
>
<span
flex=
"60"
>
{{::ctrl.replicaSet.podsRunning}} pods running, {{::ctrl.replicaSet.podsPending}} pending
<ng-pluralize
class=
"kd-replicase-card-pods-stat"
count=
"::ctrl.replicaSet.pods.running"
when=
"{'one': '1 pod running,',
'other': '{} pods running,'}"
>
</ng-pluralize>
<span
ng-if=
"::ctrl.replicaSet.pods.waiting"
class=
"kd-replicase-card-pods-stat"
>
{{::ctrl.replicaSet.pods.waiting}} waiting,
</span>
<span
ng-if=
"::ctrl.replicaSet.pods.failed"
class=
"kd-replicase-card-pods-stat"
>
{{::ctrl.replicaSet.pods.failed}} failed,
</span>
<span
class=
"kd-replicase-card-pods-stat"
>
{{::ctrl.replicaSet.pods.desired}} desired
</span>
</span>
<logs-menu
flex=
"40"
namespace=
"::ctrl.replicaSet.namespace"
replica-set-name=
"::ctrl.replicaSet.name"
>
...
...
src/app/frontend/replicasetlist/replicasetcard.scss
浏览文件 @
d10182e4
...
...
@@ -16,7 +16,7 @@
.kd-replicaset-card
{
margin
:
$baseline-grid
;
width
:
(
$layout-breakpoint-lg
-
(
2
*
$baseline-grid
)
*
2
)
/
3
;
width
:
(
$layout-breakpoint-lg
-
(
2
*
$baseline-grid
)
*
2
)
/
3
;
}
.kd-replicaset-card-name
{
...
...
@@ -24,6 +24,10 @@
display
:
inline-block
;
font-weight
:
$regular-font-weight
;
text-decoration
:
none
;
&
:visited
{
color
:
inherit
;
}
}
.kd-replicaset-card-title
{
...
...
@@ -78,6 +82,10 @@
margin-right
:
2
*
$baseline-grid
;
}
.kd-replicase-card-pods-stat
{
white-space
:
nowrap
;
}
.kd-menu-logs-item-header
{
box-sizing
:
inherit
;
color
:
$foreground-2
;
...
...
@@ -102,8 +110,3 @@
.kd-menu-logs-item-since
{
width
:
15
*
$baseline-grid
;
}
.kd-menu-logs-link-icon
{
font-size
:
$subhead-font-size-base
;
margin-left
:
$baseline-grid
;
}
src/test/backend/replicasetlist_test.go
浏览文件 @
d10182e4
...
...
@@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/api"
)
func
TestIs
ServiceMatchingReplicaSet
(
t
*
testing
.
T
)
{
func
TestIs
LabelSelectorMatching
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
serviceSelector
,
replicaSetSelector
map
[
string
]
string
expected
bool
...
...
@@ -42,9 +42,9 @@ func TestIsServiceMatchingReplicaSet(t *testing.T) {
map
[
string
]
string
{
"app"
:
"my-name"
,
"version"
:
"1.1"
},
true
},
}
for
_
,
c
:=
range
cases
{
actual
:=
is
ServiceMatchingReplicaSet
(
c
.
serviceSelector
,
c
.
replicaSetSelector
)
actual
:=
is
LabelSelectorMatching
(
c
.
serviceSelector
,
c
.
replicaSetSelector
)
if
actual
!=
c
.
expected
{
t
.
Errorf
(
"is
ServiceMatchingReplicaSet
(%+v, %+v) == %+v, expected %+v"
,
t
.
Errorf
(
"is
LabelSelectorMatching
(%+v, %+v) == %+v, expected %+v"
,
c
.
serviceSelector
,
c
.
replicaSetSelector
,
actual
,
c
.
expected
)
}
}
...
...
@@ -86,12 +86,17 @@ func TestGetReplicaSetList(t *testing.T) {
cases
:=
[]
struct
{
replicaSets
[]
api
.
ReplicationController
services
[]
api
.
Service
pods
[]
api
.
Pod
expected
*
ReplicaSetList
}{
{
nil
,
nil
,
&
ReplicaSetList
{
ReplicaSets
:
[]
ReplicaSet
{}}},
{
nil
,
nil
,
nil
,
&
ReplicaSetList
{
ReplicaSets
:
[]
ReplicaSet
{}}},
{
[]
api
.
ReplicationController
{
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"my-app-1"
,
Namespace
:
"namespace-1"
,
},
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
Template
:
&
api
.
PodTemplateSpec
{
...
...
@@ -100,6 +105,10 @@ func TestGetReplicaSetList(t *testing.T) {
},
},
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"my-app-2"
,
Namespace
:
"namespace-2"
,
},
Spec
:
api
.
ReplicationControllerSpec
{
Selector
:
map
[
string
]
string
{
"app"
:
"my-name-2"
,
"ver"
:
"2"
},
Template
:
&
api
.
PodTemplateSpec
{
...
...
@@ -124,23 +133,98 @@ func TestGetReplicaSetList(t *testing.T) {
},
},
},
[]
api
.
Pod
{
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodFailed
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodFailed
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodPending
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-2"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodPending
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodRunning
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodSucceeded
,
},
},
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"namespace-1"
,
Labels
:
map
[
string
]
string
{
"app"
:
"my-name-1"
},
},
Status
:
api
.
PodStatus
{
Phase
:
api
.
PodUnknown
,
},
},
},
&
ReplicaSetList
{
ReplicaSets
:
[]
ReplicaSet
{
{
Name
:
"my-app-1"
,
Namespace
:
"namespace-1"
,
ContainerImages
:
[]
string
{
"my-container-image-1"
},
InternalEndpoints
:
[]
Endpoint
{{
Host
:
"my-app-1.namespace-1"
}},
Pods
:
ReplicaSetPodInfo
{
Failed
:
2
,
Waiting
:
1
,
Running
:
1
,
},
},
{
Name
:
"my-app-2"
,
Namespace
:
"namespace-2"
,
ContainerImages
:
[]
string
{
"my-container-image-2"
},
InternalEndpoints
:
[]
Endpoint
{{
Host
:
"my-app-2.namespace-2"
}},
Pods
:
ReplicaSetPodInfo
{},
},
},
},
},
}
for
_
,
c
:=
range
cases
{
actual
:=
getReplicaSetList
(
c
.
replicaSets
,
c
.
services
)
actual
:=
getReplicaSetList
(
c
.
replicaSets
,
c
.
services
,
c
.
pods
)
if
!
reflect
.
DeepEqual
(
actual
,
c
.
expected
)
{
t
.
Errorf
(
"getReplicaSetList(%#v, %#v) ==
%#v, expected %#v
"
,
t
.
Errorf
(
"getReplicaSetList(%#v, %#v) ==
\n
%#v
\n
expected
\n
%#v
\n
"
,
c
.
replicaSets
,
c
.
services
,
actual
,
c
.
expected
)
}
}
...
...
src/test/backend/replicasetpods_test.go
浏览文件 @
d10182e4
...
...
@@ -72,7 +72,7 @@ func TestGetReplicaSetPods(t *testing.T) {
limit
int
expected
*
ReplicaSetPods
}{
{
nil
,
0
,
&
ReplicaSetPods
{}},
{
nil
,
0
,
&
ReplicaSetPods
{
Pods
:
[]
ReplicaSetPodWithContainers
{}
}},
{
pods
,
10
,
&
ReplicaSetPods
{
Pods
:
[]
ReplicaSetPodWithContainers
{
{
Name
:
"pod-2"
,
...
...
src/test/frontend/logs/logstoolbar/logstoolbar_controller_test.js
浏览文件 @
d10182e4
...
...
@@ -48,6 +48,11 @@ describe('Logs toolbar controller', () => {
],
};
/** @type {!backendApi.Logs} podLogs */
const
logs
=
{
container
:
mockContainer
,
};
/** @type {!StateParams} */
const
stateParams
=
new
StateParams
(
mockNamespace
,
mockReplicaSet
,
mockPodId
,
mockContainer
);
...
...
@@ -66,8 +71,8 @@ describe('Logs toolbar controller', () => {
angular
.
mock
.
inject
((
$controller
,
$state
)
=>
{
state
=
$state
;
ctrl
=
$controller
(
LogsToolbarController
,
{
replicaSetPods
:
replicaSetPods
,
$stateParams
:
stateParams
},
$state
);
LogsToolbarController
,
{
replicaSetPods
:
replicaSetPods
,
$stateParams
:
stateParams
,
podLogs
:
logs
},
$state
);
});
});
...
...
src/test/frontend/replicasetdetail/replicasetdetail_controller_test.js
浏览文件 @
d10182e4
...
...
@@ -28,9 +28,15 @@ describe('Replica Set Detail controller', () => {
beforeEach
(()
=>
{
angular
.
mock
.
module
(
replicaSetDetailModule
.
name
);
angular
.
mock
.
inject
((
$
resource
,
$log
,
$state
,
$mdDialog
)
=>
{
angular
.
mock
.
inject
((
$
controller
,
$mdDialog
,
$resource
)
=>
{
mdDialog
=
$mdDialog
;
ctrl
=
new
ReplicaSetDetailController
(
mdDialog
,
$state
,
$resource
,
$log
,
[],
[],
[]);
ctrl
=
$controller
(
ReplicaSetDetailController
,
{
replicaSetDetail
:
{},
replicaSetEvents
:
{},
replicaSetDetailResource
:
$resource
(
'
/foo
'
),
replicaSetSpecPodsResource
:
$resource
(
'
/bar
'
),
$stateParams
:
{
replicaSet
:
'
foo-replicaset
'
,
namespace
:
'
foo-namespace
'
},
});
});
});
...
...
@@ -93,4 +99,9 @@ describe('Replica Set Detail controller', () => {
// then
expect
(
mdDialog
.
show
).
toHaveBeenCalled
();
});
it
(
'
should create logs href
'
,
()
=>
{
expect
(
ctrl
.
getPodLogsHref
({
name
:
'
foo-pod
'
}))
.
toBe
(
'
#/logs/foo-namespace/foo-replicaset/foo-pod/
'
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录