Commit 58786e20 authored by Phil Hughes's avatar Phil Hughes

Merge branch...

Merge branch '45104-special-characters-in-project-name-path-prevent-users-from-using-the-container-registry' into 'master'

Resolve "Special characters in project name/path prevent users from using the container registry"

Closes #62770 and #45104

See merge request gitlab-org/gitlab-ce!29616
parents a7cc29c8 f01127ad
......@@ -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>
<gl-loading-icon v-else-if="isLoading" size="md" class="prepend-top-16" />
<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>
<collapsible-container
v-for="item in repos"
v-else-if="!isLoading && repos.length"
:key="item.id"
:repo="item"
/>
<h5>{{ s__('ContainerRegistry|Quick Start') }}</h5>
<p>
{{
s__(
'ContainerRegistry|You can add an image to this registry with the following commands:',
)
}}
</p>
<p v-else-if="!isLoading && !repos.length">
{{
__(`No container images stored for this project.
Add one by following the instructions above.`)
}}
</p>
<pre>
docker build -t {{ repositoryUrl }} .
docker push {{ repositoryUrl }}
</pre>
</svg-message>
</div>
</template>
<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
......
- 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&rsquo;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&rsquo;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 } }
---
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&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
msgstr ""
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
msgid "ContainerRegistry|Container Registry"
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&rsquo;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|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 Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
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();
});
});
});
});
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