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) {
|
||||
switch requestPath := request.URL.Path; requestPath {
|
||||
case "/volumes/create":
|
||||
return transport.decorateGenericResourceCreationOperation(request, volumeObjectIdentifier, portainer.VolumeResourceControl)
|
||||
return transport.decorateVolumeResourceCreationOperation(request, volumeObjectIdentifier, portainer.VolumeResourceControl)
|
||||
|
||||
case "/volumes/prune":
|
||||
return transport.administratorOperation(request)
|
||||
|
|
|
@ -2,12 +2,14 @@ package docker
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"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/security"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -87,3 +89,40 @@ func (transport *Transport) volumeInspectOperation(response *http.Response, exec
|
|||
func selectorVolumeLabels(responseObject map[string]interface{}) map[string]interface{} {
|
||||
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',
|
||||
function VolumeFactory($resource, API_ENDPOINT_ENDPOINTS, EndpointProvider, VolumesInterceptor) {
|
||||
'use strict';
|
||||
|
||||
function addVolumeNameToHeader(config) {
|
||||
return config.data.Name;
|
||||
}
|
||||
|
||||
return $resource(
|
||||
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 },
|
||||
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: {
|
||||
method: 'DELETE',
|
||||
transformResponse: genericHandler,
|
||||
|
|
Loading…
Reference in New Issue