1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

feat(stacks): scope stack names to endpoint (#4520)

* refactor(stack): create unique name function

* refactor(stack): change stack resource control id

* feat(stacks): validate stack unique name in endpoint

* feat(stacks): prevent name collision with external stacks

* refactor(stacks): move resource id util

* refactor(stacks): supply resource id util with name and endpoint

* fix(docker): calculate swarm resource id

* feat(stack): prevent migration if stack name already exist

* feat(authorization): use stackutils
This commit is contained in:
Chaim Lev-Ari 2021-02-23 22:18:05 +02:00 committed by GitHub
parent a62e0496de
commit 86ad1c6af1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 245 additions and 99 deletions

View file

@ -5,10 +5,12 @@ import (
"net/http"
"strings"
"github.com/portainer/portainer/api/internal/stackutils"
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
"github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api"
portainer "github.com/portainer/portainer/api"
)
const (
@ -117,17 +119,17 @@ func (transport *Transport) getInheritedResourceControlFromServiceOrStack(resour
switch resourceType {
case portainer.ContainerResourceControl:
return getInheritedResourceControlFromContainerLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromContainerLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
case portainer.NetworkResourceControl:
return getInheritedResourceControlFromNetworkLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromNetworkLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
case portainer.VolumeResourceControl:
return getInheritedResourceControlFromVolumeLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromVolumeLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
case portainer.ServiceResourceControl:
return getInheritedResourceControlFromServiceLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromServiceLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
case portainer.ConfigResourceControl:
return getInheritedResourceControlFromConfigLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromConfigLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
case portainer.SecretResourceControl:
return getInheritedResourceControlFromSecretLabels(client, resourceIdentifier, resourceControls)
return getInheritedResourceControlFromSecretLabels(client, transport.endpoint.ID, resourceIdentifier, resourceControls)
}
return nil, nil
@ -273,8 +275,9 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
}
if resourceLabelsObject[resourceLabelForDockerSwarmStackName] != nil {
inheritedSwarmStackIdentifier := resourceLabelsObject[resourceLabelForDockerSwarmStackName].(string)
resourceControl = authorization.GetResourceControlByResourceIDAndType(inheritedSwarmStackIdentifier, portainer.StackResourceControl, resourceControls)
stackName := resourceLabelsObject[resourceLabelForDockerSwarmStackName].(string)
stackResourceID := stackutils.ResourceControlID(transport.endpoint.ID, stackName)
resourceControl = authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls)
if resourceControl != nil {
return resourceControl, nil
@ -282,8 +285,9 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
}
if resourceLabelsObject[resourceLabelForDockerComposeStackName] != nil {
inheritedComposeStackIdentifier := resourceLabelsObject[resourceLabelForDockerComposeStackName].(string)
resourceControl = authorization.GetResourceControlByResourceIDAndType(inheritedComposeStackIdentifier, portainer.StackResourceControl, resourceControls)
stackName := resourceLabelsObject[resourceLabelForDockerComposeStackName].(string)
stackResourceID := stackutils.ResourceControlID(transport.endpoint.ID, stackName)
resourceControl = authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls)
if resourceControl != nil {
return resourceControl, nil
@ -296,6 +300,20 @@ func (transport *Transport) findResourceControl(resourceIdentifier string, resou
return nil, nil
}
func getStackResourceIDFromLabels(resourceLabelsObject map[string]string, endpointID portainer.EndpointID) string {
if resourceLabelsObject[resourceLabelForDockerSwarmStackName] != "" {
stackName := resourceLabelsObject[resourceLabelForDockerSwarmStackName]
return stackutils.ResourceControlID(endpointID, stackName)
}
if resourceLabelsObject[resourceLabelForDockerComposeStackName] != "" {
stackName := resourceLabelsObject[resourceLabelForDockerComposeStackName]
return stackutils.ResourceControlID(endpointID, stackName)
}
return ""
}
func decorateObject(object map[string]interface{}, resourceControl *portainer.ResourceControl) map[string]interface{} {
if object["Portainer"] == nil {
object["Portainer"] = make(map[string]interface{})

View file

@ -15,15 +15,15 @@ const (
configObjectIdentifier = "ID"
)
func getInheritedResourceControlFromConfigLabels(dockerClient *client.Client, configID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromConfigLabels(dockerClient *client.Client, endpointID portainer.EndpointID, configID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
config, _, err := dockerClient.ConfigInspectWithRaw(context.Background(), configID)
if err != nil {
return nil, err
}
swarmStackName := config.Spec.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(config.Spec.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil

View file

@ -19,7 +19,7 @@ const (
containerObjectIdentifier = "Id"
)
func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client, containerID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client, endpointID portainer.EndpointID, containerID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
container, err := dockerClient.ContainerInspect(context.Background(), containerID)
if err != nil {
return nil, err
@ -33,14 +33,9 @@ func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client,
}
}
swarmStackName := container.Config.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
}
composeStackName := container.Config.Labels[resourceLabelForDockerComposeStackName]
if composeStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(composeStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(container.Config.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil

View file

@ -4,11 +4,12 @@ import (
"context"
"net/http"
portainer "github.com/portainer/portainer/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy/factory/responseutils"
"github.com/portainer/portainer/api/internal/authorization"
)
@ -18,15 +19,15 @@ const (
networkObjectName = "Name"
)
func getInheritedResourceControlFromNetworkLabels(dockerClient *client.Client, networkID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromNetworkLabels(dockerClient *client.Client, endpointID portainer.EndpointID, networkID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
network, err := dockerClient.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
if err != nil {
return nil, err
}
swarmStackName := network.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(network.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil

View file

@ -15,15 +15,15 @@ const (
secretObjectIdentifier = "ID"
)
func getInheritedResourceControlFromSecretLabels(dockerClient *client.Client, secretID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromSecretLabels(dockerClient *client.Client, endpointID portainer.EndpointID, secretID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
secret, _, err := dockerClient.SecretInspectWithRaw(context.Background(), secretID)
if err != nil {
return nil, err
}
swarmStackName := secret.Spec.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(secret.Spec.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil

View file

@ -20,15 +20,15 @@ const (
serviceObjectIdentifier = "ID"
)
func getInheritedResourceControlFromServiceLabels(dockerClient *client.Client, serviceID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromServiceLabels(dockerClient *client.Client, endpointID portainer.EndpointID, serviceID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
service, _, err := dockerClient.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
if err != nil {
return nil, err
}
swarmStackName := service.Spec.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(service.Spec.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil

View file

@ -8,7 +8,7 @@ import (
"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"
"github.com/portainer/portainer/api/internal/authorization"
@ -18,15 +18,15 @@ const (
volumeObjectIdentifier = "ID"
)
func getInheritedResourceControlFromVolumeLabels(dockerClient *client.Client, volumeID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
func getInheritedResourceControlFromVolumeLabels(dockerClient *client.Client, endpointID portainer.EndpointID, volumeID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
volume, err := dockerClient.VolumeInspect(context.Background(), volumeID)
if err != nil {
return nil, err
}
swarmStackName := volume.Labels[resourceLabelForDockerSwarmStackName]
if swarmStackName != "" {
return authorization.GetResourceControlByResourceIDAndType(swarmStackName, portainer.StackResourceControl, resourceControls), nil
stackResourceID := getStackResourceIDFromLabels(volume.Labels, endpointID)
if stackResourceID != "" {
return authorization.GetResourceControlByResourceIDAndType(stackResourceID, portainer.StackResourceControl, resourceControls), nil
}
return nil, nil