mirror of https://github.com/portainer/portainer
fix(volumes): add unicity check on volumes (#3779)
* fix(volumes): add unicity check on volumes * fix(volumes): add header to volume creation request * fix(volumes): change few thingspull/3798/head
parent
7fa73d1147
commit
8046fb0438
|
@ -273,7 +273,7 @@ func (transport *Transport) proxyServiceRequest(request *http.Request) (*http.Re
|
||||||
func (transport *Transport) proxyVolumeRequest(request *http.Request) (*http.Response, error) {
|
func (transport *Transport) proxyVolumeRequest(request *http.Request) (*http.Response, error) {
|
||||||
switch requestPath := request.URL.Path; requestPath {
|
switch requestPath := request.URL.Path; requestPath {
|
||||||
case "/volumes/create":
|
case "/volumes/create":
|
||||||
return transport.decorateGenericResourceCreationOperation(request, volumeObjectIdentifier, portainer.VolumeResourceControl)
|
return transport.decorateVolumeResourceCreationOperation(request, volumeObjectIdentifier, portainer.VolumeResourceControl)
|
||||||
|
|
||||||
case "/volumes/prune":
|
case "/volumes/prune":
|
||||||
return transport.administratorOperation(request)
|
return transport.administratorOperation(request)
|
||||||
|
|
|
@ -2,12 +2,14 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
|
||||||
"github.com/portainer/portainer/api"
|
portainer "github.com/portainer/portainer/api"
|
||||||
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
|
||||||
|
"github.com/portainer/portainer/api/http/security"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -87,3 +89,40 @@ func (transport *Transport) volumeInspectOperation(response *http.Response, exec
|
||||||
func selectorVolumeLabels(responseObject map[string]interface{}) map[string]interface{} {
|
func selectorVolumeLabels(responseObject map[string]interface{}) map[string]interface{} {
|
||||||
return responseutils.GetJSONObject(responseObject, "Labels")
|
return responseutils.GetJSONObject(responseObject, "Labels")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (transport *Transport) decorateVolumeResourceCreationOperation(request *http.Request, resourceIdentifierAttribute string, resourceType portainer.ResourceControlType) (*http.Response, error) {
|
||||||
|
tokenData, err := security.RetrieveTokenData(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
volumeID := request.Header.Get("X-Portainer-VolumeName")
|
||||||
|
|
||||||
|
if volumeID != "" {
|
||||||
|
cli := transport.dockerClient
|
||||||
|
agentTargetHeader := request.Header.Get(portainer.PortainerAgentTargetHeader)
|
||||||
|
if agentTargetHeader != "" {
|
||||||
|
dockerClient, err := transport.dockerClientFactory.CreateClient(transport.endpoint, agentTargetHeader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer dockerClient.Close()
|
||||||
|
cli = dockerClient
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = cli.VolumeInspect(context.Background(), volumeID)
|
||||||
|
if err == nil {
|
||||||
|
return nil, errors.New("a volume with the same name already exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := transport.executeDockerRequest(request)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode == http.StatusCreated && volumeID != "" {
|
||||||
|
err = transport.decorateGenericResourceCreationResponse(response, resourceIdentifierAttribute, resourceType, tokenData.ID)
|
||||||
|
}
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@ angular.module('portainer.docker').factory('Volume', [
|
||||||
'VolumesInterceptor',
|
'VolumesInterceptor',
|
||||||
function VolumeFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider, VolumesInterceptor) {
|
function VolumeFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider, VolumesInterceptor) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
function addVolumeNameToHeader(config) {
|
||||||
|
return config.data.Name;
|
||||||
|
}
|
||||||
|
|
||||||
return $resource(
|
return $resource(
|
||||||
API_ENDPOINT_ENDPOINTS + '/:endpointId/docker/volumes/:id/:action',
|
API_ENDPOINT_ENDPOINTS + '/:endpointId/docker/volumes/:id/:action',
|
||||||
{
|
{
|
||||||
|
@ -15,7 +20,13 @@ angular.module('portainer.docker').factory('Volume', [
|
||||||
{
|
{
|
||||||
query: { method: 'GET', interceptor: VolumesInterceptor, timeout: 15000 },
|
query: { method: 'GET', interceptor: VolumesInterceptor, timeout: 15000 },
|
||||||
get: { method: 'GET', params: { id: '@id' } },
|
get: { method: 'GET', params: { id: '@id' } },
|
||||||
create: { method: 'POST', params: { action: 'create' }, transformResponse: genericHandler, ignoreLoadingBar: true },
|
create: {
|
||||||
|
method: 'POST',
|
||||||
|
params: { action: 'create' },
|
||||||
|
transformResponse: genericHandler,
|
||||||
|
ignoreLoadingBar: true,
|
||||||
|
headers: { 'X-Portainer-VolumeName': addVolumeNameToHeader },
|
||||||
|
},
|
||||||
remove: {
|
remove: {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
transformResponse: genericHandler,
|
transformResponse: genericHandler,
|
||||||
|
|
Loading…
Reference in New Issue