Feat: supports setting environment differences for application plan (#2624)

* Feat: supports setting environment differences for application plan

* Feat: update swagger config

* Feat: CRUD of application env binding plan

* Style: change code style

Co-authored-by: barnettZQG <yiyun.pro>
This commit is contained in:
barnettZQG
2021-11-05 10:42:18 +08:00
committed by GitHub
co-authored by lnx01
parent cd686fbb24
commit df5bc2727e
12 changed files with 1459 additions and 251 deletions
+685 -68
View File
@@ -321,8 +321,8 @@
"tags": [
"application"
],
"summary": "list all applications",
"operationId": "listApplications",
"summary": "list all application plans",
"operationId": "listApplicationPlans",
"parameters": [
{
"type": "string",
@@ -368,8 +368,8 @@
"tags": [
"application"
],
"summary": "create one application",
"operationId": "createApplication",
"summary": "create one application plan",
"operationId": "createApplicationPlan",
"parameters": [
{
"name": "body",
@@ -407,12 +407,12 @@
"tags": [
"application"
],
"summary": "detail one application",
"operationId": "detailApplication",
"summary": "detail one application plan",
"operationId": "detailApplicationPlan",
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -431,6 +431,50 @@
}
}
},
"put": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "update one application plan",
"operationId": "updateApplicationPlan",
"parameters": [
{
"type": "string",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1.UpdateApplicationPlanRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.ApplicationPlanBase"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
},
"delete": {
"consumes": [
"application/xml",
@@ -444,11 +488,11 @@
"application"
],
"summary": "delete one application",
"operationId": "deleteApplication",
"operationId": "deleteApplicationPlan",
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -486,7 +530,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -528,7 +572,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -574,7 +618,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -612,7 +656,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -632,6 +676,148 @@
}
}
},
"/api/v1/applicationplans/{name}/envs": {
"post": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "creating an application environment plan",
"operationId": "createApplicationEnv",
"parameters": [
{
"type": "string",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1.CreateApplicationEnvPlanRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.EnvBind"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/applicationplans/{name}/envs/{envName}": {
"put": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "set application plan differences in the specified environment",
"operationId": "updateApplicationEnvBinding",
"parameters": [
{
"type": "string",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier of the application plan",
"name": "envName",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v1.PutApplicationPlanEnvRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.EnvBind"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
},
"delete": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"application"
],
"summary": "delete an application environment plan",
"operationId": "deleteApplicationEnv",
"parameters": [
{
"type": "string",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier of the application plan",
"name": "envName",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.EmptyResponse"
}
},
"404": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/applicationplans/{name}/policies": {
"get": {
"consumes": [
@@ -650,7 +836,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -871,7 +1057,7 @@
"parameters": [
{
"type": "string",
"description": "identifier of the application",
"description": "identifier of the application plan",
"name": "name",
"in": "path",
"required": true
@@ -1097,6 +1283,178 @@
}
}
},
"/api/v1/clusters/cloud-clusters/{provider}/create": {
"post": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"cluster"
],
"summary": "create cloud cluster",
"operationId": "createCloudCluster",
"parameters": [
{
"type": "string",
"description": "identifier of the cloud provider",
"name": "provider",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/*v1.CreateCloudClusterRequest"
}
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.CreateCloudClusterResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/clusters/cloud-clusters/{provider}/creation": {
"get": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"cluster"
],
"summary": "list cloud cluster creation",
"operationId": "listCloudClusterCreation",
"parameters": [
{
"type": "string",
"description": "identifier of the cloud provider",
"name": "provider",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.ListCloudClusterCreationResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/clusters/cloud-clusters/{provider}/creation/{cloudClusterName}": {
"get": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"cluster"
],
"summary": "check cloud cluster create status",
"operationId": "getCloudClusterCreationStatus",
"parameters": [
{
"type": "string",
"description": "identifier of the cloud provider",
"name": "provider",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier for cloud cluster which is creating",
"name": "cloudClusterName",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.CreateCloudClusterResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
},
"delete": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"cluster"
],
"summary": "delete cloud cluster creation",
"operationId": "deleteCloudClusterCreation",
"parameters": [
{
"type": "string",
"description": "identifier of the cloud provider",
"name": "provider",
"in": "path",
"required": true
},
{
"type": "string",
"description": "identifier for cloud cluster which is creating",
"name": "cloudClusterName",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"schema": {
"$ref": "#/definitions/v1.CreateCloudClusterResponse"
}
},
"400": {
"schema": {
"$ref": "#/definitions/bcode.Bcode"
}
}
}
}
},
"/api/v1/clusters/{clusterName}": {
"get": {
"consumes": [
@@ -1215,7 +1573,7 @@
}
}
},
"/api/v1/componentdefinitions": {
"/api/v1/definitions": {
"get": {
"consumes": [
"application/xml",
@@ -1226,23 +1584,76 @@
"application/xml"
],
"tags": [
"componentdefinition"
"definition"
],
"summary": "list all componentdefinition",
"operationId": "listComponentDefinition",
"summary": "list all definitions",
"operationId": "listDefinitions",
"parameters": [
{
"type": "string",
"description": "if specified, query the componentdefinition supported by the env.",
"description": "query the definition type",
"name": "type",
"in": "query"
},
{
"type": "string",
"description": "if specified, query the definition supported by the env.",
"name": "envName",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/v1.ListComponentDefinitionResponse"
"$ref": "#/definitions/map[string]string"
}
},
"500": {
"description": "Bummer, something went wrong"
}
}
}
},
"/api/v1/definitions/{name}": {
"get": {
"consumes": [
"application/xml",
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"tags": [
"definition"
],
"summary": "detail definition",
"operationId": "detailDefinition",
"parameters": [
{
"type": "string",
"description": "identifier of the definition",
"name": "name",
"in": "path",
"required": true
},
{
"type": "string",
"description": "query the definition type",
"name": "type",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/map[string]string"
}
},
"500": {
"description": "Bummer, something went wrong"
}
}
}
@@ -1834,9 +2245,9 @@
},
"common.AppRolloutStatus": {
"required": [
"rollingState",
"batchRollingState",
"upgradedReplicas",
"rollingState",
"currentBatch",
"upgradedReadyReplicas",
"lastTargetAppRevision"
@@ -2975,24 +3386,6 @@
}
}
},
"v1.ComponentDefinitionBase": {
"required": [
"name",
"description",
"icon"
],
"properties": {
"description": {
"type": "string"
},
"icon": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"v1.ComponentPlanBase": {
"required": [
"name",
@@ -3068,6 +3461,19 @@
}
}
},
"v1.ComponentSelector": {
"required": [
"components"
],
"properties": {
"components": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"v1.ConnectCloudClusterRequest": {
"required": [
"accessKeyID",
@@ -3120,6 +3526,31 @@
}
}
},
"v1.CreateApplicationEnvPlanRequest": {
"required": [
"componentSelector",
"name",
"alias",
"clusterSelector"
],
"properties": {
"alias": {
"type": "string"
},
"clusterSelector": {
"$ref": "#/definitions/v1.ClusterSelector"
},
"componentSelector": {
"$ref": "#/definitions/v1.ComponentSelector"
},
"description": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"v1.CreateApplicationPlanRequest": {
"required": [
"name",
@@ -3182,6 +3613,57 @@
}
}
},
"v1.CreateCloudClusterRequest": {
"required": [
"accessKeyID",
"accessKeySecret",
"name",
"zone",
"workerNumber",
"cpuCoresPerWorker",
"memoryPerWorker"
],
"properties": {
"accessKeyID": {
"type": "string"
},
"accessKeySecret": {
"type": "string"
},
"cpuCoresPerWorker": {
"type": "integer",
"format": "int64"
},
"memoryPerWorker": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"workerNumber": {
"type": "integer",
"format": "int32"
},
"zone": {
"type": "string"
}
}
},
"v1.CreateCloudClusterResponse": {
"required": [
"clusterID",
"status"
],
"properties": {
"clusterID": {
"type": "string"
},
"status": {
"type": "string"
}
}
},
"v1.CreateClusterRequest": {
"required": [
"name",
@@ -3338,13 +3820,77 @@
}
}
},
"v1.DefinitionBase": {
"required": [
"name",
"description",
"icon"
],
"properties": {
"description": {
"type": "string"
},
"icon": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"v1.DefinitionProperties": {
"required": [
"default",
"description",
"title",
"type"
],
"properties": {
"default": {
"type": "string"
},
"description": {
"type": "string"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"v1.DefinitionSchema": {
"required": [
"properties",
"required",
"type"
],
"properties": {
"properties": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/v1.DefinitionProperties"
}
},
"required": {
"type": "array",
"items": {
"type": "string"
}
},
"type": {
"type": "string"
}
}
},
"v1.DetailAddonResponse": {
"required": [
"name",
"version",
"description",
"icon",
"tags",
"name"
"tags"
],
"properties": {
"deploy_data": {
@@ -3375,15 +3921,15 @@
},
"v1.DetailApplicationPlanResponse": {
"required": [
"icon",
"status",
"gatewayRule",
"name",
"namespace",
"icon",
"gatewayRule",
"alias",
"description",
"createTime",
"updateTime",
"name",
"alias",
"status",
"policies",
"status",
"resourceInfo",
@@ -3453,20 +3999,20 @@
},
"v1.DetailClusterResponse": {
"required": [
"createTime",
"description",
"status",
"reason",
"kubeConfig",
"kubeConfigSecret",
"name",
"alias",
"provider",
"labels",
"dashboardURL",
"updateTime",
"description",
"dashboardURL",
"kubeConfigSecret",
"createTime",
"name",
"icon",
"apiServerURL",
"alias",
"labels",
"status",
"kubeConfig",
"resourceInfo"
],
"properties": {
@@ -3524,13 +4070,13 @@
},
"v1.DetailComponentPlanResponse": {
"required": [
"appPrimaryKey",
"alias",
"type",
"createTime",
"updateTime",
"alias",
"appPrimaryKey",
"creator",
"name",
"createTime"
"type"
],
"properties": {
"alias": {
@@ -3606,15 +4152,25 @@
}
}
},
"v1.DetailDefinitionResponse": {
"required": [
"schema"
],
"properties": {
"schema": {
"$ref": "#/definitions/v1.DefinitionSchema"
}
}
},
"v1.DetailPolicyResponse": {
"required": [
"description",
"creator",
"properties",
"createTime",
"updateTime",
"name",
"type"
"type",
"description",
"creator"
],
"properties": {
"createTime": {
@@ -3757,12 +4313,20 @@
"v1.EnvBind": {
"required": [
"name",
"clusterSelector"
"alias",
"clusterSelector",
"componentSelector"
],
"properties": {
"alias": {
"type": "string"
},
"clusterSelector": {
"$ref": "#/definitions/v1.ClusterSelector"
},
"componentSelector": {
"$ref": "#/definitions/v1.ComponentSelector"
},
"description": {
"type": "string"
},
@@ -3850,6 +4414,19 @@
}
}
},
"v1.ListCloudClusterCreationResponse": {
"required": [
"creations"
],
"properties": {
"creations": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"v1.ListCloudClusterResponse": {
"required": [
"clusters",
@@ -3881,15 +4458,15 @@
}
}
},
"v1.ListComponentDefinitionResponse": {
"v1.ListDefinitionResponse": {
"required": [
"componentDefinitions"
"definitions"
],
"properties": {
"componentDefinitions": {
"definitions": {
"type": "array",
"items": {
"$ref": "#/definitions/v1.ComponentDefinitionBase"
"$ref": "#/definitions/v1.DefinitionBase"
}
}
}
@@ -4089,6 +4666,46 @@
}
}
},
"v1.PutApplicationPlanEnvRequest": {
"properties": {
"alias": {
"type": "string"
},
"clusterSelector": {
"$ref": "#/definitions/v1.ClusterSelector"
},
"componentSelector": {
"$ref": "#/definitions/v1.ComponentSelector"
},
"description": {
"type": "string"
}
}
},
"v1.UpdateApplicationPlanRequest": {
"required": [
"alias",
"description",
"icon"
],
"properties": {
"alias": {
"type": "string"
},
"description": {
"type": "string"
},
"icon": {
"type": "string"
},
"labels": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"v1.UpdatePolicyRequest": {
"required": [
"description",
+11 -4
View File
@@ -62,18 +62,25 @@ func (a *ApplicationPlan) Index() map[string]string {
// EnvBind application env bind
type EnvBind struct {
Name string `json:"name" validate:"checkname"`
Description string `json:"description,omitempty"`
ClusterSelector *ClusterSelector `json:"clusterSelector"`
Name string `json:"name"`
Alias string `json:"alias"`
Description string `json:"description,omitempty"`
ClusterSelector ClusterSelector `json:"clusterSelector"`
ComponentSelector *ComponentSelector `json:"componentSelector"`
}
// ClusterSelector cluster selector
type ClusterSelector struct {
Name string `json:"name" validate:"checkname"`
Name string `json:"name"`
// Adapt to a scenario where only one Namespace is available or a user-defined Namespace is available.
Namespace string `json:"namespace,omitempty"`
}
// ComponentSelector component selector
type ComponentSelector struct {
Components []string `json:"components"`
}
// ApplicationComponentPlan component database model
type ApplicationComponentPlan struct {
Model
+43 -7
View File
@@ -29,11 +29,12 @@ import (
var (
// CtxKeyApplication request context key of application
CtxKeyApplication = "application"
// CtxKeyWorkflow request context key of workflow
CtxKeyWorkflow = "workflow"
// CtxKeyApplicationEnvBinding request context key of env binding
CtxKeyApplicationEnvBinding = "envbinding-policy"
)
// CtxKeyWorkflow request context key of workflow
var CtxKeyWorkflow = "workflow"
// AddonPhase defines the phase of an addon
type AddonPhase string
@@ -228,7 +229,7 @@ type EnvBindList []*EnvBind
// ContainCluster contain cluster name
func (e EnvBindList) ContainCluster(name string) bool {
for _, eb := range e {
if eb.ClusterSelector != nil && eb.ClusterSelector.Name == name {
if eb.ClusterSelector.Name == name {
return true
}
}
@@ -283,11 +284,21 @@ type CreateApplicationPlanRequest struct {
Deploy bool `json:"deploy,omitempty"`
}
// UpdateApplicationPlanRequest update application plan base config
type UpdateApplicationPlanRequest struct {
Alias string `json:"alias" validate:"checkalias"`
Description string `json:"description"`
Icon string `json:"icon"`
Labels map[string]string `json:"labels,omitempty"`
}
// EnvBind application env bind
type EnvBind struct {
Name string `json:"name" validate:"checkname"`
Description string `json:"description,omitempty"`
ClusterSelector *ClusterSelector `json:"clusterSelector"`
Name string `json:"name" validate:"checkname"`
Alias string `json:"alias" validate:"checkalias"`
Description string `json:"description,omitempty"`
ClusterSelector ClusterSelector `json:"clusterSelector"`
ComponentSelector *ComponentSelector `json:"componentSelector"`
}
// ClusterSelector cluster selector
@@ -297,6 +308,11 @@ type ClusterSelector struct {
Namespace string `json:"namespace,omitempty"`
}
// ComponentSelector component selector
type ComponentSelector struct {
Components []string `json:"components"`
}
// DetailApplicationPlanResponse application plan detail
type DetailApplicationPlanResponse struct {
ApplicationPlanBase
@@ -359,6 +375,11 @@ type DetailComponentPlanResponse struct {
//TODO: Status
}
// ListApplicationComponentOptions list app plan component list
type ListApplicationComponentOptions struct {
EnvName string `json:"envName"`
}
// CreateApplicationTemplateRequest create app template request model
type CreateApplicationTemplateRequest struct {
TemplateName string `json:"templateName" validate:"checkname"`
@@ -417,12 +438,14 @@ type DetailDefinitionResponse struct {
Schema *DefinitionSchema `json:"schema"`
}
// DefinitionSchema definition schema info
type DefinitionSchema struct {
Properties map[string]*DefinitionProperties `json:"properties"`
Required []string `json:"required"`
Type string `json:"type"`
}
// DefinitionProperties definition properties
type DefinitionProperties struct {
Items *DefinitionSchema `json:"items,omitempty"`
Enum []interface{} `json:"enum,omitempty"`
@@ -611,3 +634,16 @@ type ApplicationDeployResponse struct {
// VelaQLViewResponse query response
type VelaQLViewResponse map[string]interface{}
// PutApplicationPlanEnvRequest set diff request
type PutApplicationPlanEnvRequest struct {
ComponentSelector *ComponentSelector `json:"componentSelector,omitempty"`
Alias *string `json:"alias,omitempty" validate:"checkalias"`
Description *string `json:"description,omitempty"`
ClusterSelector *ClusterSelector `json:"clusterSelector,omitempty"`
}
// CreateApplicationEnvPlanRequest new application env plan
type CreateApplicationEnvPlanRequest struct {
EnvBind
}
@@ -20,6 +20,8 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"sort"
"strings"
corev1 "k8s.io/api/core/v1"
@@ -49,18 +51,22 @@ type PolicyType string
const (
// EnvBindPolicy Multiple environment distribution policy
EnvBindPolicy PolicyType = "env-binding"
// EnvBindPolicyDefaultName default policy name
EnvBindPolicyDefaultName string = "env-bindings"
)
// ApplicationUsecase application usecase
type ApplicationUsecase interface {
ListApplications(ctx context.Context, listOptions apisv1.ListApplicatioPlanOptions) ([]*apisv1.ApplicationPlanBase, error)
GetApplication(ctx context.Context, appName string) (*model.ApplicationPlan, error)
DetailApplication(ctx context.Context, app *model.ApplicationPlan) (*apisv1.DetailApplicationPlanResponse, error)
ListApplicationPlans(ctx context.Context, listOptions apisv1.ListApplicatioPlanOptions) ([]*apisv1.ApplicationPlanBase, error)
GetApplicationPlan(ctx context.Context, appName string) (*model.ApplicationPlan, error)
DetailApplicationPlan(ctx context.Context, app *model.ApplicationPlan) (*apisv1.DetailApplicationPlanResponse, error)
PublishApplicationTemplate(ctx context.Context, app *model.ApplicationPlan) (*apisv1.ApplicationTemplateBase, error)
CreateApplication(context.Context, apisv1.CreateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error)
DeleteApplication(ctx context.Context, app *model.ApplicationPlan) error
CreateApplicationPlan(context.Context, apisv1.CreateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error)
UpdateApplicationPlan(context.Context, *model.ApplicationPlan, apisv1.UpdateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error)
DeleteApplicationPlan(ctx context.Context, app *model.ApplicationPlan) error
Deploy(ctx context.Context, app *model.ApplicationPlan, req apisv1.ApplicationDeployRequest) (*apisv1.ApplicationDeployResponse, error)
ListComponents(ctx context.Context, app *model.ApplicationPlan) ([]*apisv1.ComponentPlanBase, error)
ListComponents(ctx context.Context, app *model.ApplicationPlan, op apisv1.ListApplicationComponentOptions) ([]*apisv1.ComponentPlanBase, error)
AddComponent(ctx context.Context, app *model.ApplicationPlan, com apisv1.CreateComponentPlanRequest) (*apisv1.ComponentPlanBase, error)
DetailComponent(ctx context.Context, app *model.ApplicationPlan, componentName string) (*apisv1.DetailComponentPlanResponse, error)
DeleteComponent(ctx context.Context, app *model.ApplicationPlan, componentName string) error
@@ -69,6 +75,10 @@ type ApplicationUsecase interface {
DetailPolicy(ctx context.Context, app *model.ApplicationPlan, policyName string) (*apisv1.DetailPolicyResponse, error)
DeletePolicy(ctx context.Context, app *model.ApplicationPlan, policyName string) error
UpdatePolicy(ctx context.Context, app *model.ApplicationPlan, policyName string, policy apisv1.UpdatePolicyRequest) (*apisv1.DetailPolicyResponse, error)
GetApplicationPlanEnvBindingPolicy(ctx context.Context, app *model.ApplicationPlan) (*v1alpha1.EnvBindingSpec, error)
UpdateApplicationEnvBindingPlan(ctx context.Context, app *model.ApplicationPlan, envName string, diff apisv1.PutApplicationPlanEnvRequest) (*apisv1.EnvBind, error)
CreateApplicationEnvBindingPlan(ctx context.Context, app *model.ApplicationPlan, env apisv1.CreateApplicationEnvPlanRequest) (*apisv1.EnvBind, error)
DeleteApplicationEnvBindingPlan(ctx context.Context, app *model.ApplicationPlan, envName string) error
}
type applicationUsecaseImpl struct {
@@ -92,8 +102,8 @@ func NewApplicationUsecase(ds datastore.DataStore, workflowUsecase WorkflowUseca
}
}
// ListApplications list applications
func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptions apisv1.ListApplicatioPlanOptions) ([]*apisv1.ApplicationPlanBase, error) {
// ListApplicationPlans list applications
func (c *applicationUsecaseImpl) ListApplicationPlans(ctx context.Context, listOptions apisv1.ListApplicatioPlanOptions) ([]*apisv1.ApplicationPlanBase, error) {
var app = model.ApplicationPlan{}
if listOptions.Namespace != "" {
app.Namespace = listOptions.Namespace
@@ -104,7 +114,7 @@ func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptio
}
var list []*apisv1.ApplicationPlanBase
for _, entity := range entitys {
appBase := c.converAppModelToBase(ctx, entity.(*model.ApplicationPlan))
appBase := c.converAppModelToBase(entity.(*model.ApplicationPlan))
if listOptions.Query != "" &&
!(strings.Contains(appBase.Alias, listOptions.Query) ||
strings.Contains(appBase.Name, listOptions.Query) ||
@@ -116,28 +126,34 @@ func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptio
}
list = append(list, appBase)
}
sort.Slice(list, func(i, j int) bool {
return list[i].UpdateTime.Unix() > list[j].UpdateTime.Unix()
})
return list, nil
}
// GetApplication get application model
func (c *applicationUsecaseImpl) GetApplication(ctx context.Context, appName string) (*model.ApplicationPlan, error) {
// GetApplicationPlan get application model
func (c *applicationUsecaseImpl) GetApplicationPlan(ctx context.Context, appName string) (*model.ApplicationPlan, error) {
var app = model.ApplicationPlan{
Name: appName,
}
if err := c.ds.Get(ctx, &app); err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrApplicationNotExist
}
return nil, err
}
return &app, nil
}
// DetailApplication detail application info
func (c *applicationUsecaseImpl) DetailApplication(ctx context.Context, app *model.ApplicationPlan) (*apisv1.DetailApplicationPlanResponse, error) {
base := c.converAppModelToBase(ctx, app)
// DetailApplicationPlan detail application plan info
func (c *applicationUsecaseImpl) DetailApplicationPlan(ctx context.Context, app *model.ApplicationPlan) (*apisv1.DetailApplicationPlanResponse, error) {
base := c.converAppModelToBase(app)
policys, err := c.queryApplicationPolicys(ctx, app)
if err != nil {
return nil, err
}
components, err := c.ListComponents(ctx, app)
components, err := c.ListComponents(ctx, app, apisv1.ListApplicationComponentOptions{})
if err != nil {
return nil, err
}
@@ -162,8 +178,8 @@ func (c *applicationUsecaseImpl) PublishApplicationTemplate(ctx context.Context,
return nil, nil
}
// CreateApplication create application
func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apisv1.CreateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error) {
// CreateApplicationPlan create application
func (c *applicationUsecaseImpl) CreateApplicationPlan(ctx context.Context, req apisv1.CreateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error) {
application := model.ApplicationPlan{
Name: req.Name,
Alias: req.Alias,
@@ -240,38 +256,7 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis
// build-in create env binding policy
if len(req.EnvBind) > 0 {
policy := model.ApplicationPolicyPlan{
AppPrimaryKey: application.PrimaryKey(),
Name: "env-binds",
Description: "build-in create",
Type: string(EnvBindPolicy),
Creator: "",
}
var envBindingSpec v1alpha1.EnvBindingSpec
for _, envBind := range req.EnvBind {
placement := v1alpha1.EnvPlacement{
ClusterSelector: &common.ClusterSelector{
Name: envBind.ClusterSelector.Name,
},
}
if envBind.ClusterSelector.Namespace != "" {
placement.NamespaceSelector = &v1alpha1.NamespaceSelector{
Name: envBind.ClusterSelector.Namespace,
}
}
envBindingSpec.Envs = append(envBindingSpec.Envs, v1alpha1.EnvConfig{
Name: envBind.Name,
Placement: placement,
})
}
properties, err := model.NewJSONStructByStruct(envBindingSpec)
if err != nil {
log.Logger.Errorf("new env binding properties failure,%s", err.Error())
return nil, bcode.ErrInvalidProperties
}
policy.Properties = properties
if err := c.ds.Add(ctx, &policy); err != nil {
log.Logger.Errorf("save env binding policy failure,%s", err.Error())
if _, err := c.createApplictionPlanEnvBindingPolicy(ctx, &application, req.EnvBind); err != nil {
return nil, err
}
}
@@ -284,7 +269,7 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis
return nil, err
}
// render app base info.
base := c.converAppModelToBase(ctx, &application)
base := c.converAppModelToBase(&application)
// deploy to cluster if need.
if req.Deploy && canDeploy {
if _, err := c.Deploy(ctx, &application, apisv1.ApplicationDeployRequest{
@@ -297,6 +282,17 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis
return base, nil
}
func (c *applicationUsecaseImpl) UpdateApplicationPlan(ctx context.Context, app *model.ApplicationPlan, req apisv1.UpdateApplicationPlanRequest) (*apisv1.ApplicationPlanBase, error) {
app.Alias = req.Alias
app.Description = req.Description
app.Labels = req.Labels
app.Icon = req.Icon
if err := c.ds.Put(ctx, app); err != nil {
return nil, err
}
return c.converAppModelToBase(app), nil
}
func (c *applicationUsecaseImpl) saveApplicationComponent(ctx context.Context, app *model.ApplicationPlan, components []common.ApplicationComponent) error {
var componentModels []datastore.Entity
for _, component := range components {
@@ -336,7 +332,7 @@ func (c *applicationUsecaseImpl) saveApplicationComponent(ctx context.Context, a
return c.ds.BatchAdd(ctx, componentModels)
}
func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model.ApplicationPlan) ([]*apisv1.ComponentPlanBase, error) {
func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model.ApplicationPlan, op apisv1.ListApplicationComponentOptions) ([]*apisv1.ComponentPlanBase, error) {
var component = model.ApplicationComponentPlan{
AppPrimaryKey: app.PrimaryKey(),
}
@@ -344,11 +340,31 @@ func (c *applicationUsecaseImpl) ListComponents(ctx context.Context, app *model.
if err != nil {
return nil, err
}
envComponents := map[string]bool{}
componentSelectorDefine := false
if op.EnvName != "" {
envbinding, err := c.GetApplicationPlanEnvBindingPolicy(ctx, app)
if err != nil && !errors.Is(err, bcode.ErrApplicationNotEnv) {
log.Logger.Errorf("query app plan env binding policy config failure %s", err.Error())
}
if envbinding != nil {
for _, env := range envbinding.Envs {
if env.Selector != nil && env.Name == op.EnvName {
componentSelectorDefine = true
for _, componentName := range env.Selector.Components {
envComponents[componentName] = true
}
}
}
}
}
var list []*apisv1.ComponentPlanBase
for _, component := range components {
log.Logger.Infof("component name %s", component.PrimaryKey())
pm := component.(*model.ApplicationComponentPlan)
list = append(list, c.converComponentModelToBase(pm))
if !componentSelectorDefine || envComponents[pm.Name] {
list = append(list, c.converComponentModelToBase(pm))
}
}
return list, nil
}
@@ -412,18 +428,49 @@ func (c *applicationUsecaseImpl) converPolicyModelToBase(policy *model.Applicati
func (c *applicationUsecaseImpl) saveApplicationPolicy(ctx context.Context, app *model.ApplicationPlan, policys []v1beta1.AppPolicy) error {
var policyModels []datastore.Entity
var envbindingPolicy *model.ApplicationPolicyPlan
for _, policy := range policys {
properties, err := model.NewJSONStruct(policy.Properties)
if err != nil {
log.Logger.Errorf("parse trait properties failire %w", err)
return bcode.ErrInvalidProperties
}
policyModels = append(policyModels, &model.ApplicationPolicyPlan{
appPolicyPlan := &model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Name: policy.Name,
Type: policy.Type,
Properties: properties,
})
}
if policy.Type != string(EnvBindPolicy) {
policyModels = append(policyModels, appPolicyPlan)
} else {
envbindingPolicy = appPolicyPlan
}
}
// If multiple configurations are configured, enable only the last one.
if envbindingPolicy != nil {
envbindingPolicy.Name = EnvBindPolicyDefaultName
policyModels = append(policyModels, envbindingPolicy)
var envBindingSpec v1alpha1.EnvBindingSpec
if err := json.Unmarshal([]byte(envbindingPolicy.Properties.JSON()), &envBindingSpec); err != nil {
return fmt.Errorf("unmarshal env binding policy failure %w", err)
}
for _, env := range envBindingSpec.Envs {
envBind := &model.EnvBind{
Name: env.Name,
Description: "",
}
if env.Selector != nil {
envBind.ComponentSelector = (*model.ComponentSelector)(env.Selector)
}
if env.Placement.ClusterSelector != nil {
envBind.ClusterSelector.Name = env.Placement.ClusterSelector.Name
}
if env.Placement.NamespaceSelector != nil {
envBind.ClusterSelector.Namespace = env.Placement.NamespaceSelector.Name
}
app.EnvBinds = append(app.EnvBinds, envBind)
}
}
return c.ds.BatchAdd(ctx, policyModels)
}
@@ -443,6 +490,52 @@ func (c *applicationUsecaseImpl) queryApplicationPolicys(ctx context.Context, ap
return
}
func (c *applicationUsecaseImpl) GetApplicationPlanEnvBindingPolicy(ctx context.Context, app *model.ApplicationPlan) (*v1alpha1.EnvBindingSpec, error) {
var policy = model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Type: string(EnvBindPolicy),
Name: EnvBindPolicyDefaultName,
}
err := c.ds.Get(ctx, &policy)
if err != nil {
if errors.Is(err, datastore.ErrRecordNotExist) {
return nil, bcode.ErrApplicationNotEnv
}
return nil, err
}
var envBindingSpec v1alpha1.EnvBindingSpec
if err := json.Unmarshal([]byte(policy.Properties.JSON()), &envBindingSpec); err != nil {
return nil, err
}
return &envBindingSpec, nil
}
func (c *applicationUsecaseImpl) createApplictionPlanEnvBindingPolicy(ctx context.Context, app *model.ApplicationPlan, envbinds apisv1.EnvBindList) (*model.ApplicationPolicyPlan, error) {
policy := &model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Name: EnvBindPolicyDefaultName,
Description: "build-in create",
Type: string(EnvBindPolicy),
Creator: "",
}
var envBindingSpec v1alpha1.EnvBindingSpec
for _, envBind := range envbinds {
envBindingSpec.Envs = append(envBindingSpec.Envs, createEnvBind(*envBind))
app.EnvBinds = append(app.EnvBinds, createModelEnvBind(*envBind))
}
properties, err := model.NewJSONStructByStruct(envBindingSpec)
if err != nil {
log.Logger.Errorf("new env binding properties failure,%s", err.Error())
return nil, bcode.ErrInvalidProperties
}
policy.Properties = properties
if err := c.ds.Add(ctx, policy); err != nil {
log.Logger.Errorf("save env binding policy failure,%s", err.Error())
return nil, err
}
return policy, nil
}
// DetailPolicy detail app policy
// TODO: Add status data about the policy.
func (c *applicationUsecaseImpl) DetailPolicy(ctx context.Context, app *model.ApplicationPlan, policyName string) (*apisv1.DetailPolicyResponse, error) {
@@ -642,8 +735,8 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo
return app, nil
}
func (c *applicationUsecaseImpl) converAppModelToBase(ctx context.Context, app *model.ApplicationPlan) *apisv1.ApplicationPlanBase {
appBeas := &apisv1.ApplicationPlanBase{
func (c *applicationUsecaseImpl) converAppModelToBase(app *model.ApplicationPlan) *apisv1.ApplicationPlanBase {
appBase := &apisv1.ApplicationPlanBase{
Name: app.Name,
Alias: app.Alias,
Namespace: app.Namespace,
@@ -653,49 +746,28 @@ func (c *applicationUsecaseImpl) converAppModelToBase(ctx context.Context, app *
Icon: app.Icon,
Labels: app.Labels,
}
var policy = model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Type: string(EnvBindPolicy),
}
policys, err := c.ds.List(ctx, &policy, &datastore.ListOptions{})
if err != nil {
log.Logger.Errorf("query application env binding policy failure %s", err.Error())
}
for _, policyEntity := range policys {
policy := policyEntity.(*model.ApplicationPolicyPlan)
if policy.Properties != nil {
var envBindingSpec v1alpha1.EnvBindingSpec
if err := json.Unmarshal([]byte(policy.Properties.JSON()), &envBindingSpec); err != nil {
log.Logger.Errorf("unmarshal env binding policy failure %s", err.Error())
continue
}
for _, env := range envBindingSpec.Envs {
envBind := &apisv1.EnvBind{
Name: env.Name,
Description: "",
}
if env.Placement.ClusterSelector != nil {
envBind.ClusterSelector = &apisv1.ClusterSelector{
Name: env.Placement.ClusterSelector.Name,
}
}
if env.Placement.NamespaceSelector != nil && envBind.ClusterSelector != nil {
envBind.ClusterSelector.Namespace = env.Placement.NamespaceSelector.Name
}
appBeas.EnvBind = append(appBeas.EnvBind, envBind)
}
for _, envBind := range app.EnvBinds {
apiEnvBind := &apisv1.EnvBind{
Name: envBind.Name,
Alias: envBind.Alias,
Description: envBind.Description,
ClusterSelector: apisv1.ClusterSelector(envBind.ClusterSelector),
}
if envBind.ComponentSelector != nil {
apiEnvBind.ComponentSelector = (*apisv1.ComponentSelector)(envBind.ComponentSelector)
}
appBase.EnvBind = append(appBase.EnvBind, apiEnvBind)
}
// TODO: get and render app status
return appBeas
return appBase
}
// DeleteApplication delete application
func (c *applicationUsecaseImpl) DeleteApplication(ctx context.Context, app *model.ApplicationPlan) error {
// DeleteApplicationPlan delete application plan
func (c *applicationUsecaseImpl) DeleteApplicationPlan(ctx context.Context, app *model.ApplicationPlan) error {
// TODO: check app can be deleted
// query all components to deleted
components, err := c.ListComponents(ctx, app)
components, err := c.ListComponents(ctx, app, apisv1.ListApplicationComponentOptions{})
if err != nil {
return err
}
@@ -854,3 +926,193 @@ func (c *applicationUsecaseImpl) UpdatePolicy(ctx context.Context, app *model.Ap
PolicyBase: *c.converPolicyModelToBase(&policy),
}, nil
}
// UpdateApplicationEnvBindingPlan update application env binding diff
func (c *applicationUsecaseImpl) UpdateApplicationEnvBindingPlan(
ctx context.Context,
app *model.ApplicationPlan,
envName string,
envUpdate apisv1.PutApplicationPlanEnvRequest) (*apisv1.EnvBind, error) {
// update env-binding policy
envBinding, err := c.GetApplicationPlanEnvBindingPolicy(ctx, app)
if err != nil {
return nil, err
}
for i, env := range envBinding.Envs {
if env.Name == envName {
if envUpdate.ComponentSelector == nil {
envBinding.Envs[i].Selector = nil
} else {
envBinding.Envs[i].Selector = &v1alpha1.EnvSelector{
Components: envUpdate.ComponentSelector.Components,
}
}
}
}
properties, err := model.NewJSONStructByStruct(envBinding)
if err != nil {
log.Logger.Errorf("new env binding properties failure,%s", err.Error())
return nil, bcode.ErrInvalidProperties
}
policy := &model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Name: EnvBindPolicyDefaultName,
}
if err := c.ds.Get(ctx, policy); err != nil {
return nil, err
}
policy.Properties = properties
if err := c.ds.Put(ctx, policy); err != nil {
return nil, err
}
var envBind model.EnvBind
// update env-binding base
for i, env := range app.EnvBinds {
if env.Name == envName {
if envUpdate.Description != nil {
app.EnvBinds[i].Description = *envUpdate.Description
}
if envUpdate.Alias != nil {
app.EnvBinds[i].Alias = *envUpdate.Alias
}
if envUpdate.ClusterSelector != nil {
app.EnvBinds[i].ClusterSelector = model.ClusterSelector{
Name: envUpdate.ClusterSelector.Name,
Namespace: envUpdate.ClusterSelector.Namespace,
}
}
if envUpdate.ComponentSelector == nil {
app.EnvBinds[i].ComponentSelector = nil
} else {
app.EnvBinds[i].ComponentSelector = &model.ComponentSelector{
Components: envUpdate.ComponentSelector.Components,
}
}
envBind = *app.EnvBinds[i]
}
}
if err := c.ds.Put(ctx, app); err != nil {
return nil, err
}
re := &apisv1.EnvBind{
Name: envBind.Name,
Alias: envBind.Alias,
Description: envBind.Description,
ClusterSelector: apisv1.ClusterSelector(envBind.ClusterSelector),
}
if envBind.ComponentSelector != nil {
re.ComponentSelector = (*apisv1.ComponentSelector)(envBind.ComponentSelector)
}
return re, nil
}
// CreateApplicationEnvBindingPlan create application env plan
func (c *applicationUsecaseImpl) CreateApplicationEnvBindingPlan(ctx context.Context, app *model.ApplicationPlan, envReq apisv1.CreateApplicationEnvPlanRequest) (*apisv1.EnvBind, error) {
for _, env := range app.EnvBinds {
if env.Name == envReq.Name {
return nil, bcode.ErrApplicationEnvExist
}
}
app.EnvBinds = append(app.EnvBinds, createModelEnvBind(envReq.EnvBind))
envBinding, err := c.GetApplicationPlanEnvBindingPolicy(ctx, app)
if err != nil {
return nil, err
}
envBinding.Envs = append(envBinding.Envs, createEnvBind(envReq.EnvBind))
properties, err := model.NewJSONStructByStruct(envBinding)
if err != nil {
log.Logger.Errorf("new env binding properties failure,%s", err.Error())
return nil, bcode.ErrInvalidProperties
}
policy := &model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Name: EnvBindPolicyDefaultName,
}
if err := c.ds.Get(ctx, policy); err != nil {
return nil, err
}
policy.Properties = properties
if err := c.ds.Put(ctx, policy); err != nil {
return nil, err
}
if err := c.ds.Put(ctx, app); err != nil {
return nil, err
}
return &envReq.EnvBind, nil
}
// DeleteApplicationEnvBindingPlan delete application env binding plan
func (c *applicationUsecaseImpl) DeleteApplicationEnvBindingPlan(ctx context.Context, app *model.ApplicationPlan, envName string) error {
for i, envBind := range app.EnvBinds {
if envBind.Name == envName {
app.EnvBinds = append(app.EnvBinds[0:i], app.EnvBinds[i+1:]...)
}
}
envBinding, err := c.GetApplicationPlanEnvBindingPolicy(ctx, app)
if err != nil {
return err
}
for i, envBind := range envBinding.Envs {
if envBind.Name == envName {
envBinding.Envs = append(envBinding.Envs[0:i], envBinding.Envs[i+1:]...)
}
}
properties, err := model.NewJSONStructByStruct(envBinding)
if err != nil {
log.Logger.Errorf("new env binding properties failure,%s", err.Error())
return bcode.ErrInvalidProperties
}
policy := &model.ApplicationPolicyPlan{
AppPrimaryKey: app.PrimaryKey(),
Name: EnvBindPolicyDefaultName,
}
if err := c.ds.Get(ctx, policy); err != nil {
return err
}
policy.Properties = properties
if err := c.ds.Put(ctx, policy); err != nil {
return err
}
if err := c.ds.Put(ctx, app); err != nil {
return err
}
return nil
}
func createEnvBind(envBind apisv1.EnvBind) v1alpha1.EnvConfig {
placement := v1alpha1.EnvPlacement{
ClusterSelector: &common.ClusterSelector{
Name: envBind.ClusterSelector.Name,
},
}
if envBind.ClusterSelector.Namespace != "" {
placement.NamespaceSelector = &v1alpha1.NamespaceSelector{
Name: envBind.ClusterSelector.Namespace,
}
}
var componentSelector *v1alpha1.EnvSelector
if envBind.ComponentSelector != nil {
componentSelector = &v1alpha1.EnvSelector{
Components: envBind.ComponentSelector.Components,
}
}
return v1alpha1.EnvConfig{
Name: envBind.Name,
Placement: placement,
Selector: componentSelector,
}
}
func createModelEnvBind(envBind apisv1.EnvBind) *model.EnvBind {
re := model.EnvBind{
Name: envBind.Name,
Description: envBind.Description,
Alias: envBind.Alias,
ClusterSelector: model.ClusterSelector(envBind.ClusterSelector),
}
if envBind.ComponentSelector != nil {
re.ComponentSelector = (*model.ComponentSelector)(envBind.ComponentSelector)
}
return &re
}
@@ -54,12 +54,27 @@ var _ = Describe("Test application usecase function", func() {
Name: "test-app",
Namespace: "test-app-namespace",
Description: "this is a test app",
EnvBind: []*v1.EnvBind{{
Name: "dev",
Description: "dev env",
ClusterSelector: v1.ClusterSelector{
Name: "dev",
Namespace: "devnamespace",
},
}, {
Name: "test",
Description: "test env",
ClusterSelector: v1.ClusterSelector{
Name: "dev",
Namespace: "testnamespace",
},
}},
}
base, err := appUsecase.CreateApplication(context.TODO(), req)
base, err := appUsecase.CreateApplicationPlan(context.TODO(), req)
Expect(err).Should(BeNil())
Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty())
_, err = appUsecase.CreateApplication(context.TODO(), req)
_, err = appUsecase.CreateApplicationPlan(context.TODO(), req)
equal := cmp.Equal(err, bcode.ErrApplicationExist, cmpopts.EquateErrors())
Expect(equal).Should(BeTrue())
@@ -74,7 +89,7 @@ var _ = Describe("Test application usecase function", func() {
Labels: map[string]string{"test": "true"},
YamlConfig: string(bs),
}
base, err = appUsecase.CreateApplication(context.TODO(), req)
base, err = appUsecase.CreateApplicationPlan(context.TODO(), req)
Expect(err).Should(BeNil())
Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty())
@@ -86,7 +101,7 @@ var _ = Describe("Test application usecase function", func() {
Labels: map[string]string{"test": "true"},
YamlConfig: "asdasdasdasd",
}
base, err = appUsecase.CreateApplication(context.TODO(), req)
base, err = appUsecase.CreateApplicationPlan(context.TODO(), req)
equal = cmp.Equal(err, bcode.ErrApplicationConfig, cmpopts.EquateErrors())
Expect(equal).Should(BeTrue())
Expect(base).Should(BeNil())
@@ -101,7 +116,7 @@ var _ = Describe("Test application usecase function", func() {
Labels: map[string]string{"test": "true"},
YamlConfig: string(bs),
}
_, err = appUsecase.CreateApplication(context.TODO(), req)
_, err = appUsecase.CreateApplicationPlan(context.TODO(), req)
equal = cmp.Equal(err, bcode.ErrInvalidProperties, cmpopts.EquateErrors())
Expect(equal).Should(BeTrue())
@@ -115,49 +130,68 @@ var _ = Describe("Test application usecase function", func() {
EnvBind: []*v1.EnvBind{
{
Name: "dev",
Alias: "Chinese Word",
Description: "This is a dev env",
ClusterSelector: &v1.ClusterSelector{
ClusterSelector: v1.ClusterSelector{
Name: "dev-cluster",
},
},
{
Name: "prob",
Description: "This is a prob env",
ClusterSelector: &v1.ClusterSelector{
ClusterSelector: v1.ClusterSelector{
Name: "prob-cluster",
Namespace: "prob",
},
},
},
}
appBase, err := appUsecase.CreateApplication(context.TODO(), req)
appBase, err := appUsecase.CreateApplicationPlan(context.TODO(), req)
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(appBase.EnvBind), 2)).Should(BeEmpty())
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd4")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd4")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
Expect(cmp.Diff(len(appBase.EnvBind), 2)).Should(BeEmpty())
})
It("Test GetApplicationPlanEnvBindingPolicy", func() {
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd4")
Expect(err).Should(BeNil())
envBinding, err := appUsecase.GetApplicationPlanEnvBindingPolicy(context.TODO(), appModel)
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(envBinding.Envs), 2)).Should(BeEmpty())
})
It("Test UpdateApplicationPlanEnvBindingDiff", func() {
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
_, err = appUsecase.UpdateApplicationEnvBindingPlan(context.TODO(), appModel, "staging", v1.PutApplicationPlanEnvRequest{
ComponentSelector: &v1.ComponentSelector{Components: []string{"hello-world-server"}},
})
Expect(err).Should(BeNil())
})
It("Test ListApplications function", func() {
apps, err := appUsecase.ListApplications(context.TODO(), v1.ListApplicatioPlanOptions{})
apps, err := appUsecase.ListApplicationPlans(context.TODO(), v1.ListApplicatioPlanOptions{})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(apps), 3)).Should(BeEmpty())
})
It("Test DetailApplication function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
detail, err := appUsecase.DetailApplication(context.TODO(), appModel)
detail, err := appUsecase.DetailApplicationPlan(context.TODO(), appModel)
Expect(err).Should(BeNil())
Expect(cmp.Diff(detail.ResourceInfo.ComponentNum, 2)).Should(BeEmpty())
Expect(cmp.Diff(len(detail.Policies), 1)).Should(BeEmpty())
})
It("Test GetWorkflow function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
@@ -167,7 +201,7 @@ var _ = Describe("Test application usecase function", func() {
})
It("Test ListPolicies function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
@@ -179,19 +213,33 @@ var _ = Describe("Test application usecase function", func() {
})
It("Test ListComponents function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
components, err := appUsecase.ListComponents(context.TODO(), appModel)
components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(components), 2)).Should(BeEmpty())
Expect(cmp.Diff(components[0].ComponentType, "worker")).Should(BeEmpty())
Expect(components[1].UpdateTime).ShouldNot(BeNil())
components, err = appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{
EnvName: "test",
})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(components), 1)).Should(BeEmpty())
Expect(cmp.Diff(components[0].Name, "data-worker")).Should(BeEmpty())
components, err = appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{
EnvName: "staging",
})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(components), 1)).Should(BeEmpty())
Expect(cmp.Diff(components[0].Name, "hello-world-server")).Should(BeEmpty())
})
It("Test DetailComponent function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
@@ -203,18 +251,18 @@ var _ = Describe("Test application usecase function", func() {
})
It("Test DetailPolicy function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
detail, err := appUsecase.DetailPolicy(context.TODO(), appModel, "example-multi-env-policy")
detail, err := appUsecase.DetailPolicy(context.TODO(), appModel, EnvBindPolicyDefaultName)
Expect(err).Should(BeNil())
Expect(cmp.Diff(detail.Type, "env-binding")).Should(BeEmpty())
Expect((*detail.Properties)["envs"]).ShouldNot(BeEmpty())
})
It("Test AddComponent function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
base, err := appUsecase.AddComponent(context.TODO(), appModel, v1.CreateComponentPlanRequest{
@@ -230,7 +278,7 @@ var _ = Describe("Test application usecase function", func() {
})
It("Test DetailComponent function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
detailResponse, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2")
@@ -241,11 +289,11 @@ var _ = Describe("Test application usecase function", func() {
})
It("Test AddPolicy function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
_, err = appUsecase.AddPolicy(context.TODO(), appModel, v1.CreatePolicyRequest{
Name: "example-multi-env-policy",
Name: EnvBindPolicyDefaultName,
Description: "this is a test2 policy",
Type: "env-binding",
Properties: ``,
@@ -259,8 +307,9 @@ var _ = Describe("Test application usecase function", func() {
})
Expect(err).Should(BeNil())
})
It("Test DetailPolicy function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
detail, err := appUsecase.DetailPolicy(context.TODO(), appModel, "env-binding-2")
@@ -268,8 +317,9 @@ var _ = Describe("Test application usecase function", func() {
Expect(detail.Properties).ShouldNot(BeNil())
Expect((*detail.Properties)["envs"]).ShouldNot(BeEmpty())
})
It("Test UpdatePolicy function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
base, err := appUsecase.UpdatePolicy(context.TODO(), appModel, "env-binding-2", v1.UpdatePolicyRequest{
@@ -281,21 +331,75 @@ var _ = Describe("Test application usecase function", func() {
Expect((*base.Properties)["envs"]).Should(BeEmpty())
})
It("Test DeletePolicy function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
err = appUsecase.DeletePolicy(context.TODO(), appModel, "env-binding-2")
Expect(err).Should(BeNil())
})
It("Test DeleteComponent function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
err = appUsecase.DeleteComponent(context.TODO(), appModel, "test2")
Expect(err).Should(BeNil())
})
It("Test CreateApplicationEnvBindingPlan function", func() {
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
env, err := appUsecase.CreateApplicationEnvBindingPlan(context.TODO(), appModel, v1.CreateApplicationEnvPlanRequest{
EnvBind: v1.EnvBind{
Name: "prod2",
Alias: "生产环境",
Description: "这是一个用户某客户的生产环境",
ClusterSelector: v1.ClusterSelector{
Name: "prob",
},
},
})
Expect(err).Should(BeNil())
Expect(env).ShouldNot(BeNil())
appModelNew, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(appModelNew.EnvBinds), 4)).Should(BeEmpty())
spec, err := appUsecase.GetApplicationPlanEnvBindingPolicy(context.TODO(), appModelNew)
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(spec.Envs), 4)).Should(BeEmpty())
})
It("Test CreateApplicationEnvBindingPlan function", func() {
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
env, err := appUsecase.UpdateApplicationEnvBindingPlan(context.TODO(), appModel, "prod2", v1.PutApplicationPlanEnvRequest{
ComponentSelector: &v1.ComponentSelector{
Components: []string{},
},
})
Expect(err).Should(BeNil())
Expect(env).ShouldNot(BeNil())
components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{
EnvName: "prod2",
})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(components), 0)).Should(BeEmpty())
})
It("Test DeleteApplicationEnvBindingPlan function", func() {
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
err = appUsecase.DeleteApplicationEnvBindingPlan(context.TODO(), appModel, "prod2")
Expect(err).Should(BeNil())
})
It("Test Deploy Application function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
res, err := appUsecase.Deploy(context.TODO(), appModel, v1.ApplicationDeployRequest{
@@ -311,12 +415,13 @@ var _ = Describe("Test application usecase function", func() {
Expect(cmp.Diff(len(oam.Spec.Components), 2)).Should(BeEmpty())
Expect(cmp.Diff(len(oam.Spec.Policies), 1)).Should(BeEmpty())
})
It("Test DeleteApplication function", func() {
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
appModel, err := appUsecase.GetApplicationPlan(context.TODO(), "test-app-sadasd")
Expect(err).Should(BeNil())
err = appUsecase.DeleteApplication(context.TODO(), appModel)
err = appUsecase.DeleteApplicationPlan(context.TODO(), appModel)
Expect(err).Should(BeNil())
components, err := appUsecase.ListComponents(context.TODO(), appModel)
components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{})
Expect(err).Should(BeNil())
Expect(cmp.Diff(len(components), 0)).Should(BeEmpty())
policies, err := appUsecase.ListPolicies(context.TODO(), appModel)
+12 -3
View File
@@ -23,7 +23,7 @@ var ErrApplicationConfig = NewBcode(400, 10000, "application config does not com
var ErrComponentTypeNotSupport = NewBcode(400, 10001, "An unsupported component type was used.")
// ErrApplicationExist application is exist
var ErrApplicationExist = NewBcode(400, 10002, "application name is exist")
var ErrApplicationExist = NewBcode(400, 10002, "application plan name is exist")
// ErrInvalidProperties properties(trait or component or others) is invalid
var ErrInvalidProperties = NewBcode(400, 10003, "properties is invalid")
@@ -38,10 +38,10 @@ var ErrDeployApplyFail = NewBcode(500, 10005, "application deploy apply failure"
var ErrNoComponent = NewBcode(200, 10006, "application not have components, can not deploy")
// ErrApplicationComponetExist application component is exist
var ErrApplicationComponetExist = NewBcode(400, 10007, "application component is exist")
var ErrApplicationComponetExist = NewBcode(400, 10007, "application component plan is exist")
// ErrApplicationComponetNotExist application component is not exist
var ErrApplicationComponetNotExist = NewBcode(404, 10008, "application component is not exist")
var ErrApplicationComponetNotExist = NewBcode(404, 10008, "application component plan is not exist")
// ErrApplicationPolicyExist application policy is exist
var ErrApplicationPolicyExist = NewBcode(400, 10009, "application policy is exist")
@@ -51,3 +51,12 @@ var ErrApplicationPolicyNotExist = NewBcode(404, 10010, "application policy is n
// ErrCreateNamespace auto create namespace failure before deploy app
var ErrCreateNamespace = NewBcode(500, 10011, "auto create namespace failure")
// ErrApplicationNotExist application is not exist
var ErrApplicationNotExist = NewBcode(404, 10012, "application plan name is not exist")
// ErrApplicationNotEnv no env binding policy
var ErrApplicationNotEnv = NewBcode(404, 10013, "application plan not set env binding policy")
// ErrApplicationEnvExist application env is exist
var ErrApplicationEnvExist = NewBcode(400, 10014, "application env plan is exist")
@@ -29,18 +29,18 @@ import (
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
)
type applicationWebService struct {
type applicationPlanWebService struct {
applicationUsecase usecase.ApplicationUsecase
}
// NewApplicationWebService new application manage webservice
func NewApplicationWebService(applicationUsecase usecase.ApplicationUsecase) WebService {
return &applicationWebService{
// NewApplicationPlanWebService new application manage webservice
func NewApplicationPlanWebService(applicationUsecase usecase.ApplicationUsecase) WebService {
return &applicationPlanWebService{
applicationUsecase: applicationUsecase,
}
}
func (c *applicationWebService) GetWebService() *restful.WebService {
func (c *applicationPlanWebService) GetWebService() *restful.WebService {
ws := new(restful.WebService)
ws.Path(versionPrefix+"/applicationplans").
Consumes(restful.MIME_XML, restful.MIME_JSON).
@@ -49,8 +49,8 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
tags := []string{"application"}
ws.Route(ws.GET("/").To(c.listApplications).
Doc("list all applications").
ws.Route(ws.GET("/").To(c.listApplicationPlans).
Doc("list all application plans").
Metadata(restfulspec.KeyOpenAPITags, tags).
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
Param(ws.QueryParameter("namespace", "Namespace-based search").DataType("string")).
@@ -59,37 +59,80 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
Returns(400, "", bcode.Bcode{}).
Writes(apis.ListApplicationPlanResponse{}))
ws.Route(ws.POST("/").To(c.createApplication).
Doc("create one application").
ws.Route(ws.POST("/").To(c.createApplicationPlan).
Doc("create one application plan").
Metadata(restfulspec.KeyOpenAPITags, tags).
Reads(apis.CreateApplicationPlanRequest{}).
Returns(200, "", apis.ApplicationPlanBase{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.ApplicationPlanBase{}))
ws.Route(ws.DELETE("/{name}").To(c.deleteApplication).
ws.Route(ws.DELETE("/{name}").To(c.deleteApplicationPlan).
Doc("delete one application").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Returns(200, "", apis.EmptyResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.EmptyResponse{}))
ws.Route(ws.GET("/{name}").To(c.detailApplication).
Doc("detail one application").
ws.Route(ws.GET("/{name}").To(c.detailApplicationPlan).
Doc("detail one application plan").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Returns(200, "", apis.DetailApplicationPlanResponse{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.DetailApplicationPlanResponse{}))
ws.Route(ws.PUT("/{name}").To(c.updateApplicationPlan).
Doc("update one application plan").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Reads(apis.UpdateApplicationPlanRequest{}).
Returns(200, "", apis.ApplicationPlanBase{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.ApplicationPlanBase{}))
ws.Route(ws.PUT("/{name}/envs/{envName}").To(c.updateApplicationEnvBinding).
Doc("set application plan differences in the specified environment").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Filter(c.envCheckFilter).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Param(ws.PathParameter("envName", "identifier of the application plan").DataType("string")).
Reads(apis.PutApplicationPlanEnvRequest{}).
Returns(200, "", apis.EnvBind{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.EnvBind{}))
ws.Route(ws.POST("/{name}/envs").To(c.createApplicationEnv).
Doc("creating an application environment plan").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Reads(apis.CreateApplicationEnvPlanRequest{}).
Returns(200, "", apis.EnvBind{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.EmptyResponse{}))
ws.Route(ws.DELETE("/{name}/envs/{envName}").To(c.deleteApplicationEnv).
Doc("delete an application environment plan").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Filter(c.envCheckFilter).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Param(ws.PathParameter("envName", "identifier of the application plan").DataType("string")).
Returns(200, "", apis.EmptyResponse{}).
Returns(404, "", bcode.Bcode{}).
Writes(apis.EmptyResponse{}))
ws.Route(ws.POST("/{name}/template").To(c.publishApplicationTemplate).
Doc("create one application template").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Reads(apis.CreateApplicationTemplateRequest{}).
Returns(200, "", apis.ApplicationTemplateBase{}).
Returns(400, "", bcode.Bcode{}).
@@ -99,7 +142,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
Doc("deploy or upgrade the application").
Metadata(restfulspec.KeyOpenAPITags, tags).
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Returns(200, "", apis.ApplicationDeployRequest{}).
Returns(400, "", bcode.Bcode{}).
Writes(apis.ApplicationDeployResponse{}))
@@ -107,7 +150,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
ws.Route(ws.GET("/{name}/componentplans").To(c.listApplicationComponents).
Doc("gets the componentplan topology of the application").
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Param(ws.QueryParameter("envName", "list components that deployed in define env").DataType("string")).
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", apis.ComponentPlanListResponse{}).
@@ -117,7 +160,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
ws.Route(ws.POST("/{name}/componentplans").To(c.createComponent).
Doc("create component plan for application plan").
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Metadata(restfulspec.KeyOpenAPITags, tags).
Reads(apis.CreateComponentPlanRequest{}).
Returns(200, "", apis.ComponentPlanBase{}).
@@ -127,7 +170,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
ws.Route(ws.GET("/{name}/componentplans/{componentName}").To(c.detailComponent).
Doc("detail component plan for application plan").
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", apis.DetailComponentPlanResponse{}).
Returns(400, "", bcode.Bcode{}).
@@ -136,7 +179,7 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
ws.Route(ws.GET("/{name}/policies").To(c.listApplicationPolicies).
Doc("list policy for application").
Filter(c.appCheckFilter).
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
Param(ws.PathParameter("name", "identifier of the application plan").DataType("string")).
Metadata(restfulspec.KeyOpenAPITags, tags).
Returns(200, "", apis.ListApplicationPolicy{}).
Returns(400, "", bcode.Bcode{}).
@@ -185,8 +228,8 @@ func (c *applicationWebService) GetWebService() *restful.WebService {
return ws
}
func (c *applicationWebService) appCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
app, err := c.applicationUsecase.GetApplication(req.Request.Context(), req.PathParameter("name"))
func (c *applicationPlanWebService) appCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
app, err := c.applicationUsecase.GetApplicationPlan(req.Request.Context(), req.PathParameter("name"))
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -195,7 +238,24 @@ func (c *applicationWebService) appCheckFilter(req *restful.Request, res *restfu
chain.ProcessFilter(req, res)
}
func (c *applicationWebService) createApplication(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) envCheckFilter(req *restful.Request, res *restful.Response, chain *restful.FilterChain) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
envBinding, err := c.applicationUsecase.GetApplicationPlanEnvBindingPolicy(req.Request.Context(), app)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
for _, env := range envBinding.Envs {
if env.Name == req.PathParameter("envName") {
req.Request = req.Request.WithContext(context.WithValue(req.Request.Context(), &apis.CtxKeyApplicationEnvBinding, env))
chain.ProcessFilter(req, res)
return
}
}
bcode.ReturnError(req, res, bcode.ErrApplicationNotEnv)
}
func (c *applicationPlanWebService) createApplicationPlan(req *restful.Request, res *restful.Response) {
// Verify the validity of parameters
var createReq apis.CreateApplicationPlanRequest
if err := req.ReadEntity(&createReq); err != nil {
@@ -207,7 +267,7 @@ func (c *applicationWebService) createApplication(req *restful.Request, res *res
return
}
// Call the usecase layer code
appBase, err := c.applicationUsecase.CreateApplication(req.Request.Context(), createReq)
appBase, err := c.applicationUsecase.CreateApplicationPlan(req.Request.Context(), createReq)
if err != nil {
log.Logger.Errorf("create application failure %s", err.Error())
bcode.ReturnError(req, res, err)
@@ -221,8 +281,8 @@ func (c *applicationWebService) createApplication(req *restful.Request, res *res
}
}
func (c *applicationWebService) listApplications(req *restful.Request, res *restful.Response) {
apps, err := c.applicationUsecase.ListApplications(req.Request.Context(), apis.ListApplicatioPlanOptions{
func (c *applicationPlanWebService) listApplicationPlans(req *restful.Request, res *restful.Response) {
apps, err := c.applicationUsecase.ListApplicationPlans(req.Request.Context(), apis.ListApplicatioPlanOptions{
Namespace: req.QueryParameter("namespace"),
Cluster: req.QueryParameter("cluster"),
Query: req.QueryParameter("query"),
@@ -237,9 +297,9 @@ func (c *applicationWebService) listApplications(req *restful.Request, res *rest
}
}
func (c *applicationWebService) detailApplication(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) detailApplicationPlan(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
detail, err := c.applicationUsecase.DetailApplication(req.Request.Context(), app)
detail, err := c.applicationUsecase.DetailApplicationPlan(req.Request.Context(), app)
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -250,7 +310,7 @@ func (c *applicationWebService) detailApplication(req *restful.Request, res *res
}
}
func (c *applicationWebService) publishApplicationTemplate(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) publishApplicationTemplate(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
base, err := c.applicationUsecase.PublishApplicationTemplate(req.Request.Context(), app)
if err != nil {
@@ -264,7 +324,7 @@ func (c *applicationWebService) publishApplicationTemplate(req *restful.Request,
}
// deployApplication TODO: return event model
func (c *applicationWebService) deployApplication(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) deployApplication(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var createReq apis.ApplicationDeployRequest
@@ -287,9 +347,9 @@ func (c *applicationWebService) deployApplication(req *restful.Request, res *res
}
}
func (c *applicationWebService) deleteApplication(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) deleteApplicationPlan(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
err := c.applicationUsecase.DeleteApplication(req.Request.Context(), app)
err := c.applicationUsecase.DeleteApplicationPlan(req.Request.Context(), app)
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -300,9 +360,11 @@ func (c *applicationWebService) deleteApplication(req *restful.Request, res *res
}
}
func (c *applicationWebService) listApplicationComponents(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) listApplicationComponents(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
components, err := c.applicationUsecase.ListComponents(req.Request.Context(), app)
components, err := c.applicationUsecase.ListComponents(req.Request.Context(), app, apis.ListApplicationComponentOptions{
EnvName: req.QueryParameter("envName"),
})
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -313,7 +375,7 @@ func (c *applicationWebService) listApplicationComponents(req *restful.Request,
}
}
func (c *applicationWebService) createComponent(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) createComponent(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var createReq apis.CreateComponentPlanRequest
@@ -336,7 +398,7 @@ func (c *applicationWebService) createComponent(req *restful.Request, res *restf
}
}
func (c *applicationWebService) detailComponent(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) detailComponent(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
detail, err := c.applicationUsecase.DetailComponent(req.Request.Context(), app, req.PathParameter("componentName"))
if err != nil {
@@ -349,7 +411,7 @@ func (c *applicationWebService) detailComponent(req *restful.Request, res *restf
}
}
func (c *applicationWebService) createApplicationPolicy(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) createApplicationPolicy(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var createReq apis.CreatePolicyRequest
@@ -372,7 +434,7 @@ func (c *applicationWebService) createApplicationPolicy(req *restful.Request, re
}
}
func (c *applicationWebService) listApplicationPolicies(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) listApplicationPolicies(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
policies, err := c.applicationUsecase.ListPolicies(req.Request.Context(), app)
if err != nil {
@@ -385,7 +447,7 @@ func (c *applicationWebService) listApplicationPolicies(req *restful.Request, re
}
}
func (c *applicationWebService) detailApplicationPolicy(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) detailApplicationPolicy(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
detail, err := c.applicationUsecase.DetailPolicy(req.Request.Context(), app, req.PathParameter("policyName"))
if err != nil {
@@ -398,7 +460,7 @@ func (c *applicationWebService) detailApplicationPolicy(req *restful.Request, re
}
}
func (c *applicationWebService) deleteApplicationPolicy(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) deleteApplicationPolicy(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
err := c.applicationUsecase.DeletePolicy(req.Request.Context(), app, req.PathParameter("policyName"))
if err != nil {
@@ -411,7 +473,7 @@ func (c *applicationWebService) deleteApplicationPolicy(req *restful.Request, re
}
}
func (c *applicationWebService) updateApplicationPolicy(req *restful.Request, res *restful.Response) {
func (c *applicationPlanWebService) updateApplicationPolicy(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var updateReq apis.UpdatePolicyRequest
@@ -433,3 +495,85 @@ func (c *applicationWebService) updateApplicationPolicy(req *restful.Request, re
return
}
}
func (c *applicationPlanWebService) updateApplicationEnvBinding(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var updateReq apis.PutApplicationPlanEnvRequest
if err := req.ReadEntity(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := validate.Struct(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
diff, err := c.applicationUsecase.UpdateApplicationEnvBindingPlan(req.Request.Context(), app, req.PathParameter("envName"), updateReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(diff); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *applicationPlanWebService) updateApplicationPlan(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var updateReq apis.UpdateApplicationPlanRequest
if err := req.ReadEntity(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := validate.Struct(&updateReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
base, err := c.applicationUsecase.UpdateApplicationPlan(req.Request.Context(), app, updateReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(base); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *applicationPlanWebService) createApplicationEnv(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
// Verify the validity of parameters
var createReq apis.CreateApplicationEnvPlanRequest
if err := req.ReadEntity(&createReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := validate.Struct(&createReq); err != nil {
bcode.ReturnError(req, res, err)
return
}
base, err := c.applicationUsecase.CreateApplicationEnvBindingPlan(req.Request.Context(), app, createReq)
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(base); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
func (c *applicationPlanWebService) deleteApplicationEnv(req *restful.Request, res *restful.Response) {
app := req.Request.Context().Value(&apis.CtxKeyApplication).(*model.ApplicationPlan)
err := c.applicationUsecase.DeleteApplicationEnvBindingPlan(req.Request.Context(), app, req.PathParameter("envName"))
if err != nil {
bcode.ReturnError(req, res, err)
return
}
if err := res.WriteEntity(apis.EmptyResponse{}); err != nil {
bcode.ReturnError(req, res, err)
return
}
}
@@ -52,5 +52,19 @@ var _ = Describe("Test validate function", func() {
}
err = validate.Struct(&app3)
Expect(err).Should(BeNil())
var app4 = apisv1.CreateApplicationPlanRequest{
Name: "asdasd-asdasd",
Namespace: "namespace",
}
err = validate.Struct(&app4)
Expect(err).Should(BeNil())
var component = apisv1.CreateComponentPlanRequest{
Name: "asdasd-asdasd",
ComponentType: "alibaba-ack",
}
err = validate.Struct(&component)
Expect(err).Should(BeNil())
})
})
+1 -1
View File
@@ -68,7 +68,7 @@ func Init(ctx context.Context, ds datastore.DataStore) {
definitionUsecase := usecase.NewDefinitionUsecase()
addonUsecase := usecase.NewAddonUsecase(ds)
RegistWebService(NewClusterWebService(clusterUsecase))
RegistWebService(NewApplicationWebService(applicationUsecase))
RegistWebService(NewApplicationPlanWebService(applicationUsecase))
RegistWebService(NewNamespaceWebService(namespaceUsecase))
RegistWebService(NewDefinitionWebservice(definitionUsecase))
RegistWebService(NewAddonWebService(addonUsecase))
+2 -2
View File
@@ -125,7 +125,7 @@ func (w *workflowWebService) listApplicationWorkflows(req *restful.Request, res
bcode.ReturnError(req, res, bcode.ErrMustQueryByApp)
return
}
app, err := w.applicationUsecase.GetApplication(req.Request.Context(), req.QueryParameter("appName"))
app, err := w.applicationUsecase.GetApplicationPlan(req.Request.Context(), req.QueryParameter("appName"))
if err != nil {
bcode.ReturnError(req, res, err)
return
@@ -157,7 +157,7 @@ func (w *workflowWebService) createApplicationWorkflow(req *restful.Request, res
bcode.ReturnError(req, res, err)
return
}
app, err := w.applicationUsecase.GetApplication(req.Request.Context(), createReq.AppName)
app, err := w.applicationUsecase.GetApplicationPlan(req.Request.Context(), createReq.AppName)
if err != nil {
bcode.ReturnError(req, res, err)
return
+1 -1
View File
@@ -42,7 +42,7 @@ var _ = Describe("Test application rest api", func() {
Description: "this is a test app",
Icon: "",
Labels: map[string]string{"test": "true"},
EnvBind: []*apisv1.EnvBind{{Name: "dev-env", ClusterSelector: &apisv1.ClusterSelector{
EnvBind: []*apisv1.EnvBind{{Name: "dev-env", ClusterSelector: apisv1.ClusterSelector{
Name: "dev-cluster",
}}},
}
+14
View File
@@ -0,0 +1,14 @@
{
"appName": "appplanName",
"name": "workflowName",
"alias": "workflowAlias",
"description": "workflow plan description",
"enable": true,
"default": true,
"steps": [
{ "name": "deploy-test",
"type": "deploy2env",
"properties":""
}
]
}