提交 e315f237 编写于 作者: P Piotr Bryk

Merge branch 'master' into http-path-prefix

......@@ -15,20 +15,70 @@
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
restful "github.com/emicklei/go-restful"
client "k8s.io/kubernetes/pkg/client/unversioned"
)
const (
Colon = ":"
RequestLogString = "Incoming %s %s %s request from %s:\n%v"
ResponseLogString = "Outcoming response to %s with %d status code"
)
// Web-service filter function used for request and response logging.
func wsLogger(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
remoteAddr := GetRemoteAddr(req)
log.Printf(FormatRequestLog(req, remoteAddr))
chain.ProcessFilter(req, resp)
log.Printf(FormatResponseLog(resp, remoteAddr))
}
// Returns remote address of the request (without port number).
func GetRemoteAddr(req *restful.Request) string {
if strings.Contains(req.Request.RemoteAddr, Colon) {
return strings.Split(req.Request.RemoteAddr, Colon)[0]
} else {
return req.Request.RemoteAddr
}
}
// Formats request log string.
func FormatRequestLog(req *restful.Request, remoteAddr string) string {
reqBody := make([]byte, req.Request.ContentLength)
if req.Request.Body != nil {
req.Request.Body.Read(reqBody)
}
reqURI := ""
if req.Request.URL != nil {
reqURI = req.Request.URL.RequestURI()
}
return fmt.Sprintf(RequestLogString, req.Request.Proto, req.Request.Method,
reqURI, remoteAddr, reqBody)
}
// Formats response log string.
// TODO(maciaszczykm): Display response content too.
func FormatResponseLog(resp *restful.Response, remoteAddr string) string {
return fmt.Sprintf(ResponseLogString, remoteAddr, resp.StatusCode())
}
// Creates a new HTTP handler that handles all requests to the API of the backend.
func CreateHttpApiHandler(client *client.Client) http.Handler {
apiHandler := ApiHandler{client}
wsContainer := restful.NewContainer()
deployWs := new(restful.WebService)
deployWs.Filter(wsLogger)
deployWs.Path("/api/appdeployments").
Consumes(restful.MIME_JSON).
Produces(restful.MIME_JSON)
......@@ -45,6 +95,7 @@ func CreateHttpApiHandler(client *client.Client) http.Handler {
wsContainer.Add(deployWs)
replicaSetWs := new(restful.WebService)
replicaSetWs.Filter(wsLogger)
replicaSetWs.Path("/api/replicasets").
Consumes(restful.MIME_JSON).
Produces(restful.MIME_JSON)
......@@ -70,6 +121,7 @@ func CreateHttpApiHandler(client *client.Client) http.Handler {
wsContainer.Add(replicaSetWs)
namespacesWs := new(restful.WebService)
namespacesWs.Filter(wsLogger)
namespacesWs.Path("/api/namespaces").
Consumes(restful.MIME_JSON).
Produces(restful.MIME_JSON)
......@@ -85,6 +137,7 @@ func CreateHttpApiHandler(client *client.Client) http.Handler {
wsContainer.Add(namespacesWs)
logsWs := new(restful.WebService)
logsWs.Filter(wsLogger)
logsWs.Path("/api/logs").
Produces(restful.MIME_JSON)
logsWs.Route(
......@@ -98,6 +151,7 @@ func CreateHttpApiHandler(client *client.Client) http.Handler {
wsContainer.Add(logsWs)
eventsWs := new(restful.WebService)
eventsWs.Filter(wsLogger)
eventsWs.Path("/api/events").
Produces(restful.MIME_JSON)
eventsWs.Route(
......
......@@ -27,6 +27,24 @@ type ReplicaSetWithPods struct {
Pods *api.PodList
}
// ReplicaSetPodInfo represents aggregate information about replica set pods.
type ReplicaSetPodInfo struct {
// Number of pods that are created.
Current 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.
Pending int `json:"pending"`
// Number of pods that are failed.
Failed int `json:"failed"`
}
// Returns structure containing ReplicaSet and Pods for the given replica set.
func getRawReplicaSetWithPods(client *client.Client, namespace, name string) (
*ReplicaSetWithPods, error) {
......@@ -61,3 +79,24 @@ func getRawReplicaSetPods(client *client.Client, namespace, name string) (*api.P
}
return replicaSetAndPods.Pods, nil
}
// Returns aggregate information about replica set pods.
func getReplicaSetPodInfo(replicaSet *api.ReplicationController, pods []api.Pod) ReplicaSetPodInfo {
result := ReplicaSetPodInfo{
Current: replicaSet.Status.Replicas,
Desired: replicaSet.Spec.Replicas,
}
for _, pod := range pods {
switch pod.Status.Phase {
case api.PodRunning:
result.Running++
case api.PodPending:
result.Pending++
case api.PodFailed:
result.Failed++
}
}
return result
}
......@@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/pkg/labels"
)
// Detailed information about a Replica Set.
// ReplicaSetDetail represents detailed information about a Replica Set.
type ReplicaSetDetail struct {
// Name of the Replica Set.
Name string `json:"name"`
......@@ -42,11 +42,8 @@ type ReplicaSetDetail struct {
// Container image list of the pod template specified by this Replica Set.
ContainerImages []string `json:"containerImages"`
// Number of Pod replicas specified in the spec.
PodsDesired int `json:"podsDesired"`
// Actual number of Pod replicas running.
PodsRunning int `json:"podsRunning"`
// Aggregate information about pods of this replica set.
PodInfo ReplicaSetPodInfo `json:"podInfo"`
// Detailed information about Pods belonging to this Replica Set.
Pods []ReplicaSetPod `json:"pods"`
......@@ -78,6 +75,9 @@ type ReplicaSetPod struct {
// Detailed information about a Service connected to Replica Set.
type ServiceDetail struct {
// Name of the service.
Name string `json:"name"`
// Internal endpoints of all Kubernetes services that have the same label selector as connected
// Replica Set.
// Endpoint is DNS name merged with ports.
......@@ -141,8 +141,7 @@ func GetReplicaSetDetail(client *client.Client, namespace, name string) (*Replic
Namespace: replicaSet.Namespace,
Labels: replicaSet.ObjectMeta.Labels,
LabelSelector: replicaSet.Spec.Selector,
PodsRunning: replicaSet.Status.Replicas,
PodsDesired: replicaSet.Spec.Replicas,
PodInfo: getReplicaSetPodInfo(replicaSet, pods.Items),
}
matchingServices := getMatchingServices(services.Items, replicaSet)
......@@ -229,6 +228,7 @@ func getServiceDetail(service api.Service) ServiceDetail {
}
serviceDetail := ServiceDetail{
Name: service.ObjectMeta.Name,
InternalEndpoint: getInternalEndpoint(service.Name, service.Namespace,
service.Spec.Ports),
ExternalEndpoints: externalEndpoints,
......
......@@ -61,24 +61,6 @@ type ReplicaSet struct {
ExternalEndpoints []Endpoint `json:"externalEndpoints"`
}
// 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")
......@@ -135,7 +117,14 @@ func getReplicaSetList(replicaSets []api.ReplicationController, services []api.S
}
}
podInfo := getReplicaSetPodInfo(&replicaSet, pods)
matchingPods := make([]api.Pod, 0)
for _, pod := range pods {
if pod.ObjectMeta.Namespace == replicaSet.ObjectMeta.Namespace &&
isLabelSelectorMatching(replicaSet.Spec.Selector, pod.ObjectMeta.Labels) {
matchingPods = append(matchingPods, pod)
}
}
podInfo := getReplicaSetPodInfo(&replicaSet, matchingPods)
replicaSetList.ReplicaSets = append(replicaSetList.ReplicaSets, ReplicaSet{
Name: replicaSet.ObjectMeta.Name,
......@@ -153,29 +142,6 @@ func getReplicaSetList(replicaSets []api.ReplicationController, services []api.S
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 {
......
......@@ -90,13 +90,24 @@ backendApi.Event;
*/
backendApi.ReplicaSetList;
/**
* @typedef {{
* current: number,
* desired: number,
* running: number,
* pending: number,
* failed: number
* }}
*/
backendApi.ReplicaSetPodInfo;
/**
* @typedef {{
* name: string,
* namespace: string,
* description: string,
* labels: !Object<string, string>,
* pods: {current: number, running: number, desired: number, waiting: number, failed: number},
* pods: !backendApi.ReplicaSetPodInfo,
* containerImages: !Array<string>,
* creationTime: string,
* internalEndpoints: !Array<!backendApi.Endpoint>,
......@@ -112,8 +123,7 @@ backendApi.ReplicaSet;
* labels: !Object<string, string>,
* labelSelector: !Object<string, string>,
* containerImages: !Array<string>,
* podsDesired: number,
* podsRunning: number,
* podInfo: !backendApi.ReplicaSetPodInfo,
* pods: !Array<!backendApi.ReplicaSetPod>,
* services: !Array<!backendApi.ServiceDetail>
* }}
......@@ -141,6 +151,7 @@ backendApi.ReplicaSetPod;
/**
* @typedef {{
* name: string,
* internalEndpoint: !backendApi.Endpoint,
* externalEndpoints: !Array<!backendApi.Endpoint>,
* selector: !Object<string, string>
......
......@@ -65,3 +65,14 @@ a {
vertical-align: middle;
}
.kd-comma-separated-item {
&:after {
content: ',';
}
&:last-child {
&:after {
content: '';
}
}
}
......@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<md-content class="kd-labels-content">
<div class="kd-labels" ng-repeat="(key, value) in ::labelsCtrl.labels">
{{key}}={{value}}
</div>
</md-content>
<div class="kd-labels" ng-repeat="(key, value) in ::labelsCtrl.labels">
{{key}}={{value}}
</div>
......@@ -15,8 +15,7 @@ limitations under the License.
-->
<div layout="row" flex layout-fill>
<md-content layout-padding flex layout-fill
ng-class=ctrl.getStyleClass()>
<md-content layout-padding flex layout-fill ng-class=ctrl.getStyleClass()>
<div ng-repeat="n in ctrl.logsSet" class="kd-logs-element">
<pre>{{n}}</pre>
</div>
......
......@@ -27,4 +27,5 @@ $logs-color-white: #fff;
.kd-logs-element {
padding: 0;
word-wrap: break-word;
}
......@@ -23,36 +23,64 @@ limitations under the License.
<md-icon md-font-library="material-icons">arrow_back</md-icon>
</md-button>
<h1 flex class="md-title kd-replicasetdetail-app-name">
{{ctrl.replicaSetDetail.name}}
{{::ctrl.replicaSetDetail.name}}
</h1>
</div>
</div>
<div flex layout="column" class="kd-replicasetdetail-sidebar-item">
<div layout="row" flex="nogrow" class="kd-replicasetdetail-sidebar-actions">
<span class="kd-replicasetdetail-sidebar-title kd-replicasetdetail-sidebar-info">
Replica set
</span>
<div layout="row" flex="nogrow">
<md-button class="md-primary" ng-click="ctrl.handleDeleteReplicaSetDialog()">
<md-icon class="material-icons">delete</md-icon>
DELETE
</md-button>
</div>
<div flex layout="column" class="kd-replicasetdetail-sidebar-info">
<div>
<span class="kd-replicasetdetail-sidebar-title">
{{ctrl.replicaSetDetail.podsDesired}} pods
</span>
<md-button class="md-icon-button md-primary">
<md-icon class="material-icons"
ng-click="ctrl.handleUpdateReplicasDialog()">
mode_edit
</md-icon>
</md-button>
<span class="kd-replicasetdetail-sidebar-line">Name</span>
<span class="kd-replicasetdetail-sidebar-subline">
{{::ctrl.replicaSetDetail.name}}
</span>
<span class="kd-replicasetdetail-sidebar-line">Namespace</span>
<span class="kd-replicasetdetail-sidebar-subline">
{{::ctrl.replicaSetDetail.namespace}}
</span>
<div layout="row" layout-align="start end">
<div flex="nogrow">
<span class="kd-replicasetdetail-sidebar-line">Pods</span>
<span class="kd-replicasetdetail-sidebar-subline">
{{::ctrl.replicaSetDetail.podInfo.current}} created,
{{::ctrl.replicaSetDetail.podInfo.desired}} desired
</span>
</div>
<div flex="nogrow">
<md-button class="md-icon-button md-primary">
<md-icon class="material-icons"
ng-click="ctrl.handleUpdateReplicasDialog()">
mode_edit
</md-icon>
</md-button>
</div>
</div>
<span class="kd-replicasetdetail-sidebar-line">Label selector</span>
<span class="kd-replicasetdetail-sidebar-line">Pods status</span>
<span class="kd-replicasetdetail-sidebar-subline">
<span ng-if="::ctrl.replicaSetDetail.podInfo.pending" class="kd-comma-separated-item">
{{::ctrl.replicaSetDetail.podInfo.pending}} pending<!-- Collapse whitespace
--></span>
<span ng-if="::ctrl.replicaSetDetail.podInfo.failed" class="kd-comma-separated-item">
{{::ctrl.replicaSetDetail.podInfo.failed}} failed<!-- Collapse whitespace
--></span>
<span ng-if="::ctrl.replicaSetDetail.podInfo.running" class="kd-comma-separated-item">
{{::ctrl.replicaSetDetail.podInfo.running}} running
</span>
</span>
<span class="kd-replicasetdetail-sidebar-line">Label selector</span>
<span class="kd-replicasetdetail-sidebar-subline kd-has-labels">
<kd-labels labels="::ctrl.replicaSetDetail.labelSelector"></kd-labels>
</span>
<span class="kd-replicasetdetail-sidebar-title">Replica Set</span>
<span class="kd-replicasetdetail-sidebar-line">Labels</span>
<span class="kd-replicasetdetail-sidebar-subline">
<span class="kd-replicasetdetail-sidebar-subline kd-has-labels">
<kd-labels labels="::ctrl.replicaSetDetail.labels"></kd-labels>
</span>
<span class="kd-replicasetdetail-sidebar-line">Images</span>
......@@ -62,29 +90,32 @@ limitations under the License.
</span>
<div ng-if="::ctrl.replicaSetDetail.services" layout="column">
<span class="kd-replicasetdetail-sidebar-title">Services</span>
<span class="kd-replicasetdetail-sidebar-line">Label selector</span>
<span class="kd-replicasetdetail-sidebar-subline"
ng-repeat="service in ::ctrl.replicaSetDetail.services">
<kd-labels labels="::service.selector"></kd-labels>
</span>
<span class="kd-replicasetdetail-sidebar-line">Internal endpoint</span>
<div class="kd-replicasetdetail-sidebar-subline"
ng-repeat="service in ::ctrl.replicaSetDetail.services">
<div ng-if="::service.internalEndpoint">
<kd-service-endpoint endpoint="::service.internalEndpoint"></kd-service-endpoint>
<div ng-repeat="service in ::ctrl.replicaSetDetail.services">
<span class="kd-replicasetdetail-sidebar-line">Name</span>
<span class="kd-replicasetdetail-sidebar-subline">
{{::service.name}}
</span>
<span class="kd-replicasetdetail-sidebar-line">Label selector</span>
<span class="kd-replicasetdetail-sidebar-subline kd-has-labels">
<kd-labels labels="::service.selector"></kd-labels>
</span>
<span class="kd-replicasetdetail-sidebar-line">Internal endpoint</span>
<div class="kd-replicasetdetail-sidebar-subline">
<div ng-if="::service.internalEndpoint">
<kd-service-endpoint endpoint="::service.internalEndpoint"></kd-service-endpoint>
</div>
<span ng-hide="service.internalEndpoint">none</span>
</div>
<span ng-hide="service.internalEndpoint">none</span>
</div>
<span class="kd-replicasetdetail-sidebar-line">External endpoint</span>
<div class="kd-replicasetdetail-sidebar-subline"
ng-repeat="service in ::ctrl.replicaSetDetail.services">
<div ng-repeat="endpoint in service.externalEndpoints">
<kd-service-endpoint endpoint="::endpoint"></kd-service-endpoint>
<span class="kd-replicasetdetail-sidebar-line">External endpoint</span>
<div class="kd-replicasetdetail-sidebar-subline">
<div ng-repeat="endpoint in service.externalEndpoints">
<kd-service-endpoint endpoint="::endpoint"></kd-service-endpoint>
</div>
<span class="kd-replicasetdetail-sidebar-subline"
ng-hide="::service.externalEndpoints">
none
</span>
</div>
<span class="kd-replicasetdetail-sidebar-subline"
ng-hide="::service.externalEndpoints">
none
</span>
</div>
</div>
</div>
......@@ -300,7 +331,7 @@ limitations under the License.
</thead>
<tbody>
<tr ng-repeat="event in ctrl.events | orderBy:ctrl.sortEventsBy:ctrl.eventsOrder">
<td class="kd-replicasetdetail-table-cell">
<td class="kd-replicasetdetail-table-cell kd-replicasetdetail-message-table-cell">
<i ng-if="ctrl.isEventWarning(event)"
class="material-icons kd-replicasetdetail-warning-icon">warning</i>
{{event.message}}
......
......@@ -33,7 +33,7 @@ $table-cell-height-half: $table-cell-height / 2;
.kd-replicasetdetail-sidebar-item {
padding-left: 2 * $baseline-grid;
padding-right: $baseline-grid;
padding-right: $baseline-grid;
}
.kd-replicasetdetail-table {
......@@ -51,21 +51,34 @@ $table-cell-height-half: $table-cell-height / 2;
.kd-replicasetdetail-sidebar-title {
font-size: $subhead-font-size-base;
font-weight: $bold-font-weight;
padding: $baseline-grid 0;
padding-bottom: $baseline-grid;
padding-top: $baseline-grid;
&.kd-replicasetdetail-sidebar-info {
padding-bottom: 0;
padding-top: 2 * $baseline-grid;
}
}
.kd-replicasetdetail-sidebar-line {
color: $foreground-2;
display: block;
font-size: $body-font-size-base;
padding-bottom: $baseline-grid;
}
.kd-replicasetdetail-sidebar-subline {
color: $foreground-1;
display: block;
font-size: $body-font-size-base;
overflow: hidden;
padding-bottom: $baseline-grid;
text-overflow: ellipsis;
&.kd-has-labels {
// To offset for labels margin.
margin-bottom: -$baseline-grid / 2;
}
}
.kd-replicasetdetail-warning-icon {
......@@ -84,10 +97,6 @@ $table-cell-height-half: $table-cell-height / 2;
padding-left: $baseline-grid + 6px;
}
.kd-replicasetdetail-sidebar-actions {
padding-top: $baseline-grid;
}
.kd-replicasetdetail-option-picker {
padding-right: 2 * $baseline-grid;
width: 15 * $baseline-grid;
......@@ -109,6 +118,11 @@ $table-cell-height-half: $table-cell-height / 2;
font-size: $body-font-size-base;
height: $table-cell-height;
padding: 0 0 0 (2 * $baseline-grid);
&.kd-replicasetdetail-message-table-cell {
white-space: normal;
word-break: break-all;
}
}
.kd-replicasetdetail-table-icon {
......
......@@ -20,8 +20,8 @@ limitations under the License.
<p>Replica set {{ctrl.replicaSetDetail.name}} will be updated to reflect the desired count.
<br/>
<span class="kd-updatereplicas-pod-status">
Current status: {{ctrl.replicaSetDetail.podsRunning}}
running, {{ctrl.replicaSetDetail.podsDesired}} desired
Current status: {{ctrl.replicaSetDetail.podsCreated}}
created, {{ctrl.replicaSetDetail.podsDesired}} desired
</span>
</p>
<form ng-submit="ctrl.updateReplicasCount()">
......
......@@ -21,12 +21,13 @@ export default class UpdateReplicasDialogController {
/**
* @param {!md.$dialog} $mdDialog
* @param {!angular.$log} $log
* @param {!ui.router.$state} $state
* @param {!backendApi.ReplicaSetDetail} replicaSetDetail
* @param {!function(number, function(!backendApi.ReplicaSetSpec),
* function(!angular.$http.Response)=)} updateReplicasFn
* @ngInject
*/
constructor($mdDialog, $log, replicaSetDetail, updateReplicasFn) {
constructor($mdDialog, $log, $state, replicaSetDetail, updateReplicasFn) {
/** @export {number} */
this.replicas;
......@@ -42,6 +43,9 @@ export default class UpdateReplicasDialogController {
/** @private {!angular.$log} */
this.log_ = $log;
/** @private {!ui.router.$state} */
this.state_ = $state;
}
/**
......@@ -68,6 +72,7 @@ export default class UpdateReplicasDialogController {
this.log_.info('Successfully updated replica set.');
this.log_.info(updatedSpec);
this.mdDialog_.hide();
this.state_.reload();
}
/**
......
......@@ -37,13 +37,15 @@ limitations under the License.
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">
<span ng-if="::ctrl.replicaSet.pods.pending"
class="kd-replicase-card-pods-stat kd-comma-separated-item">
{{::ctrl.replicaSet.pods.pending}} pending<!-- Collapse whitespace
--></span>
<span ng-if="::ctrl.replicaSet.pods.failed"
class="kd-replicase-card-pods-stat kd-comma-separated-item">
{{::ctrl.replicaSet.pods.failed}} failed<!-- Collapse whitespace
--></span>
<span class="kd-replicase-card-pods-stat kd-comma-separated-item">
{{::ctrl.replicaSet.pods.desired}} desired
</span>
</span>
......
// Copyright 2015 Google Inc. 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 main
import (
"fmt"
"net/http"
"reflect"
"testing"
restful "github.com/emicklei/go-restful"
)
func TestGetRemoteAddr(t *testing.T) {
cases := []struct {
request *restful.Request
expected string
}{
{
&restful.Request{
Request: &http.Request{
RemoteAddr: "192.168.1.1:8080",
},
},
"192.168.1.1",
},
{
&restful.Request{
Request: &http.Request{
RemoteAddr: "192.168.1.2",
},
},
"192.168.1.2",
},
}
for _, c := range cases {
actual := GetRemoteAddr(c.request)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("GetRemoteAddr(%#v) == %#v, expected %#v", c.request, actual, c.expected)
}
}
}
func TestFormatRequestLog(t *testing.T) {
cases := []struct {
request *restful.Request
remoteAddr string
expected string
}{
{
&restful.Request{
Request: &http.Request{
RemoteAddr: "192.168.1.1:8080",
Proto: "HTTP 1.1",
Method: "GET",
},
},
"192.168.1.1",
fmt.Sprintf(RequestLogString, "HTTP 1.1", "GET", "", "192.168.1.1", "[]"),
},
}
for _, c := range cases {
actual := FormatRequestLog(c.request, c.remoteAddr)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("GetRemoteAddr(%#v, %#v) == %#v, expected %#v", c.request, c.remoteAddr,
actual, c.expected)
}
}
}
func TestFormatResponseLog(t *testing.T) {
cases := []struct {
response *restful.Response
remoteAddr string
expected string
}{
{
&restful.Response{},
"192.168.1.1",
fmt.Sprintf(ResponseLogString, "192.168.1.1", http.StatusOK),
},
}
for _, c := range cases {
actual := FormatResponseLog(c.response, c.remoteAddr)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("GetRemoteAddr(%#v, %#v) == %#v, expected %#v", c.response, c.remoteAddr,
actual, c.expected)
}
}
}
......@@ -134,7 +134,7 @@ func TestGetReplicaSetList(t *testing.T) {
},
},
[]api.Pod{
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -143,7 +143,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodFailed,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -152,7 +152,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodFailed,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -161,7 +161,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodPending,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-2",
Labels: map[string]string{"app": "my-name-1"},
......@@ -170,7 +170,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodPending,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -179,7 +179,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodRunning,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -188,7 +188,7 @@ func TestGetReplicaSetList(t *testing.T) {
Phase: api.PodSucceeded,
},
},
api.Pod{
{
ObjectMeta: api.ObjectMeta{
Namespace: "namespace-1",
Labels: map[string]string{"app": "my-name-1"},
......@@ -207,7 +207,7 @@ func TestGetReplicaSetList(t *testing.T) {
InternalEndpoints: []Endpoint{{Host: "my-app-1.namespace-1"}},
Pods: ReplicaSetPodInfo{
Failed: 2,
Waiting: 1,
Pending: 1,
Running: 1,
},
}, {
......
......@@ -21,12 +21,12 @@ describe('Replica Set Detail controller', () => {
* @type {!ReplicaSetDetailController}
*/
let ctrl;
/** @type {!md.$dialog} */
let mdDialog;
/** @type {!angular.$log} */
let log;
/** @type {!ui.router.$state} */
let state;
/**
* First parameter behavior is changed to indicate successful/failed update.
......@@ -45,11 +45,14 @@ describe('Replica Set Detail controller', () => {
beforeEach(() => {
angular.mock.module(replicaSetDetailModule.name);
angular.mock.inject(($resource, $log, $state, $mdDialog) => {
angular.mock.inject(($resource, $log, $state, $mdDialog, $controller) => {
mdDialog = $mdDialog;
log = $log;
state = $state;
ctrl = new UpdateReplicasDialogController(mdDialog, log, {}, mockUpdateReplicasFn);
ctrl = $controller(
UpdateReplicasDialogController,
{replicaSetDetail: {}, updateReplicasFn: mockUpdateReplicasFn});
});
});
......@@ -57,6 +60,7 @@ describe('Replica Set Detail controller', () => {
// given
spyOn(log, 'info');
spyOn(mdDialog, 'hide');
spyOn(state, 'reload');
// Indicates if there was error during update
ctrl.replicas = false;
......@@ -66,6 +70,7 @@ describe('Replica Set Detail controller', () => {
// then
expect(log.info).toHaveBeenCalledWith('Successfully updated replica set.');
expect(mdDialog.hide).toHaveBeenCalled();
expect(state.reload).toHaveBeenCalled();
});
it('should log error after edit replicas and hide the dialog', () => {
......@@ -84,6 +89,8 @@ describe('Replica Set Detail controller', () => {
});
it('should close the dialog on cancel', () => {
spyOn(state, 'reload');
// given
spyOn(mdDialog, 'cancel');
......@@ -92,5 +99,6 @@ describe('Replica Set Detail controller', () => {
// then
expect(mdDialog.cancel).toHaveBeenCalled();
expect(state.reload).not.toHaveBeenCalled();
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册