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 things
pull/3798/head
Maxime Bajeux 2020-05-08 23:40:49 +02:00 committed by GitHub
parent 7fa73d1147
commit 8046fb0438
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 3 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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,