Upgrade loadbalancer image

This commit is contained in:
Vincent Fiduccia 2016-12-09 18:51:05 -07:00
parent 204bfd1a6f
commit 7eb2bb45f4
18 changed files with 152 additions and 22 deletions

View File

@ -55,7 +55,7 @@
<tr> <tr>
<td data-title="{{t 'auditLogsPage.table.time'}}:">{{date-from-now log.created}}</td> <td data-title="{{t 'auditLogsPage.table.time'}}:">{{date-from-now log.created}}</td>
<td data-title="{{t 'auditLogsPage.table.eventType'}}:" class="force-wrap" title="{{log.eventType}}"> <td data-title="{{t 'auditLogsPage.table.eventType'}}:" class="force-wrap" title="{{log.eventType}}">
{{log.eventType}} <i class="icon icon-info addtl-info-trigger" {{action 'showResponseObjects' log.requestObject log.responseObject }}></i> {{log.eventType}} <i class="icon icon-info service-icon-button" {{action 'showResponseObjects' log.requestObject log.responseObject }}></i>
</td> </td>
<td data-title="{{t 'auditLogsPage.table.description'}}:">{{#if log.description}}{{log.description}}{{else}}<span class="text-muted">None</span>{{/if}}</td> <td data-title="{{t 'auditLogsPage.table.description'}}:">{{#if log.description}}{{log.description}}{{else}}<span class="text-muted">None</span>{{/if}}</td>
<td data-title="{{t 'auditLogsPage.table.environment'}}:" class="clip"> <td data-title="{{t 'auditLogsPage.table.environment'}}:" class="clip">

View File

@ -12,6 +12,7 @@ export default Ember.Component.extend(NewOrEdit, {
allHosts : null, allHosts : null,
allServices : null, allServices : null,
allCertificates : null, allCertificates : null,
upgradeImage : null,
isGlobal : null, isGlobal : null,
isRequestedHost : null, isRequestedHost : null,
@ -212,6 +213,10 @@ export default Ember.Component.extend(NewOrEdit, {
return false; return false;
} }
if ( this.get('upgradeImage')+'' === 'true' ) {
return true;
}
// Label arrays are updated one at a time and make this flap, // Label arrays are updated one at a time and make this flap,
// so ignore them until they're all set // so ignore them until they're all set
if ( !this.get('labelsReady') ) { if ( !this.get('labelsReady') ) {
@ -222,9 +227,23 @@ export default Ember.Component.extend(NewOrEdit, {
let neu = removeKeys(this.get('service.launchConfig.labels'),C.LABELS_TO_IGNORE); let neu = removeKeys(this.get('service.launchConfig.labels'),C.LABELS_TO_IGNORE);
return arrayToStr(old) !== arrayToStr(neu); return arrayToStr(old) !== arrayToStr(neu);
}.property( }.property(
'editing',
'upgradeImage',
'service.launchConfig.labels' 'service.launchConfig.labels'
), ),
upgradeInfo: function() {
let from = (this.get('existing.launchConfig.imageUuid')||'').replace(/^docker:/,'');
let to = (this.get('service.launchConfig.imageUuid')||'').replace(/^docker:/,'');
if ( this.get('upgradeImage')+'' === 'true' ) {
return Ember.Object.create({
from: from,
to: to,
});
}
}.property('existing.launchConfig.imageUuid','service.launchConfig.imageUuid'),
// ---------------------------------- // ----------------------------------
// Labels // Labels
// ---------------------------------- // ----------------------------------

View File

@ -92,5 +92,16 @@
</div> </div>
{{/select-tab}} {{/select-tab}}
{{#if upgradeInfo}}
<div class="lacsso banner bg-info m-20 p-0">
<div class="lacsso banner-icon" style="width: 68px;"><span class="icon icon-2x icon-info"></span></div>
<div class="lacsso banner-info">
<p class="lacsso p-15 ">
{{format-html-message 'servicePage.newBalancer.upgradeImage' from=upgradeInfo.from to=upgradeInfo.to}}
</p>
</div>
</div>
{{/if}}
{{top-errors errors=errors}} {{top-errors errors=errors}}
{{save-cancel editing=editing editLabel=editLabel save="save" cancel="cancel"}} {{save-cancel editing=editing editLabel=editLabel save="save" cancel="cancel"}}

View File

@ -40,9 +40,13 @@ export default Ember.Component.extend({
this.get('prefs').set(C.PREFS.EXPANDED_STACKS, list); this.get('prefs').set(C.PREFS.EXPANDED_STACKS, list);
}, },
addtlInfo: function(service) { addtlInfo(service) {
this.sendAction('showAddtlInfo', service); this.sendAction('showAddtlInfo', service);
}, },
upgradeImage(service) {
service.send('upgrade','true');
}
}, },
init() { init() {

View File

@ -96,12 +96,19 @@
{{#if service.showTransitioningMessage}} {{#if service.showTransitioningMessage}}
<span class="{{service.stateColor}}">({{service.transitioningMessage}})</span> <span class="{{service.stateColor}}">({{service.transitioningMessage}})</span>
{{/if}} {{/if}}
<button type="button" class="btn-link" role="button" {{action 'addtlInfo' service}}> <button type="button" class="btn-link service-icon-button" role="button" {{action 'addtlInfo' service}}>
<i class="icon icon-info addtl-info-trigger"/> <i class="icon icon-info"/>
</button> </button>
{{#if service.isError}} {{~#if service.imageUpgradeAvailable~}}
{{#link-to "service.log" service.stackId service.id class="btn-link"}}<i class="icon icon-alert"/>{{/link-to}} {{#tooltip-element type="tooltip-basic" model=(t 'stackSection.upgradeImage') tooltipTemplate="tooltip-static" aria-describedby="tooltip-base" tooltipFor="upgradeImage"}}
{{/if}} <button type="button" class="btn-link text-warning service-icon-button r-pl0" role="button" {{action 'upgradeImage' service}}>
<i class="icon icon-arrow-circle-up"/>
</button>
{{/tooltip-element}}
{{~/if~}}
{{~#if service.isError~}}
{{#link-to "service.log" service.stackId service.id class="btn-link service-icon-button"}}<i class="icon icon-alert"/>{{/link-to}}
{{~/if~}}
</td> </td>
<td data-title="{{t 'stackSection.table.dataTitle.details'}}:" class="force-wrap service-detail">{{service.displayDetail}}{{service.displayPorts}}</td> <td data-title="{{t 'stackSection.table.dataTitle.details'}}:" class="force-wrap service-detail">{{service.displayDetail}}{{service.displayPorts}}</td>
<td data-title="{{t 'stackSection.table.dataTitle.kind'}}:"> <td data-title="{{t 'stackSection.table.dataTitle.kind'}}:">

View File

@ -0,0 +1,31 @@
import Ember from 'ember';
import C from 'ui/utils/constants';
export default Ember.Route.extend({
k8s: Ember.inject.service(),
model() {
return this.get('k8s').getServices().then((services) => {
let svc = services.find(function(x) {
return x && x.metadata && x.metadata.labels && x.metadata.labels[C.LABEL.K8S_DASHBOARD];
});
if ( svc )
{
let port = svc.spec.ports[0];
let dashboard;
if ( port ) {
dashboard = 'http://' + this.get('k8s.clusterIp') +'/'+ port.nodePort;
}
return Ember.Object.create({
dashboardUrl: dashboard,
});
}
else
{
return Ember.RSVP.reject('Unable to find kubernetes-dashbaord service');
}
});
},
});

View File

@ -0,0 +1,20 @@
<section class="header">
<h1>{{t 'k8sTab.dashboard.header'}}</h1>
</section>
<div class="row r-mt20 r-ml20 r-mr20">
<div class="text-center col-md-6 col-md-offset-3 gutter">
<div class="well">
<div class="row">
<img height="55" src="{{app.baseAssets}}assets/images/hexagon-kubernetes.svg" />
</div>
<h4>{{t 'k8sTab.dashboard.dashboard.header'}}</h4>
<p>{{t 'k8sTab.dashboard.dashboard.content'}}</p>
{{#if model.dashboardUrl}}
<a href="{{model.dashboardUrl}}" target="_blank" rel="noreferrer nofollow" class="btn btn-primary">{{t 'k8sTab.dashboard.dashboard.button'}}</a>
{{else}}
<button class="btn btn-primary btn-disabled">{{t 'k8sTab.dashboard.dashboard.button'}}</button>
{{/if}}
</div>
</div>
</div>

View File

@ -18,7 +18,9 @@ function specToPort(spec) {
var LoadBalancerService = Service.extend({ var LoadBalancerService = Service.extend({
type: 'loadBalancerService', type: 'loadBalancerService',
intl : Ember.inject.service(),
intl: Ember.inject.service(),
settings: Ember.inject.service(),
initPorts() { initPorts() {
let rules = this.get('lbConfig.portRules')||[]; let rules = this.get('lbConfig.portRules')||[];
@ -122,6 +124,12 @@ var LoadBalancerService = Service.extend({
return out.htmlSafe(); return out.htmlSafe();
}.property('consumedServicesWithNames.@each.{name,service}', 'intl._locale'), }.property('consumedServicesWithNames.@each.{name,service}', 'intl._locale'),
imageUpgradeAvailable: function() {
let cur = this.get('launchConfig.imageUuid').replace(/^docker:/,'');
let available = this.get(`settings.${C.SETTING.BALANCER_IMAGE}`);
return cur !== available && !!this.get('actionLinks.upgrade');
}.property('launchConfig.imageUuid',`settings.${C.SETTING.BALANCER_IMAGE}`,'actionLinks.upgrade'),
}); });
export default LoadBalancerService; export default LoadBalancerService;

View File

@ -79,7 +79,7 @@ var Service = Resource.extend({
} }
}, },
upgrade() { upgrade(upgradeImage='false') {
var route = 'service.new'; var route = 'service.new';
if ( (this.get('launchConfig.kind')||'').toLowerCase() === 'virtualmachine') { if ( (this.get('launchConfig.kind')||'').toLowerCase() === 'virtualmachine') {
route = 'service.new-virtualmachine'; route = 'service.new-virtualmachine';
@ -90,6 +90,7 @@ var Service = Resource.extend({
this.get('application').transitionToRoute(route, {queryParams: { this.get('application').transitionToRoute(route, {queryParams: {
serviceId: this.get('id'), serviceId: this.get('id'),
upgrade: true, upgrade: true,
upgradeImage: upgradeImage,
stackId: this.get('stackId'), stackId: this.get('stackId'),
}}); }});
}, },
@ -386,8 +387,6 @@ var Service = Resource.extend({
return Util.formatSi(this.get('launchConfig.memoryReservation'), 1024, 'iB', 'B'); return Util.formatSi(this.get('launchConfig.memoryReservation'), 1024, 'iB', 'B');
} }
}), }),
}); });
export function activeIcon(service) export function activeIcon(service)

View File

@ -79,7 +79,7 @@ export default Resource.extend({
} }
if ( str === C.LABEL.CERTIFIED_RANCHER && this.get('catalogId') === C.CATALOG.LIBRARY_KEY ) { if ( str === C.LABEL.CERTIFIED_RANCHER && this.get('catalogId') === C.CATALOG.LIBRARY_KEY ) {
return 'badge-certified'; return 'badge-rancher';
} else if ( str === C.LABEL.CERTIFIED_PARTNER ) { } else if ( str === C.LABEL.CERTIFIED_PARTNER ) {
return 'badge-partner'; return 'badge-partner';
} else { } else {

View File

@ -1,11 +1,12 @@
import Ember from 'ember'; import Ember from 'ember';
export default Ember.Controller.extend({ export default Ember.Controller.extend({
queryParams: ['stackId','serviceId','tab','upgrade'], queryParams: ['stackId','serviceId','tab','upgrade','upgradeImage'],
stackId: null, stackId: null,
serviceId: null, serviceId: null,
tab: 'ssl', tab: 'ssl',
upgrade: null, upgrade: null,
upgradeImage: 'false',
actions: { actions: {
done() { done() {

View File

@ -24,6 +24,11 @@ export default Ember.Route.extend({
if ( hash.existingService ) { if ( hash.existingService ) {
if ( params.upgrade+'' === 'true' ) { if ( params.upgrade+'' === 'true' ) {
service = hash.existingService.clone(); service = hash.existingService.clone();
if ( params.upgradeImage+'' === 'true' ) {
service.set('launchConfig.imageUuid', 'docker:' + this.get(`settings.${C.SETTING.BALANCER_IMAGE}`));
}
hash.existing = hash.existingService; hash.existing = hash.existingService;
} else { } else {
service = hash.existingService.cloneForNew(); service = hash.existingService.cloneForNew();
@ -74,6 +79,7 @@ export default Ember.Route.extend({
controller.set('stackId', null); controller.set('stackId', null);
controller.set('serviceId', null); controller.set('serviceId', null);
controller.set('upgrade', null); controller.set('upgrade', null);
controller.set('upgradeImage', null);
} }
}, },

View File

@ -2,6 +2,7 @@
service=model.service service=model.service
existing=model.existing existing=model.existing
editing=upgrade editing=upgrade
upgradeImage=upgradeImage
allHosts=model.allHosts allHosts=model.allHosts
allServices=model.allServices allServices=model.allServices
allCertificates=model.allCertificates allCertificates=model.allCertificates

View File

@ -172,8 +172,9 @@ $lines-to-show: 4;
@extend .badge-rancher; @extend .badge-rancher;
background-color: $greenTwo; background-color: $greenTwo;
&:after { &:before {
border-color: $greenTwo; border-color: $greenTwo;
border-left-color: transparent;
} }
} }
@ -181,8 +182,9 @@ $lines-to-show: 4;
@extend .badge-rancher; @extend .badge-rancher;
background-color: $blueTwo; background-color: $blueTwo;
&:after { &:before {
border-color: $blueTwo; border-color: $blueTwo;
border-left-color: transparent;
} }
} }

View File

@ -478,11 +478,10 @@ $light-yellow: #FFBE18;
background-image: url('images/hexagon-kubernetes.svg'); background-image: url('images/hexagon-kubernetes.svg');
} }
.addtl-info-trigger { .service-icon-button {
cursor: pointer; cursor: pointer;
margin-left: 3px; padding-left: 3px;
position: relative; padding-right: 3px;
top: 1px;
} }
.service-detail { .service-detail {

View File

@ -131,7 +131,7 @@ var C = {
K8S_POD_NAMESPACE: 'io.kubernetes.pod.namespace', K8S_POD_NAMESPACE: 'io.kubernetes.pod.namespace',
K8S_POD_NAME: 'io.kubernetes.pod.name', K8S_POD_NAME: 'io.kubernetes.pod.name',
K8S_KUBECTL: 'io.rancher.k8s.kubectld', K8S_KUBECTL: 'io.rancher.k8s.kubectld',
K8S_DASHBOARD: 'io.rancher.k8s.dashboard', K8S_DASHBOARD: 'io.rancher.k8s.kubernetes-dashboard',
ORCHESTRATION_SUPPORTED: 'io.rancher.orchestration.supported', ORCHESTRATION_SUPPORTED: 'io.rancher.orchestration.supported',
CERTIFIED: 'io.rancher.certified', CERTIFIED: 'io.rancher.certified',
CERTIFIED_RANCHER: 'rancher', CERTIFIED_RANCHER: 'rancher',

View File

@ -105,6 +105,9 @@ const navTree = [
ctx: [getProjectId, getNamespaceId], ctx: [getProjectId, getNamespaceId],
condition: k8sReady, condition: k8sReady,
}, },
{
divider: true,
},
{ {
id: 'k8s-cli', id: 'k8s-cli',
localizedLabel: 'nav.k8s.cli', localizedLabel: 'nav.k8s.cli',
@ -113,6 +116,16 @@ const navTree = [
ctx: [getProjectId], ctx: [getProjectId],
condition: k8sReady, condition: k8sReady,
}, },
/*
{
id: 'k8s-dashboard',
localizedLabel: 'nav.k8s.dashboard',
icon: 'icon icon-external-link',
route: 'k8s-tab.dashboard',
ctx: [getProjectId],
condition: k8sReady,
},
*/
{ {
id: 'k8s-notready', id: 'k8s-notready',
icon: 'icon icon-spinner icon-spin', icon: 'icon icon-spinner icon-spin',

View File

@ -703,6 +703,13 @@ k8sTab:
petset: Pet Set petset: Pet Set
pod: Pod pod: Pod
dashboard:
header: Kubernetes Dashboard
dashboard:
header: Dashboard
content: Kubernetes Dashboard is a general purpose, web-based UI for Kubernetes clusters. It allows users to manage applications running in the cluster and troubleshoot them, as well as manage the cluster itself.
button: Kubernetes UI
kubectl: kubectl:
header: kubectl header: kubectl
stepOne: stepOne:
@ -946,6 +953,7 @@ servicePage:
description: description:
placeholder: e.g. Current version of MyApp placeholder: e.g. Current version of MyApp
newBalancer: newBalancer:
upgradeImage: "The balancer software image will be upgraded from <code>{from}</code> to <code>{to}</code>."
form: form:
name: name:
placeholder: e.g. website placeholder: e.g. website
@ -3010,6 +3018,7 @@ stackSection:
details: Details details: Details
containers: Containers containers: Containers
actions: Actions actions: Actions
upgradeImage: Upgrade Container Image
snapshotSection: snapshotSection: