diff --git a/api/http/handler/edgestacks/edgestack_create.go b/api/http/handler/edgestacks/edgestack_create.go
index 13a498033..b06b412e4 100644
--- a/api/http/handler/edgestacks/edgestack_create.go
+++ b/api/http/handler/edgestacks/edgestack_create.go
@@ -92,6 +92,8 @@ type swarmStackFromFileContentPayload struct {
DeploymentType portainer.EdgeStackDeploymentType `example:"0" enums:"0,1,2"`
// List of Registries to use for this stack
Registries []portainer.RegistryID
+ // Uses the manifest's namespaces instead of the default one
+ UseManifestNamespaces bool
}
func (payload *swarmStackFromFileContentPayload) Validate(r *http.Request) error {
@@ -114,7 +116,7 @@ func (handler *Handler) createSwarmStackFromFileContent(r *http.Request, dryrun
return nil, err
}
- stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries)
+ stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries, payload.UseManifestNamespaces)
if err != nil {
return nil, errors.Wrap(err, "failed to create Edge stack object")
}
@@ -197,6 +199,8 @@ type swarmStackFromGitRepositoryPayload struct {
DeploymentType portainer.EdgeStackDeploymentType `example:"0" enums:"0,1,2"`
// List of Registries to use for this stack
Registries []portainer.RegistryID
+ // Uses the manifest's namespaces instead of the default one
+ UseManifestNamespaces bool
}
func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) error {
@@ -230,7 +234,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(r *http.Request, dryru
return nil, err
}
- stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries)
+ stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries, payload.UseManifestNamespaces)
if err != nil {
return nil, errors.Wrap(err, "failed to create edge stack object")
}
@@ -268,6 +272,8 @@ type swarmStackFromFileUploadPayload struct {
// nomad deploytype is enabled only for nomad environments(endpoints)
DeploymentType portainer.EdgeStackDeploymentType `example:"0" enums:"0,1,2"`
Registries []portainer.RegistryID
+ // Uses the manifest's namespaces instead of the default one
+ UseManifestNamespaces bool
}
func (payload *swarmStackFromFileUploadPayload) Validate(r *http.Request) error {
@@ -303,6 +309,9 @@ func (payload *swarmStackFromFileUploadPayload) Validate(r *http.Request) error
}
payload.Registries = registries
+ useManifestNamespaces, _ := request.RetrieveBooleanMultiPartFormValue(r, "UseManifestNamespaces", true)
+ payload.UseManifestNamespaces = useManifestNamespaces
+
return nil
}
@@ -313,7 +322,7 @@ func (handler *Handler) createSwarmStackFromFileUpload(r *http.Request, dryrun b
return nil, err
}
- stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries)
+ stack, err := handler.edgeStacksService.BuildEdgeStack(payload.Name, payload.DeploymentType, payload.EdgeGroups, payload.Registries, payload.UseManifestNamespaces)
if err != nil {
return nil, errors.Wrap(err, "failed to create edge stack object")
}
diff --git a/api/http/handler/edgestacks/edgestack_update.go b/api/http/handler/edgestacks/edgestack_update.go
index 9bc690f31..f9cd768ed 100644
--- a/api/http/handler/edgestacks/edgestack_update.go
+++ b/api/http/handler/edgestacks/edgestack_update.go
@@ -19,6 +19,8 @@ type updateEdgeStackPayload struct {
Version *int
EdgeGroups []portainer.EdgeGroupID
DeploymentType portainer.EdgeStackDeploymentType
+ // Uses the manifest's namespaces instead of the default one
+ UseManifestNamespaces bool
}
func (payload *updateEdgeStackPayload) Validate(r *http.Request) error {
@@ -168,6 +170,8 @@ func (handler *Handler) edgeStackUpdate(w http.ResponseWriter, r *http.Request)
stack.ManifestPath = filesystem.ManifestFileDefaultName
}
+ stack.UseManifestNamespaces = payload.UseManifestNamespaces
+
hasDockerEndpoint, err := hasDockerEndpoint(handler.DataStore.Endpoint(), relatedEndpointIds)
if err != nil {
return httperror.InternalServerError("Unable to check for existence of docker environment", err)
diff --git a/api/http/handler/endpointedge/endpoint_edgestack_inspect.go b/api/http/handler/endpointedge/endpoint_edgestack_inspect.go
index 5958f2c4d..ed874c0fc 100644
--- a/api/http/handler/endpointedge/endpoint_edgestack_inspect.go
+++ b/api/http/handler/endpointedge/endpoint_edgestack_inspect.go
@@ -10,11 +10,14 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/middlewares"
"github.com/portainer/portainer/api/internal/endpointutils"
+ "github.com/portainer/portainer/api/kubernetes"
)
type configResponse struct {
StackFileContent string
Name string
+ // Namespace to use for Kubernetes manifests, leave empty to use the namespaces defined in the manifest
+ Namespace string
}
// @summary Inspect an Edge Stack for an Environment(Endpoint)
@@ -59,12 +62,18 @@ func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http.
}
}
+ namespace := ""
+ if !edgeStack.UseManifestNamespaces {
+ namespace = kubernetes.DefaultNamespace
+ }
+
if endpointutils.IsKubernetesEndpoint(endpoint) {
fileName = edgeStack.ManifestPath
if fileName == "" {
return httperror.BadRequest("Kubernetes is not supported by this stack", errors.New("Kubernetes is not supported by this stack"))
}
+
}
stackFileContent, err := handler.FileService.GetFileContent(edgeStack.ProjectPath, fileName)
@@ -75,5 +84,6 @@ func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http.
return response.JSON(w, configResponse{
StackFileContent: string(stackFileContent),
Name: edgeStack.Name,
+ Namespace: namespace,
})
}
diff --git a/api/internal/edge/edgestacks/service.go b/api/internal/edge/edgestacks/service.go
index b08e4ae01..702d5e5f5 100644
--- a/api/internal/edge/edgestacks/service.go
+++ b/api/internal/edge/edgestacks/service.go
@@ -30,7 +30,9 @@ func NewService(dataStore dataservices.DataStore) *Service {
func (service *Service) BuildEdgeStack(name string,
deploymentType portainer.EdgeStackDeploymentType,
edgeGroups []portainer.EdgeGroupID,
- registries []portainer.RegistryID) (*portainer.EdgeStack, error) {
+ registries []portainer.RegistryID,
+ useManifestNamespaces bool,
+) (*portainer.EdgeStack, error) {
edgeStacksService := service.dataStore.EdgeStack()
err := validateUniqueName(edgeStacksService.EdgeStacks, name)
@@ -40,13 +42,14 @@ func (service *Service) BuildEdgeStack(name string,
stackID := edgeStacksService.GetNextIdentifier()
return &portainer.EdgeStack{
- ID: portainer.EdgeStackID(stackID),
- Name: name,
- DeploymentType: deploymentType,
- CreationDate: time.Now().Unix(),
- EdgeGroups: edgeGroups,
- Status: make(map[portainer.EndpointID]portainer.EdgeStackStatus),
- Version: 1,
+ ID: portainer.EdgeStackID(stackID),
+ Name: name,
+ DeploymentType: deploymentType,
+ CreationDate: time.Now().Unix(),
+ EdgeGroups: edgeGroups,
+ Status: make(map[portainer.EndpointID]portainer.EdgeStackStatus),
+ Version: 1,
+ UseManifestNamespaces: useManifestNamespaces,
}, nil
}
diff --git a/api/kubernetes/contants.go b/api/kubernetes/contants.go
new file mode 100644
index 000000000..a2d934a42
--- /dev/null
+++ b/api/kubernetes/contants.go
@@ -0,0 +1,6 @@
+package kubernetes
+
+const (
+ // DefaultNamespace is the default namespace used when no namespace is specified
+ DefaultNamespace = "default"
+)
diff --git a/api/portainer.go b/api/portainer.go
index 7b6c45da1..2c7b72aa0 100644
--- a/api/portainer.go
+++ b/api/portainer.go
@@ -281,6 +281,8 @@ type (
Version int `json:"Version"`
ManifestPath string
DeploymentType EdgeStackDeploymentType
+ // Uses the manifest's namespaces instead of the default one
+ UseManifestNamespaces bool
// Deprecated
Prune bool `json:"Prune"`
diff --git a/app/edge/components/edit-edge-stack-form/editEdgeStackForm.html b/app/edge/components/edit-edge-stack-form/editEdgeStackForm.html
index 73a5e3a10..4f737ba8e 100644
--- a/app/edge/components/edit-edge-stack-form/editEdgeStackForm.html
+++ b/app/edge/components/edit-edge-stack-form/editEdgeStackForm.html
@@ -48,21 +48,33 @@
-
- You can get more information about Kubernetes file format in the
- official documentation.
-
+ You can get more information about Kubernetes file format in the + official documentation. +
+