Преглед изворни кода

Merge branch 'belanger/stacks' of github.com:porter-dev/porter into nico/por-521-frontend-stacks-work

jnfrati пре 3 година
родитељ
комит
1b22dc9104

+ 29 - 10
api/server/handlers/stack/create.go

@@ -3,6 +3,7 @@ package stack
 import (
 	"fmt"
 	"net/http"
+	"strings"
 
 	"github.com/porter-dev/porter/api/server/authz"
 	"github.com/porter-dev/porter/api/server/handlers"
@@ -113,6 +114,8 @@ func (p *StackCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	helmReleaseMap := make(map[string]*helmrelease.Release)
 
+	deployErrs := make([]string, 0)
+
 	for _, appResource := range req.AppResources {
 		rel, err := applyAppResource(&applyAppResourceOpts{
 			config:     p.Config(),
@@ -125,17 +128,22 @@ func (p *StackCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		})
 
 		if err != nil {
-			// TODO: mark stack with error
-			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-			return
+			deployErrs = append(deployErrs, err.Error())
+		} else {
+			helmReleaseMap[fmt.Sprintf("%s/%s", namespace, appResource.Name)] = rel
 		}
-
-		helmReleaseMap[fmt.Sprintf("%s/%s", namespace, appResource.Name)] = rel
 	}
 
 	// update stack revision status
 	revision := &stack.Revisions[0]
-	revision.Status = string(types.StackRevisionStatusDeployed)
+
+	if len(deployErrs) > 0 {
+		revision.Status = string(types.StackRevisionStatusFailed)
+		revision.Reason = "DeployError"
+		revision.Message = strings.Join(deployErrs, " , ")
+	} else {
+		revision.Status = string(types.StackRevisionStatusDeployed)
+	}
 
 	revision, err = p.Repo().Stack().UpdateStackRevision(revision)
 
@@ -144,14 +152,25 @@ func (p *StackCreateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	saveErrs := make([]string, 0)
+
 	for _, resource := range revision.Resources {
-		rel := helmReleaseMap[fmt.Sprintf("%s/%s", namespace, resource.Name)]
+		if rel, exists := helmReleaseMap[fmt.Sprintf("%s/%s", namespace, resource.Name)]; exists {
+			_, err = release.CreateAppReleaseFromHelmRelease(p.Config(), proj.ID, cluster.ID, resource.ID, rel)
+
+			if err != nil {
+				saveErrs = append(saveErrs, fmt.Sprintf("the resource %s/%s could not be saved right now", namespace, resource.Name))
+			}
+		}
+	}
+
+	if len(saveErrs) > 0 {
+		revision.Reason = "SaveError"
+		revision.Message = strings.Join(saveErrs, " , ")
 
-		// TODO: case on addon vs application
-		_, err = release.CreateAppReleaseFromHelmRelease(p.Config(), proj.ID, cluster.ID, resource.ID, rel)
+		revision, err = p.Repo().Stack().UpdateStackRevision(revision)
 
 		if err != nil {
-			// TODO: mark stack with error
 			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
 			return
 		}

+ 11 - 4
api/server/handlers/stack/rollback.go

@@ -2,6 +2,7 @@ package stack
 
 import (
 	"net/http"
+	"strings"
 
 	"github.com/porter-dev/porter/api/server/authz"
 	"github.com/porter-dev/porter/api/server/handlers"
@@ -96,6 +97,8 @@ func (p *StackRollbackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 	}
 
 	// apply to cluster
+	rollbackErrors := make([]string, 0)
+
 	for _, resource := range revision.Resources {
 		err := rollbackAppResource(&rollbackAppResourceOpts{
 			helmAgent:      helmAgent,
@@ -104,13 +107,17 @@ func (p *StackRollbackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 		})
 
 		if err != nil {
-			// TODO: mark stack with error
-			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-			return
+			rollbackErrors = append(rollbackErrors, err.Error())
 		}
 	}
 
-	revision.Status = string(types.StackRevisionStatusDeployed)
+	if len(rollbackErrors) > 0 {
+		revision.Status = string(types.StackRevisionStatusFailed)
+		revision.Reason = "RollbackError"
+		revision.Message = strings.Join(rollbackErrors, " , ")
+	} else {
+		revision.Status = string(types.StackRevisionStatusDeployed)
+	}
 
 	revision, err = p.Repo().Stack().UpdateStackRevision(revision)
 

+ 11 - 4
api/server/handlers/stack/update_source_put.go

@@ -2,6 +2,7 @@ package stack
 
 import (
 	"net/http"
+	"strings"
 
 	"github.com/porter-dev/porter/api/server/authz"
 	"github.com/porter-dev/porter/api/server/handlers"
@@ -94,6 +95,8 @@ func (p *StackPutSourceConfigHandler) ServeHTTP(w http.ResponseWriter, r *http.R
 		return
 	}
 
+	deployErrs := make([]string, 0)
+
 	for i, appResource := range clonedAppResources {
 		// get the corresponding source config tag
 		var imageTag string
@@ -118,15 +121,19 @@ func (p *StackPutSourceConfigHandler) ServeHTTP(w http.ResponseWriter, r *http.R
 		})
 
 		if err != nil {
-			// TODO: mark stack with error
-			p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
-			return
+			deployErrs = append(deployErrs, err.Error())
 		}
 
 		clonedAppResources[i].HelmRevisionID++
 	}
 
-	revision.Status = string(types.StackRevisionStatusDeployed)
+	if len(deployErrs) > 0 {
+		revision.Status = string(types.StackRevisionStatusFailed)
+		revision.Reason = "DeployError"
+		revision.Message = strings.Join(deployErrs, " , ")
+	} else {
+		revision.Status = string(types.StackRevisionStatusDeployed)
+	}
 
 	revision, err = p.Repo().Stack().UpdateStackRevision(revision)
 

+ 1 - 1
api/server/router/v1/stack.go

@@ -112,7 +112,7 @@ func getV1StackRoutes(
 	// POST /api/v1/projects/{project_id}/clusters/{cluster_id}/namespaces/{namespace}/stacks -> stack.NewStackCreateHandler
 	// swagger:operation POST /api/v1/projects/{project_id}/clusters/{cluster_id}/namespaces/{namespace}/stacks createStack
 	//
-	// Creates a stack
+	// Creates a new stack and triggers a deployment for all resources in the stack.
 	//
 	// ---
 	// produces:

+ 6 - 0
api/types/stacks.go

@@ -146,6 +146,12 @@ type StackRevisionMeta struct {
 type StackRevision struct {
 	*StackRevisionMeta
 
+	// The reason for any error or status change
+	Reason string `json:"reason"`
+
+	// The message associated with an error or status change
+	Message string `json:"message"`
+
 	// The list of resources deployed in this revision
 	Resources []StackResource `json:"resources"`
 

+ 5 - 0
internal/models/stack.go

@@ -55,6 +55,9 @@ type StackRevision struct {
 
 	Status string
 
+	Reason  string
+	Message string
+
 	Resources []StackResource
 
 	SourceConfigs []StackSourceConfig
@@ -88,6 +91,8 @@ func (s StackRevision) ToStackRevisionType(stackID string) *types.StackRevision
 		StackRevisionMeta: &metaType,
 		SourceConfigs:     sourceConfigs,
 		Resources:         resources,
+		Reason:            s.Reason,
+		Message:           s.Message,
 	}
 }
 

+ 6 - 2
internal/repository/gorm/stack.go

@@ -29,10 +29,14 @@ func (repo *StackRepository) CreateStack(stack *models.Stack) (*models.Stack, er
 // ReadStack gets a stack specified by its string id
 func (repo *StackRepository) ListStacks(projectID, clusterID uint, namespace string) ([]*models.Stack, error) {
 	stacks := make([]*models.Stack, 0)
+	query := repo.db.Where("stacks.project_id = ? AND stacks.cluster_id = ?", projectID, clusterID)
+
+	if namespace != "" {
+		query = query.Where("stacks.namespace = ?", namespace)
+	}
 
 	// get stack IDs
-	if err := repo.db.
-		Where("stacks.project_id = ? AND stacks.cluster_id = ? AND stacks.namespace = ?", projectID, clusterID, namespace).Find(&stacks).Error; err != nil {
+	if err := query.Find(&stacks).Error; err != nil {
 		return nil, err
 	}