Registry component now includes error messages
Includes changes to the Vue container registry component to support the display of an empty message and error message when invalid characters are found in the group, project or branch name. repositories/index.html.haml has been changed to remove the content and place into Vue component.
This commit is contained in:
parent
a7cc29c89f
commit
f01127ad25
12 changed files with 219 additions and 89 deletions
|
@ -3,22 +3,81 @@ import { mapGetters, mapActions } from 'vuex';
|
|||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import store from '../stores';
|
||||
import CollapsibleContainer from './collapsible_container.vue';
|
||||
import SvgMessage from './svg_message.vue';
|
||||
import { s__, sprintf } from '../../locale';
|
||||
|
||||
export default {
|
||||
name: 'RegistryListApp',
|
||||
components: {
|
||||
CollapsibleContainer,
|
||||
GlLoadingIcon,
|
||||
SvgMessage,
|
||||
},
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
characterError: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
helpPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
noContainersImage: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
containersErrorImage: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
repositoryUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
store,
|
||||
computed: {
|
||||
...mapGetters(['isLoading', 'repos']),
|
||||
dockerConnectionErrorText() {
|
||||
return sprintf(
|
||||
s__(`ContainerRegistry|We are having trouble connecting to Docker, which could be due to an
|
||||
issue with your project name or path. For more information, please review the
|
||||
%{docLinkStart}Container Registry documentation%{docLinkEnd}.`),
|
||||
{
|
||||
docLinkStart: `<a href="${this.helpPagePath}#docker-connection-error">`,
|
||||
docLinkEnd: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
introText() {
|
||||
return sprintf(
|
||||
s__(`ContainerRegistry|With the Docker Container Registry integrated into GitLab, every
|
||||
project can have its own space to store its Docker images. Learn more about the
|
||||
%{docLinkStart}Container Registry%{docLinkEnd}.`),
|
||||
{
|
||||
docLinkStart: `<a href="${this.helpPagePath}">`,
|
||||
docLinkEnd: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
noContainerImagesText() {
|
||||
return sprintf(
|
||||
s__(`ContainerRegistry|With the Container Registry, every project can have its own space to
|
||||
store its Docker images. Learn more about the %{docLinkStart}Container Registry%{docLinkEnd}.`),
|
||||
{
|
||||
docLinkStart: `<a href="${this.helpPagePath}">`,
|
||||
docLinkEnd: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.setMainEndpoint(this.endpoint);
|
||||
|
@ -33,20 +92,44 @@ export default {
|
|||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<gl-loading-icon v-if="isLoading" size="md" />
|
||||
<svg-message v-if="characterError" id="invalid-characters" :svg-path="containersErrorImage">
|
||||
<h4>
|
||||
{{ s__('ContainerRegistry|Docker connection error') }}
|
||||
</h4>
|
||||
<p v-html="dockerConnectionErrorText"></p>
|
||||
</svg-message>
|
||||
|
||||
<collapsible-container
|
||||
v-for="item in repos"
|
||||
v-else-if="!isLoading && repos.length"
|
||||
:key="item.id"
|
||||
:repo="item"
|
||||
/>
|
||||
<gl-loading-icon v-else-if="isLoading" size="md" class="prepend-top-16" />
|
||||
|
||||
<p v-else-if="!isLoading && !repos.length">
|
||||
{{
|
||||
__(`No container images stored for this project.
|
||||
Add one by following the instructions above.`)
|
||||
}}
|
||||
</p>
|
||||
<div v-else-if="!isLoading && !characterError && repos.length">
|
||||
<h4>{{ s__('ContainerRegistry|Container Registry') }}</h4>
|
||||
<p v-html="introText"></p>
|
||||
<collapsible-container v-for="item in repos" :key="item.id" :repo="item" />
|
||||
</div>
|
||||
|
||||
<svg-message
|
||||
v-else-if="!isLoading && !characterError && !repos.length"
|
||||
id="no-container-images"
|
||||
:svg-path="noContainersImage"
|
||||
>
|
||||
<h4>
|
||||
{{ s__('ContainerRegistry|There are no container images stored for this project') }}
|
||||
</h4>
|
||||
<p v-html="noContainerImagesText"></p>
|
||||
|
||||
<h5>{{ s__('ContainerRegistry|Quick Start') }}</h5>
|
||||
<p>
|
||||
{{
|
||||
s__(
|
||||
'ContainerRegistry|You can add an image to this registry with the following commands:',
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
docker build -t {{ repositoryUrl }} .
|
||||
docker push {{ repositoryUrl }}
|
||||
</pre>
|
||||
</svg-message>
|
||||
</div>
|
||||
</template>
|
||||
|
|
24
app/assets/javascripts/registry/components/svg_message.vue
Normal file
24
app/assets/javascripts/registry/components/svg_message.vue
Normal file
|
@ -0,0 +1,24 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'RegistrySvgMessage',
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
svgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :id="id" class="empty-state container-message mw-70p">
|
||||
<div class="svg-content">
|
||||
<img :src="svgPath" class="flex-align-self-center" />
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
|
@ -14,12 +14,22 @@ export default () =>
|
|||
const { dataset } = document.querySelector(this.$options.el);
|
||||
return {
|
||||
endpoint: dataset.endpoint,
|
||||
characterError: Boolean(dataset.characterError),
|
||||
helpPagePath: dataset.helpPagePath,
|
||||
noContainersImage: dataset.noContainersImage,
|
||||
containersErrorImage: dataset.containersErrorImage,
|
||||
repositoryUrl: dataset.repositoryUrl,
|
||||
};
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('registry-app', {
|
||||
props: {
|
||||
endpoint: this.endpoint,
|
||||
characterError: this.characterError,
|
||||
helpPagePath: this.helpPagePath,
|
||||
noContainersImage: this.noContainersImage,
|
||||
containersErrorImage: this.containersErrorImage,
|
||||
repositoryUrl: this.repositoryUrl,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
* Container Registry
|
||||
*/
|
||||
|
||||
.container-message {
|
||||
pre {
|
||||
white-space: pre-line;
|
||||
}
|
||||
}
|
||||
|
||||
.container-image {
|
||||
border-bottom: 1px solid $white-normal;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ module Projects
|
|||
repository.save! if repository.has_tags?
|
||||
end
|
||||
end
|
||||
rescue ContainerRegistry::Path::InvalidRegistryPathError
|
||||
@character_error = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,49 +1,9 @@
|
|||
- page_title "Container Registry"
|
||||
|
||||
%section
|
||||
.settings-header
|
||||
%h4
|
||||
= page_title
|
||||
%p
|
||||
= s_('ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images.')
|
||||
%p.append-bottom-0
|
||||
= succeed '.' do
|
||||
= s_('ContainerRegistry|Learn more about')
|
||||
= link_to _('Container Registry'), help_page_path('user/project/container_registry'), target: '_blank'
|
||||
.row.registry-placeholder.prepend-bottom-10
|
||||
.col-lg-12
|
||||
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json) } }
|
||||
|
||||
.row.prepend-top-10
|
||||
.col-lg-12
|
||||
.card
|
||||
.card-header
|
||||
= s_('ContainerRegistry|How to use the Container Registry')
|
||||
.card-body
|
||||
%p
|
||||
- link_token = link_to(_('personal access token'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank')
|
||||
- link_2fa = link_to(_('2FA enabled'), help_page_path('user/profile/account/two_factor_authentication'), target: '_blank')
|
||||
= s_('ContainerRegistry|First log in to GitLab’s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:').html_safe % { link_2fa: link_2fa, link_token: link_token }
|
||||
%pre
|
||||
docker login #{Gitlab.config.registry.host_port}
|
||||
%br
|
||||
%p
|
||||
- deploy_token = link_to(_('deploy token'), help_page_path('user/project/deploy_tokens/index', anchor: 'read-container-registry-images'), target: '_blank')
|
||||
= s_('ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images.').html_safe % { deploy_token: deploy_token }
|
||||
%br
|
||||
%p
|
||||
= s_('ContainerRegistry|Once you log in, you’re free to create and upload a container image using the common %{build} and %{push} commands').html_safe % { build: "<code>build</code>".html_safe, push: "<code>push</code>".html_safe }
|
||||
%pre
|
||||
:plain
|
||||
docker build -t #{escape_once(@project.container_registry_url)} .
|
||||
docker push #{escape_once(@project.container_registry_url)}
|
||||
%hr
|
||||
%h5.prepend-top-default
|
||||
= s_('ContainerRegistry|Use different image names')
|
||||
%p.light
|
||||
= s_('ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:')
|
||||
%pre
|
||||
:plain
|
||||
#{escape_once(@project.container_registry_url)}:tag
|
||||
#{escape_once(@project.container_registry_url)}/optional-image-name:tag
|
||||
#{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag
|
||||
.col-12
|
||||
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json),
|
||||
"help_page_path" => help_page_path('user/project/container_registry'),
|
||||
"no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
|
||||
"containers_error_image" => image_path('illustrations/docker-error-state.svg'),
|
||||
"repository_url" => escape_once(@project.container_registry_url),
|
||||
character_error: @character_error.to_s } }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Updated container registry to display error message when special characters in path. Documentation has also been updated.
|
||||
merge_request: 29616
|
||||
author:
|
||||
type: changed
|
|
@ -689,6 +689,20 @@ You can add a configuration option for backwards compatibility.
|
|||
|
||||
1. Restart the registry for the changes to take affect.
|
||||
|
||||
### Docker connection error
|
||||
|
||||
A Docker connection error can occur when there are special characters in either the group,
|
||||
project or branch name. Special characters can include:
|
||||
|
||||
* Leading underscore
|
||||
* Trailing hyphen/dash
|
||||
* Double hyphen/dash
|
||||
|
||||
To get around this, you can [change the group path](../user/group/index.md#changing-a-groups-path),
|
||||
[change the project path](../user/project/settings/index.md#renaming-a-repository) or change the
|
||||
branch name. Another option is to create a [push rule](../push_rules/push_rules.html) to prevent
|
||||
this at the instance level.
|
||||
|
||||
|
||||
[ce-18239]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18239
|
||||
[docker-insecure-self-signed]: https://docs.docker.com/registry/insecure/#use-self-signed-certificates
|
||||
|
|
|
@ -168,6 +168,19 @@ curl localhost:5001/debug/health
|
|||
curl localhost:5001/debug/vars
|
||||
```
|
||||
|
||||
#### Docker connection error
|
||||
|
||||
A Docker connection error can occur when there are special characters in either the group,
|
||||
project or branch name. Special characters can include:
|
||||
|
||||
* Leading underscore
|
||||
* Trailing hyphen/dash
|
||||
* Double hyphen/dash
|
||||
|
||||
To get around this, you can [change the group path](../group/index.md#changing-a-groups-path),
|
||||
[change the project path](../project/settings/index.md#renaming-a-repository) or chanage the branch
|
||||
name.
|
||||
|
||||
### Advanced Troubleshooting
|
||||
|
||||
>**NOTE:** The following section is only recommended for experts.
|
||||
|
|
|
@ -348,9 +348,6 @@ msgstr ""
|
|||
msgid "2FA"
|
||||
msgstr ""
|
||||
|
||||
msgid "2FA enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "2FADevice|Registered On"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2943,25 +2940,19 @@ msgstr ""
|
|||
msgid "Container registry images"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|First log in to GitLab’s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
|
||||
msgid "ContainerRegistry|Container Registry"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|How to use the Container Registry"
|
||||
msgid "ContainerRegistry|Docker connection error"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Last Updated"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Learn more about"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|No tags in Container Registry for this container image."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Once you log in, you’re free to create and upload a container image using the common %{build} and %{push} commands"
|
||||
msgid "ContainerRegistry|Quick Start"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Remove image"
|
||||
|
@ -2982,10 +2973,16 @@ msgstr ""
|
|||
msgid "ContainerRegistry|Tag ID"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|Use different image names"
|
||||
msgid "ContainerRegistry|There are no container images stored for this project"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
|
||||
msgid "ContainerRegistry|We are having trouble connecting to Docker, which could be due to an issue with your project name or path. For more information, please review the %{docLinkStart}Container Registry documentation%{docLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Learn more about the %{docLinkStart}Container Registry%{docLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images. Learn more about the %{docLinkStart}Container Registry%{docLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|You are about to delete the image <b>%{title}</b>. This will delete the image and all tags pointing to this image."
|
||||
|
@ -2994,7 +2991,7 @@ msgstr ""
|
|||
msgid "ContainerRegistry|You are about to remove repository <b>%{title}</b>. Once you confirm, this repository will be permanently deleted."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
|
||||
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contents of .gitlab-ci.yml"
|
||||
|
@ -6750,9 +6747,6 @@ msgstr ""
|
|||
msgid "No connection could be made to a Gitaly Server, please check your logs!"
|
||||
msgstr ""
|
||||
|
||||
msgid "No container images stored for this project. Add one by following the instructions above."
|
||||
msgstr ""
|
||||
|
||||
msgid "No contributions"
|
||||
msgstr ""
|
||||
|
||||
|
@ -12450,9 +12444,6 @@ msgstr[1] ""
|
|||
msgid "deleted"
|
||||
msgstr ""
|
||||
|
||||
msgid "deploy token"
|
||||
msgstr ""
|
||||
|
||||
msgid "detached"
|
||||
msgstr ""
|
||||
|
||||
|
@ -12851,9 +12842,6 @@ msgstr[1] ""
|
|||
msgid "password"
|
||||
msgstr ""
|
||||
|
||||
msgid "personal access token"
|
||||
msgstr ""
|
||||
|
||||
msgid "private"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ describe "Container Registry", :js do
|
|||
it 'user visits container registry main page' do
|
||||
visit_container_registry
|
||||
|
||||
expect(page).to have_content 'No container images'
|
||||
expect(page).to have_content 'no container images'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,6 +8,13 @@ import { reposServerResponse } from '../mock_data';
|
|||
|
||||
describe('Registry List', () => {
|
||||
const Component = Vue.extend(registry);
|
||||
const props = {
|
||||
endpoint: `${TEST_HOST}/foo`,
|
||||
helpPagePath: 'foo',
|
||||
noContainersImage: 'foo',
|
||||
containersErrorImage: 'foo',
|
||||
repositoryUrl: 'foo',
|
||||
};
|
||||
let vm;
|
||||
let mock;
|
||||
|
||||
|
@ -24,7 +31,7 @@ describe('Registry List', () => {
|
|||
beforeEach(() => {
|
||||
mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, reposServerResponse);
|
||||
|
||||
vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` });
|
||||
vm = mountComponent(Component, { ...props });
|
||||
});
|
||||
|
||||
it('should render a list of repos', done => {
|
||||
|
@ -72,7 +79,7 @@ describe('Registry List', () => {
|
|||
beforeEach(() => {
|
||||
mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, []);
|
||||
|
||||
vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` });
|
||||
vm = mountComponent(Component, { ...props });
|
||||
});
|
||||
|
||||
it('should render empty message', done => {
|
||||
|
@ -83,7 +90,7 @@ describe('Registry List', () => {
|
|||
.textContent.trim()
|
||||
.replace(/[\r\n]+/g, ' '),
|
||||
).toEqual(
|
||||
'No container images stored for this project. Add one by following the instructions above.',
|
||||
'With the Container Registry, every project can have its own space to store its Docker images. Learn more about the Container Registry.',
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
|
@ -94,7 +101,7 @@ describe('Registry List', () => {
|
|||
beforeEach(() => {
|
||||
mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, []);
|
||||
|
||||
vm = mountComponent(Component, { endpoint: `${TEST_HOST}/foo` });
|
||||
vm = mountComponent(Component, { ...props });
|
||||
});
|
||||
|
||||
it('should render a loading spinner', done => {
|
||||
|
@ -104,4 +111,22 @@ describe('Registry List', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid characters in path', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(`${TEST_HOST}/foo`).replyOnce(200, []);
|
||||
|
||||
vm = mountComponent(Component, {
|
||||
...props,
|
||||
characterError: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should render invalid characters error message', done => {
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelector('.container-message')).not.toBe(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue