Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
b87da5e6
Commit
b87da5e6
authored
Apr 18, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
38a67440
070285d4
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
140 additions
and
58 deletions
+140
-58
app/assets/javascripts/clusters/components/application_row.vue
...ssets/javascripts/clusters/components/application_row.vue
+34
-22
app/assets/javascripts/clusters/components/applications.vue
app/assets/javascripts/clusters/components/applications.vue
+7
-0
app/assets/javascripts/clusters/components/uninstall_application_button.vue
...ipts/clusters/components/uninstall_application_button.vue
+14
-0
app/assets/javascripts/clusters/constants.js
app/assets/javascripts/clusters/constants.js
+15
-0
app/assets/javascripts/clusters/stores/clusters_store.js
app/assets/javascripts/clusters/stores/clusters_store.js
+26
-29
spec/frontend/clusters/components/application_row_spec.js
spec/frontend/clusters/components/application_row_spec.js
+22
-6
spec/frontend/clusters/stores/clusters_store_spec.js
spec/frontend/clusters/stores/clusters_store_spec.js
+22
-1
No files found.
app/assets/javascripts/clusters/components/application_row.vue
View file @
b87da5e6
...
...
@@ -6,6 +6,8 @@ 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
'
;
import
UninstallApplicationButton
from
'
./uninstall_application_button.vue
'
;
import
{
APPLICATION_STATUS
,
REQUEST_SUBMITTED
,
...
...
@@ -19,6 +21,7 @@ export default {
identicon
,
TimeagoTooltip
,
GlLink
,
UninstallApplicationButton
,
},
props
:
{
id
:
{
...
...
@@ -47,6 +50,11 @@ export default {
required
:
false
,
default
:
false
,
},
uninstallable
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
status
:
{
type
:
String
,
required
:
false
,
...
...
@@ -63,6 +71,11 @@ export default {
type
:
String
,
required
:
false
,
},
installed
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
version
:
{
type
:
String
,
required
:
false
,
...
...
@@ -92,15 +105,7 @@ export default {
return
(
this
.
status
===
APPLICATION_STATUS
.
SCHEDULED
||
this
.
status
===
APPLICATION_STATUS
.
INSTALLING
||
(
this
.
requestStatus
===
REQUEST_SUBMITTED
&&
!
this
.
statusReason
&&
!
this
.
isInstalled
)
);
},
isInstalled
()
{
return
(
this
.
status
===
APPLICATION_STATUS
.
INSTALLED
||
this
.
status
===
APPLICATION_STATUS
.
UPDATED
||
this
.
status
===
APPLICATION_STATUS
.
UPDATING
||
this
.
status
===
APPLICATION_STATUS
.
UPDATE_ERRORED
(
this
.
requestStatus
===
REQUEST_SUBMITTED
&&
!
this
.
statusReason
&&
!
this
.
installed
)
);
},
canInstall
()
{
...
...
@@ -125,6 +130,12 @@ export default {
rowJsClass
()
{
return
`js-cluster-application-row-
${
this
.
id
}
`
;
},
displayUninstallButton
()
{
return
this
.
installed
&&
this
.
uninstallable
;
},
displayInstallButton
()
{
return
!
this
.
installed
||
!
this
.
uninstallable
;
},
installButtonLoading
()
{
return
!
this
.
status
||
this
.
status
===
APPLICATION_STATUS
.
SCHEDULED
||
this
.
isInstalling
;
},
...
...
@@ -145,7 +156,7 @@ export default {
label
=
s__
(
'
ClusterIntegration|Install
'
);
}
else
if
(
this
.
isInstalling
)
{
label
=
s__
(
'
ClusterIntegration|Installing
'
);
}
else
if
(
this
.
i
sI
nstalled
)
{
}
else
if
(
this
.
installed
)
{
label
=
s__
(
'
ClusterIntegration|Installed
'
);
}
...
...
@@ -257,7 +268,7 @@ export default {
<div
:class=
"[
rowJsClass,
i
sI
nstalled && 'cluster-application-installed',
installed && 'cluster-application-installed',
disabled && 'cluster-application-disabled',
]"
class=
"cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span"
...
...
@@ -280,10 +291,9 @@ export default {
target=
"blank"
rel=
"noopener noreferrer"
class=
"js-cluster-application-title"
>
{{
title
}}
</a
>
{{
title
}}
</a>
<span
v-else
class=
"js-cluster-application-title"
>
{{
title
}}
</span>
<span
v-else
class=
"js-cluster-application-title"
>
{{
title
}}
</span>
</strong>
<slot
name=
"description"
></slot>
<div
...
...
@@ -308,17 +318,15 @@ export default {
class=
"form-text text-muted label p-0 js-cluster-application-upgrade-details"
>
{{
versionLabel
}}
<span
v-if=
"upgradeSuccessful"
>
to
</span>
<span
v-if=
"upgradeSuccessful"
>
to
</span>
<gl-link
v-if=
"upgradeSuccessful"
:href=
"chartRepo"
target=
"_blank"
class=
"js-cluster-application-upgrade-version"
>
chart v
{{
version
}}
</gl-link
>
chart v
{{
version
}}
</gl-link>
</div>
<div
...
...
@@ -333,7 +341,6 @@ export default {
class=
"bs-callout bs-callout-success cluster-application-banner mt-2 mb-0 p-0 pl-3"
>
{{
upgradeSuccessDescription
}}
<button
class=
"close cluster-application-banner-close"
@
click=
"dismissUpgradeSuccess"
>
×
</button>
...
...
@@ -354,18 +361,23 @@ export default {
role="gridcell"
>
<div
v-if=
"showManageButton"
class=
"btn-group table-action-buttons"
>
<a
:href=
"manageLink"
:class=
"
{ disabled: disabled }" class="btn">
{{
manageButtonLabel
}}
</a>
<a
:href=
"manageLink"
:class=
"
{ disabled: disabled }" class="btn">
{{
manageButtonLabel
}}
</a>
</div>
<div
class=
"btn-group table-action-buttons"
>
<loading-button
v-if=
"displayInstallButton"
:loading=
"installButtonLoading"
:disabled=
"disabled || installButtonDisabled"
:label=
"installButtonLabel"
class=
"js-cluster-application-install-button"
@
click=
"installClicked"
/>
<uninstall-application-button
v-if=
"displayUninstallButton"
class=
"js-cluster-application-uninstall-button"
/>
</div>
</div>
</div>
...
...
app/assets/javascripts/clusters/components/applications.vue
View file @
b87da5e6
...
...
@@ -238,6 +238,7 @@ export default {
:status-reason=
"applications.helm.statusReason"
:request-status=
"applications.helm.requestStatus"
:request-reason=
"applications.helm.requestReason"
:installed=
"applications.helm.installed"
class=
"rounded-top"
title-link=
"https://docs.helm.sh/"
>
...
...
@@ -265,6 +266,7 @@ export default {
:status-reason=
"applications.ingress.statusReason"
:request-status=
"applications.ingress.requestStatus"
:request-reason=
"applications.ingress.requestReason"
:installed=
"applications.ingress.installed"
:disabled=
"!helmInstalled"
title-link=
"https://kubernetes.io/docs/concepts/services-networking/ingress/"
>
...
...
@@ -341,6 +343,7 @@ export default {
:status-reason=
"applications.cert_manager.statusReason"
:request-status=
"applications.cert_manager.requestStatus"
:request-reason=
"applications.cert_manager.requestReason"
:installed=
"applications.cert_manager.installed"
:install-application-request-params=
"{ email: applications.cert_manager.email }"
:disabled=
"!helmInstalled"
title-link=
"https://cert-manager.readthedocs.io/en/latest/#"
...
...
@@ -387,6 +390,7 @@ export default {
:status-reason=
"applications.prometheus.statusReason"
:request-status=
"applications.prometheus.requestStatus"
:request-reason=
"applications.prometheus.requestReason"
:installed=
"applications.prometheus.installed"
:disabled=
"!helmInstalled"
title-link=
"https://prometheus.io/docs/introduction/overview/"
>
...
...
@@ -403,6 +407,7 @@ export default {
:version=
"applications.runner.version"
:chart-repo=
"applications.runner.chartRepo"
:upgrade-available=
"applications.runner.upgradeAvailable"
:installed=
"applications.runner.installed"
:disabled=
"!helmInstalled"
title-link=
"https://docs.gitlab.com/runner/"
>
...
...
@@ -424,6 +429,7 @@ export default {
:status-reason=
"applications.jupyter.statusReason"
:request-status=
"applications.jupyter.requestStatus"
:request-reason=
"applications.jupyter.requestReason"
:installed=
"applications.jupyter.installed"
:install-application-request-params=
"{ hostname: applications.jupyter.hostname }"
:disabled=
"!helmInstalled"
title-link=
"https://jupyterhub.readthedocs.io/en/stable/"
...
...
@@ -483,6 +489,7 @@ export default {
:status-reason=
"applications.knative.statusReason"
:request-status=
"applications.knative.requestStatus"
:request-reason=
"applications.knative.requestReason"
:installed=
"applications.knative.installed"
:install-application-request-params=
"{ hostname: applications.knative.hostname }"
:disabled=
"!helmInstalled"
title-link=
"https://github.com/knative/docs"
...
...
app/assets/javascripts/clusters/components/uninstall_application_button.vue
0 → 100644
View file @
b87da5e6
<
script
>
// TODO: Implement loading button component
import
LoadingButton
from
'
~/vue_shared/components/loading_button.vue
'
;
export
default
{
components
:
{
LoadingButton
,
},
};
</
script
>
<
template
>
<loading-button
@
click=
"$emit('click')"
/>
</
template
>
app/assets/javascripts/clusters/constants.js
View file @
b87da5e6
...
...
@@ -15,9 +15,24 @@ export const APPLICATION_STATUS = {
UPDATING
:
'
updating
'
,
UPDATED
:
'
updated
'
,
UPDATE_ERRORED
:
'
update_errored
'
,
UNINSTALLING
:
'
uninstalling
'
,
UNINSTALL_ERRORED
:
'
uninstall_errored
'
,
ERROR
:
'
errored
'
,
};
/*
* The application cannot be in any of the following states without
* not being installed.
*/
export
const
APPLICATION_INSTALLED_STATUSES
=
[
APPLICATION_STATUS
.
INSTALLED
,
APPLICATION_STATUS
.
UPDATING
,
APPLICATION_STATUS
.
UPDATED
,
APPLICATION_STATUS
.
UPDATE_ERRORED
,
APPLICATION_STATUS
.
UNINSTALLING
,
APPLICATION_STATUS
.
UNINSTALL_ERRORED
,
];
// These are only used client-side
export
const
REQUEST_SUBMITTED
=
'
request-submitted
'
;
export
const
REQUEST_FAILURE
=
'
request-failure
'
;
...
...
app/assets/javascripts/clusters/stores/clusters_store.js
View file @
b87da5e6
import
{
s__
}
from
'
../../locale
'
;
import
{
parseBoolean
}
from
'
../../lib/utils/common_utils
'
;
import
{
INGRESS
,
JUPYTER
,
KNATIVE
,
CERT_MANAGER
,
RUNNER
}
from
'
../constants
'
;
import
{
INGRESS
,
JUPYTER
,
KNATIVE
,
CERT_MANAGER
,
RUNNER
,
APPLICATION_INSTALLED_STATUSES
,
}
from
'
../constants
'
;
const
isApplicationInstalled
=
appStatus
=>
APPLICATION_INSTALLED_STATUSES
.
includes
(
appStatus
);
const
applicationInitialState
=
{
status
:
null
,
statusReason
:
null
,
requestReason
:
null
,
requestStatus
:
null
,
installed
:
false
,
};
export
default
class
ClusterStore
{
constructor
()
{
...
...
@@ -12,60 +29,39 @@ export default class ClusterStore {
statusReason
:
null
,
applications
:
{
helm
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|Helm Tiller
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
},
ingress
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|Ingress
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
externalIp
:
null
,
externalHostname
:
null
,
},
cert_manager
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|Cert-Manager
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
email
:
null
,
},
runner
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|GitLab Runner
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
version
:
null
,
chartRepo
:
'
https://gitlab.com/charts/gitlab-runner
'
,
upgradeAvailable
:
null
,
},
prometheus
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|Prometheus
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
},
jupyter
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|JupyterHub
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
hostname
:
null
,
},
knative
:
{
...
applicationInitialState
,
title
:
s__
(
'
ClusterIntegration|Knative
'
),
status
:
null
,
statusReason
:
null
,
requestStatus
:
null
,
requestReason
:
null
,
hostname
:
null
,
isEditingHostName
:
false
,
externalIp
:
null
,
...
...
@@ -118,6 +114,7 @@ export default class ClusterStore {
...(
this
.
state
.
applications
[
appId
]
||
{}),
status
,
statusReason
,
installed
:
isApplicationInstalled
(
status
),
};
if
(
appId
===
INGRESS
)
{
...
...
spec/frontend/clusters/components/application_row_spec.js
View file @
b87da5e6
...
...
@@ -114,10 +114,12 @@ describe('Application Row', () => {
expect
(
vm
.
installButtonDisabled
).
toEqual
(
true
);
});
it
(
'
has disabled "Installed" when
APPLICATION_STATUS.INSTALLED
'
,
()
=>
{
it
(
'
has disabled "Installed" when
application is installed and not uninstallable
'
,
()
=>
{
vm
=
mountComponent
(
ApplicationRow
,
{
...
DEFAULT_APPLICATION_STATE
,
status
:
APPLICATION_STATUS
.
INSTALLED
,
installed
:
true
,
uninstallable
:
false
,
});
expect
(
vm
.
installButtonLabel
).
toEqual
(
'
Installed
'
);
...
...
@@ -125,15 +127,16 @@ describe('Application Row', () => {
expect
(
vm
.
installButtonDisabled
).
toEqual
(
true
);
});
it
(
'
h
as disabled "Installed" when APPLICATION_STATUS.UPDATING
'
,
()
=>
{
it
(
'
h
ides when application is installed and uninstallable
'
,
()
=>
{
vm
=
mountComponent
(
ApplicationRow
,
{
...
DEFAULT_APPLICATION_STATE
,
status
:
APPLICATION_STATUS
.
UPDATING
,
status
:
APPLICATION_STATUS
.
INSTALLED
,
installed
:
true
,
uninstallable
:
true
,
});
const
installBtn
=
vm
.
$el
.
querySelector
(
'
.js-cluster-application-install-button
'
);
expect
(
vm
.
installButtonLabel
).
toEqual
(
'
Installed
'
);
expect
(
vm
.
installButtonLoading
).
toEqual
(
false
);
expect
(
vm
.
installButtonDisabled
).
toEqual
(
true
);
expect
(
installBtn
).
toBe
(
null
);
});
it
(
'
has enabled "Install" when APPLICATION_STATUS.ERROR
'
,
()
=>
{
...
...
@@ -208,6 +211,19 @@ describe('Application Row', () => {
});
});
describe
(
'
Uninstall button
'
,
()
=>
{
it
(
'
displays button when app is installed and uninstallable
'
,
()
=>
{
vm
=
mountComponent
(
ApplicationRow
,
{
...
DEFAULT_APPLICATION_STATE
,
installed
:
true
,
uninstallable
:
true
,
});
const
uninstallButton
=
vm
.
$el
.
querySelector
(
'
.js-cluster-application-uninstall-button
'
);
expect
(
uninstallButton
).
toBeTruthy
();
});
});
describe
(
'
Upgrade button
'
,
()
=>
{
it
(
'
has indeterminate state on page load
'
,
()
=>
{
vm
=
mountComponent
(
ApplicationRow
,
{
...
...
spec/frontend/clusters/stores/clusters_store_spec.js
View file @
b87da5e6
import
ClustersStore
from
'
~/clusters/stores/clusters_store
'
;
import
{
APPLICATION_
STATUS
}
from
'
~/clusters/constants
'
;
import
{
APPLICATION_
INSTALLED_STATUSES
,
APPLICATION_STATUS
,
RUNNER
}
from
'
~/clusters/constants
'
;
import
{
CLUSTERS_MOCK_DATA
}
from
'
../services/mock_data
'
;
describe
(
'
Clusters Store
'
,
()
=>
{
...
...
@@ -70,6 +70,7 @@ describe('Clusters Store', () => {
statusReason
:
mockResponseData
.
applications
[
0
].
status_reason
,
requestStatus
:
null
,
requestReason
:
null
,
installed
:
false
,
},
ingress
:
{
title
:
'
Ingress
'
,
...
...
@@ -79,6 +80,7 @@ describe('Clusters Store', () => {
requestReason
:
null
,
externalIp
:
null
,
externalHostname
:
null
,
installed
:
false
,
},
runner
:
{
title
:
'
GitLab Runner
'
,
...
...
@@ -89,6 +91,7 @@ describe('Clusters Store', () => {
version
:
mockResponseData
.
applications
[
2
].
version
,
upgradeAvailable
:
mockResponseData
.
applications
[
2
].
update_available
,
chartRepo
:
'
https://gitlab.com/charts/gitlab-runner
'
,
installed
:
false
,
},
prometheus
:
{
title
:
'
Prometheus
'
,
...
...
@@ -96,6 +99,7 @@ describe('Clusters Store', () => {
statusReason
:
mockResponseData
.
applications
[
3
].
status_reason
,
requestStatus
:
null
,
requestReason
:
null
,
installed
:
false
,
},
jupyter
:
{
title
:
'
JupyterHub
'
,
...
...
@@ -104,6 +108,7 @@ describe('Clusters Store', () => {
requestStatus
:
null
,
requestReason
:
null
,
hostname
:
''
,
installed
:
false
,
},
knative
:
{
title
:
'
Knative
'
,
...
...
@@ -115,6 +120,7 @@ describe('Clusters Store', () => {
isEditingHostName
:
false
,
externalIp
:
null
,
externalHostname
:
null
,
installed
:
false
,
},
cert_manager
:
{
title
:
'
Cert-Manager
'
,
...
...
@@ -123,11 +129,26 @@ describe('Clusters Store', () => {
requestStatus
:
null
,
requestReason
:
null
,
email
:
mockResponseData
.
applications
[
6
].
email
,
installed
:
false
,
},
},
});
});
describe
.
each
(
APPLICATION_INSTALLED_STATUSES
)(
'
given the current app status is %s
'
,
()
=>
{
it
(
'
marks application as installed
'
,
()
=>
{
const
mockResponseData
=
CLUSTERS_MOCK_DATA
.
GET
[
'
/gitlab-org/gitlab-shell/clusters/2/status.json
'
].
data
;
const
runnerAppIndex
=
2
;
mockResponseData
.
applications
[
runnerAppIndex
].
status
=
APPLICATION_STATUS
.
INSTALLED
;
store
.
updateStateFromServer
(
mockResponseData
);
expect
(
store
.
state
.
applications
[
RUNNER
].
installed
).
toBe
(
true
);
});
});
it
(
'
sets default hostname for jupyter when ingress has a ip address
'
,
()
=>
{
const
mockResponseData
=
CLUSTERS_MOCK_DATA
.
GET
[
'
/gitlab-org/gitlab-shell/clusters/2/status.json
'
].
data
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment