Commit 940c812d authored by Enrique Alcántara's avatar Enrique Alcántara Committed by Phil Hughes

Replace upgrade with update

Use update term instead of update in the clusters managed app
implementation in order to make the implementation and UI
language more consistent.
parent 431f33fe
......@@ -142,8 +142,7 @@ export default class Clusters {
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
eventHub.$on('upgradeApplication', data => this.upgradeApplication(data));
eventHub.$on('dismissUpgradeSuccess', appId => this.dismissUpgradeSuccess(appId));
eventHub.$on('updateApplication', data => this.updateApplication(data));
eventHub.$on('saveKnativeDomain', data => this.saveKnativeDomain(data));
eventHub.$on('setKnativeHostname', data => this.setKnativeHostname(data));
eventHub.$on('uninstallApplication', data => this.uninstallApplication(data));
......@@ -155,8 +154,7 @@ export default class Clusters {
removeListeners() {
if (this.showTokenButton) this.showTokenButton.removeEventListener('click', this.showToken);
eventHub.$off('installApplication', this.installApplication);
eventHub.$off('upgradeApplication', this.upgradeApplication);
eventHub.$off('dismissUpgradeSuccess', this.dismissUpgradeSuccess);
eventHub.$off('updateApplication', this.updateApplication);
eventHub.$off('saveKnativeDomain');
eventHub.$off('setKnativeHostname');
eventHub.$off('uninstallApplication');
......@@ -331,19 +329,13 @@ export default class Clusters {
});
}
upgradeApplication(data) {
const appId = data.id;
updateApplication({ id: appId, params }) {
this.store.updateApplication(appId);
this.service.installApplication(appId, data.params).catch(() => {
this.service.installApplication(appId, params).catch(() => {
this.store.notifyUpdateFailure(appId);
});
}
dismissUpgradeSuccess(appId) {
this.store.acknowledgeSuccessfulUpdate(appId);
}
toggleIngressDomainHelpText({ externalIp }, { externalIp: newExternalIp }) {
if (externalIp !== newExternalIp) {
this.ingressDomainHelpText.classList.toggle('hide', !newExternalIp);
......
......@@ -2,7 +2,7 @@
/* eslint-disable vue/require-default-prop */
import { GlLink, GlModalDirective } from '@gitlab/ui';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import { s__, sprintf } from '../../locale';
import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
......@@ -85,7 +85,7 @@ export default {
type: String,
required: false,
},
upgradeAvailable: {
updateAvailable: {
type: Boolean,
required: false,
},
......@@ -113,11 +113,6 @@ export default {
required: false,
default: false,
},
updateAcknowledged: {
type: Boolean,
required: false,
default: true,
},
installApplicationRequestParams: {
type: Object,
required: false,
......@@ -174,11 +169,11 @@ export default {
installButtonLabel() {
let label;
if (this.canInstall) {
label = s__('ClusterIntegration|Install');
label = __('Install');
} else if (this.isInstalling) {
label = s__('ClusterIntegration|Installing');
label = __('Installing');
} else if (this.installed) {
label = s__('ClusterIntegration|Installed');
label = __('Installed');
}
return label;
......@@ -187,7 +182,7 @@ export default {
return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
},
manageButtonLabel() {
return s__('ClusterIntegration|Manage');
return __('Manage');
},
hasError() {
return this.installFailed || this.uninstallFailed;
......@@ -207,42 +202,42 @@ export default {
},
versionLabel() {
if (this.updateFailed) {
return s__('ClusterIntegration|Upgrade failed');
} else if (this.isUpgrading) {
return s__('ClusterIntegration|Upgrading');
return __('Update failed');
} else if (this.isUpdating) {
return __('Updating');
}
return s__('ClusterIntegration|Upgraded');
return __('Updated');
},
upgradeFailureDescription() {
updateFailureDescription() {
return s__('ClusterIntegration|Update failed. Please check the logs and try again.');
},
upgradeSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} upgraded successfully.'), {
updateSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} updated successfully.'), {
title: this.title,
});
},
upgradeButtonLabel() {
updateButtonLabel() {
let label;
if (this.upgradeAvailable && !this.updateFailed && !this.isUpgrading) {
label = s__('ClusterIntegration|Upgrade');
} else if (this.isUpgrading) {
label = s__('ClusterIntegration|Updating');
if (this.updateAvailable && !this.updateFailed && !this.isUpdating) {
label = __('Update');
} else if (this.isUpdating) {
label = __('Updating');
} else if (this.updateFailed) {
label = s__('ClusterIntegration|Retry update');
label = __('Retry update');
}
return label;
},
isUpgrading() {
isUpdating() {
// Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
return this.status === APPLICATION_STATUS.UPDATING;
},
shouldShowUpgradeDetails() {
shouldShowUpdateDetails() {
// This method only returns true when;
// Upgrade was successful OR Upgrade failed
// AND new upgrade is unavailable AND version information is present.
return (this.updateSuccessful || this.updateFailed) && !this.upgradeAvailable && this.version;
// Update was successful OR Update failed
// AND new update is unavailable AND version information is present.
return (this.updateSuccessful || this.updateFailed) && !this.updateAvailable && this.version;
},
uninstallSuccessDescription() {
return sprintf(s__('ClusterIntegration|%{title} uninstalled successfully.'), {
......@@ -253,7 +248,7 @@ export default {
watch: {
updateSuccessful(updateSuccessful) {
if (updateSuccessful) {
this.$toast.show(this.upgradeSuccessDescription);
this.$toast.show(this.updateSuccessDescription);
}
},
uninstallSuccessful(uninstallSuccessful) {
......@@ -269,8 +264,8 @@ export default {
params: this.installApplicationRequestParams,
});
},
upgradeClicked() {
eventHub.$emit('upgradeApplication', {
updateClicked() {
eventHub.$emit('updateApplication', {
id: this.id,
params: this.installApplicationRequestParams,
});
......@@ -332,8 +327,8 @@ export default {
<div v-if="updateable">
<div
v-if="shouldShowUpgradeDetails"
class="form-text text-muted label p-0 js-cluster-application-upgrade-details"
v-if="shouldShowUpdateDetails"
class="form-text text-muted label p-0 js-cluster-application-update-details"
>
{{ versionLabel }}
<span v-if="updateSuccessful">to</span>
......@@ -342,24 +337,24 @@ export default {
v-if="updateSuccessful"
:href="chartRepo"
target="_blank"
class="js-cluster-application-upgrade-version"
class="js-cluster-application-update-version"
>chart v{{ version }}</gl-link
>
</div>
<div
v-if="updateFailed && !isUpgrading"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message"
v-if="updateFailed && !isUpdating"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-update-details"
>
{{ upgradeFailureDescription }}
{{ updateFailureDescription }}
</div>
<loading-button
v-if="upgradeAvailable || updateFailed || isUpgrading"
class="btn btn-primary js-cluster-application-upgrade-button mt-2"
:loading="isUpgrading"
:disabled="isUpgrading"
:label="upgradeButtonLabel"
@click="upgradeClicked"
v-if="updateAvailable || updateFailed || isUpdating"
class="btn btn-primary js-cluster-application-update-button mt-2"
:loading="isUpdating"
:disabled="isUpdating"
:label="updateButtonLabel"
@click="updateClicked"
/>
</div>
</div>
......
......@@ -376,7 +376,7 @@ export default {
:request-reason="applications.runner.requestReason"
:version="applications.runner.version"
:chart-repo="applications.runner.chartRepo"
:upgrade-available="applications.runner.upgradeAvailable"
:update-available="applications.runner.updateAvailable"
:installed="applications.runner.installed"
:install-failed="applications.runner.installFailed"
:update-successful="applications.runner.updateSuccessful"
......
......@@ -123,7 +123,6 @@ const applicationStateMachine = {
target: INSTALLED,
effects: {
updateSuccessful: true,
updateAcknowledged: false,
},
},
[UPDATE_ERRORED]: {
......
......@@ -56,8 +56,7 @@ export default class ClusterStore {
title: s__('ClusterIntegration|GitLab Runner'),
version: null,
chartRepo: 'https://gitlab.com/charts/gitlab-runner',
upgradeAvailable: null,
updateAcknowledged: true,
updateAvailable: null,
updateSuccessful: false,
updateFailed: false,
},
......@@ -136,10 +135,6 @@ export default class ClusterStore {
this.state.applications[appId] = transitionApplicationState(currentAppState, event);
}
acknowledgeSuccessfulUpdate(appId) {
this.state.applications[appId].updateAcknowledged = true;
}
updateAppProperty(appId, prop, value) {
this.state.applications[appId][prop] = value;
}
......@@ -154,7 +149,7 @@ export default class ClusterStore {
status,
status_reason: statusReason,
version,
update_available: upgradeAvailable,
update_available: updateAvailable,
can_uninstall: uninstallable,
} = serverAppEntry;
const currentApplicationState = this.state.applications[appId] || {};
......@@ -191,7 +186,7 @@ export default class ClusterStore {
serverAppEntry.external_hostname || this.state.applications.knative.externalHostname;
} else if (appId === RUNNER) {
this.state.applications.runner.version = version;
this.state.applications.runner.upgradeAvailable = upgradeAvailable;
this.state.applications.runner.updateAvailable = updateAvailable;
}
});
}
......
......@@ -2136,7 +2136,7 @@ msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
msgstr ""
msgid "ClusterIntegration|%{title} upgraded successfully."
msgid "ClusterIntegration|%{title} updated successfully."
msgstr ""
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
......@@ -2331,15 +2331,6 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
msgid "ClusterIntegration|Install"
msgstr ""
msgid "ClusterIntegration|Installed"
msgstr ""
msgid "ClusterIntegration|Installing"
msgstr ""
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
......@@ -2427,9 +2418,6 @@ msgstr ""
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Manage"
msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
......@@ -2496,9 +2484,6 @@ msgstr ""
msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
msgid "ClusterIntegration|Retry update"
msgstr ""
msgid "ClusterIntegration|Save changes"
msgstr ""
......@@ -2598,21 +2583,6 @@ msgstr ""
msgid "ClusterIntegration|Update failed. Please check the logs and try again."
msgstr ""
msgid "ClusterIntegration|Updating"
msgstr ""
msgid "ClusterIntegration|Upgrade"
msgstr ""
msgid "ClusterIntegration|Upgrade failed"
msgstr ""
msgid "ClusterIntegration|Upgraded"
msgstr ""
msgid "ClusterIntegration|Upgrading"
msgstr ""
msgid "ClusterIntegration|Validating project billing status"
msgstr ""
......@@ -5339,6 +5309,9 @@ msgstr ""
msgid "Insert suggestion"
msgstr ""
msgid "Install"
msgstr ""
msgid "Install GitLab Runner"
msgstr ""
......@@ -5348,6 +5321,12 @@ msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
msgid "Installed"
msgstr ""
msgid "Installing"
msgstr ""
msgid "Instance Statistics"
msgstr ""
......@@ -5940,6 +5919,9 @@ msgstr ""
msgid "Makes this issue confidential"
msgstr ""
msgid "Manage"
msgstr ""
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
msgstr ""
......@@ -8535,6 +8517,9 @@ msgstr ""
msgid "Retry this job in order to create the necessary resources."
msgstr ""
msgid "Retry update"
msgstr ""
msgid "Retry verification"
msgstr ""
......@@ -11011,6 +10996,9 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
msgid "Updated"
msgstr ""
msgid "Updating"
msgstr ""
......
......@@ -8,8 +8,8 @@ module QA
class Show < Page::Base
view 'app/assets/javascripts/clusters/components/application_row.vue' do
element :application_row, 'js-cluster-application-row-${this.id}' # rubocop:disable QA/ElementWithPattern
element :install_button, "s__('ClusterIntegration|Install')" # rubocop:disable QA/ElementWithPattern
element :installed_button, "s__('ClusterIntegration|Installed')" # rubocop:disable QA/ElementWithPattern
element :install_button, "__('Install')" # rubocop:disable QA/ElementWithPattern
element :installed_button, "__('Installed')" # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/clusters/components/applications.vue' do
......
import Clusters from '~/clusters/clusters_bundle';
import { APPLICATION_STATUS, INGRESS_DOMAIN_SUFFIX, APPLICATIONS } from '~/clusters/constants';
import {
APPLICATION_STATUS,
INGRESS_DOMAIN_SUFFIX,
APPLICATIONS,
RUNNER,
} from '~/clusters/constants';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { loadHTMLFixture } from 'helpers/fixtures';
......@@ -353,4 +358,30 @@ describe('Clusters', () => {
});
});
});
describe('updateApplication', () => {
const params = { version: '1.0.0' };
let storeUpdateApplication;
let installApplication;
beforeEach(() => {
storeUpdateApplication = jest.spyOn(cluster.store, 'updateApplication');
installApplication = jest.spyOn(cluster.service, 'installApplication');
cluster.updateApplication({ id: RUNNER, params });
});
afterEach(() => {
storeUpdateApplication.mockRestore();
installApplication.mockRestore();
});
it('calls store updateApplication method', () => {
expect(storeUpdateApplication).toHaveBeenCalledWith(RUNNER);
});
it('sends installApplication request', () => {
expect(installApplication).toHaveBeenCalledWith(RUNNER, params);
});
});
});
......@@ -245,26 +245,26 @@ describe('Application Row', () => {
});
});
describe('Upgrade button', () => {
describe('Update button', () => {
it('has indeterminate state on page load', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: null,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
expect(upgradeBtn).toBe(null);
expect(updateBtn).toBe(null);
});
it('has enabled "Upgrade" when "upgradeAvailable" is true', () => {
it('has enabled "Update" when "updateAvailable" is true', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
upgradeAvailable: true,
updateAvailable: true,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
expect(upgradeBtn).not.toBe(null);
expect(upgradeBtn.innerHTML).toContain('Upgrade');
expect(updateBtn).not.toBe(null);
expect(updateBtn.innerHTML).toContain('Update');
});
it('has enabled "Retry update" when update process fails', () => {
......@@ -273,10 +273,10 @@ describe('Application Row', () => {
status: APPLICATION_STATUS.INSTALLED,
updateFailed: true,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
expect(upgradeBtn).not.toBe(null);
expect(upgradeBtn.innerHTML).toContain('Retry update');
expect(updateBtn).not.toBe(null);
expect(updateBtn.innerHTML).toContain('Retry update');
});
it('has disabled "Updating" when APPLICATION_STATUS.UPDATING', () => {
......@@ -284,53 +284,51 @@ describe('Application Row', () => {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.UPDATING,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
expect(upgradeBtn).not.toBe(null);
expect(vm.isUpgrading).toBe(true);
expect(upgradeBtn.innerHTML).toContain('Updating');
expect(updateBtn).not.toBe(null);
expect(vm.isUpdating).toBe(true);
expect(updateBtn.innerHTML).toContain('Updating');
});
it('clicking upgrade button emits event', () => {
it('clicking update button emits event', () => {
jest.spyOn(eventHub, '$emit');
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.INSTALLED,
upgradeAvailable: true,
updateAvailable: true,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
upgradeBtn.click();
updateBtn.click();
expect(eventHub.$emit).toHaveBeenCalledWith('upgradeApplication', {
expect(eventHub.$emit).toHaveBeenCalledWith('updateApplication', {
id: DEFAULT_APPLICATION_STATE.id,
params: {},
});
});
it('clicking disabled upgrade button emits nothing', () => {
it('clicking disabled update button emits nothing', () => {
jest.spyOn(eventHub, '$emit');
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
status: APPLICATION_STATUS.UPDATING,
});
const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
const updateBtn = vm.$el.querySelector('.js-cluster-application-update-button');
upgradeBtn.click();
updateBtn.click();
expect(eventHub.$emit).not.toHaveBeenCalled();
});
it('displays an error message if application upgrade failed', () => {
it('displays an error message if application update failed', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
title: 'GitLab Runner',
status: APPLICATION_STATUS.INSTALLED,
updateFailed: true,
});
const failureMessage = vm.$el.querySelector(
'.js-cluster-application-upgrade-failure-message',
);
const failureMessage = vm.$el.querySelector('.js-cluster-application-update-details');
expect(failureMessage).not.toBe(null);
expect(failureMessage.innerHTML).toContain(
......@@ -338,7 +336,7 @@ describe('Application Row', () => {
);
});
it('displays a success toast message if application upgrade was successful', () => {
it('displays a success toast message if application update was successful', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
title: 'GitLab Runner',
......@@ -349,13 +347,13 @@ describe('Application Row', () => {
vm.updateSuccessful = true;
return vm.$nextTick(() => {
expect(vm.$toast.show).toHaveBeenCalledWith('GitLab Runner upgraded successfully.');
expect(vm.$toast.show).toHaveBeenCalledWith('GitLab Runner updated successfully.');
});
});
});
describe('Version', () => {
it('displays a version number if application has been upgraded', () => {
it('displays a version number if application has been updated', () => {
const version = '0.1.45';
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
......@@ -363,15 +361,15 @@ describe('Application Row', () => {
updateSuccessful: true,
version,
});
const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
const updateDetails = vm.$el.querySelector('.js-cluster-application-update-details');
const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
expect(upgradeDetails.innerHTML).toContain('Upgraded');
expect(updateDetails.innerHTML).toContain('Updated');
expect(versionEl).not.toBe(null);
expect(versionEl.innerHTML).toContain(version);
});
it('contains a link to the chart repo if application has been upgraded', () => {
it('contains a link to the chart repo if application has been updated', () => {
const version = '0.1.45';
const chartRepo = 'https://gitlab.com/charts/gitlab-runner';
vm = mountComponent(ApplicationRow, {
......@@ -381,13 +379,13 @@ describe('Application Row', () => {
chartRepo,
version,
});
const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
expect(versionEl.href).toEqual(chartRepo);
expect(versionEl.target).toEqual('_blank');
});
it('does not display a version number if application upgrade failed', () => {
it('does not display a version number if application update failed', () => {
const version = '0.1.45';
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
......@@ -395,10 +393,10 @@ describe('Application Row', () => {
updateFailed: true,
version,
});
const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
const updateDetails = vm.$el.querySelector('.js-cluster-application-update-details');
const versionEl = vm.$el.querySelector('.js-cluster-application-update-version');
expect(upgradeDetails.innerHTML).toContain('failed');
expect(updateDetails.innerHTML).toContain('failed');
expect(versionEl).toBe(null);
});
});
......
......@@ -127,7 +127,7 @@ describe('applicationStateMachine', () => {
describe(`current state is ${UPDATING}`, () => {
it.each`
expectedState | event | effects
${INSTALLED} | ${UPDATED} | ${{ updateSuccessful: true, updateAcknowledged: false }}
${INSTALLED} | ${UPDATED} | ${{ updateSuccessful: true }}
${INSTALLED} | ${UPDATE_ERRORED} | ${{ updateFailed: true }}
`(`transitions to $expectedState on $event event and applies $effects`, data => {
const { expectedState, event, effects } = data;
......
......@@ -85,11 +85,10 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.applications[2].status_reason,
requestReason: null,
version: mockResponseData.applications[2].version,
upgradeAvailable: mockResponseData.applications[2].update_available,
updateAvailable: mockResponseData.applications[2].update_available,
chartRepo: 'https://gitlab.com/charts/gitlab-runner',
installed: false,
installFailed: false,
updateAcknowledged: true,
updateFailed: false,
updateSuccessful: false,
uninstallable: false,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment