mirror of
https://github.com/kubevela/kubevela.git
synced 2026-03-03 02:01:05 +00:00
Compare commits
7 Commits
v1.2.0-bet
...
v1.2.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad4b44696a | ||
|
|
1563c582bc | ||
|
|
3f2e76c75a | ||
|
|
f7ebbf4fa0 | ||
|
|
330c3e269c | ||
|
|
41e6a895a1 | ||
|
|
e8f2b79721 |
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -105,7 +105,7 @@ jobs:
|
||||
path: ./_bin/sha256-${{ steps.get_matrix.outputs.OS }}-${{ steps.get_matrix.outputs.ARCH }}.txt
|
||||
retention-days: 1
|
||||
|
||||
upload-sha256sums-plugin-homebrew:
|
||||
upload-plugin-homebrew:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
name: upload-sha256sums
|
||||
@@ -119,7 +119,12 @@ jobs:
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: sha256sums
|
||||
path: cli-artifacts
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
working-directory: cli-artifacts
|
||||
- shell: bash
|
||||
working-directory: cli-artifacts
|
||||
run: |
|
||||
for file in *
|
||||
do
|
||||
@@ -129,7 +134,7 @@ jobs:
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
with:
|
||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
||||
asset_path: sha256sums.txt
|
||||
asset_path: cli-artifacts/sha256sums.txt
|
||||
asset_name: sha256sums.txt
|
||||
asset_content_type: text/plain
|
||||
- name: Update kubectl plugin version in krew-index
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
FROM node:14.17
|
||||
FROM node:16.9.0
|
||||
WORKDIR /workspace
|
||||
COPY website-dev.sh /workspace
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ type Application struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Project string `json:"project"`
|
||||
Namespace string `json:"namespace"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
@@ -57,6 +58,9 @@ func (a *Application) Index() map[string]string {
|
||||
if a.Namespace != "" {
|
||||
index["namespace"] = a.Namespace
|
||||
}
|
||||
if a.Project != "" {
|
||||
index["project"] = a.Project
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ func init() {
|
||||
type DeliveryTarget struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
Project string `json:"project"`
|
||||
Namespace string `json:"namespace"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
@@ -51,6 +52,9 @@ func (d *DeliveryTarget) Index() map[string]string {
|
||||
if d.Namespace != "" {
|
||||
index["namespace"] = d.Namespace
|
||||
}
|
||||
if d.Project != "" {
|
||||
index["project"] = d.Project
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
|
||||
53
pkg/apiserver/model/project.go
Normal file
53
pkg/apiserver/model/project.go
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package model
|
||||
|
||||
func init() {
|
||||
RegistModel(&Project{})
|
||||
}
|
||||
|
||||
// Project project model
|
||||
type Project struct {
|
||||
Model
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Description string `json:"description,omitempty"`
|
||||
// Namespace Control cluster namespace
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
// TableName return custom table name
|
||||
func (p *Project) TableName() string {
|
||||
return tableNamePrefix + "project"
|
||||
}
|
||||
|
||||
// PrimaryKey return custom primary key
|
||||
func (p *Project) PrimaryKey() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
// Index return custom index
|
||||
func (p *Project) Index() map[string]string {
|
||||
index := make(map[string]string)
|
||||
if p.Name != "" {
|
||||
index["name"] = p.Name
|
||||
}
|
||||
if p.Namespace != "" {
|
||||
index["namespace"] = p.Namespace
|
||||
}
|
||||
return index
|
||||
}
|
||||
@@ -58,6 +58,12 @@ const (
|
||||
// EmptyResponse empty response, it will used for delete api
|
||||
type EmptyResponse struct{}
|
||||
|
||||
// NameAlias name and alias
|
||||
type NameAlias struct {
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
}
|
||||
|
||||
// CreateAddonRegistryRequest defines the format for addon registry create request
|
||||
type CreateAddonRegistryRequest struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
@@ -253,7 +259,7 @@ type ClusterBase struct {
|
||||
|
||||
// ListApplicatioOptions list application query options
|
||||
type ListApplicatioOptions struct {
|
||||
Namespace string `json:"namespace"`
|
||||
Project string `json:"project"`
|
||||
TargetName string `json:"targetName"`
|
||||
Query string `json:"query"`
|
||||
}
|
||||
@@ -280,7 +286,7 @@ func (e EnvBindingList) ContainTarget(name string) bool {
|
||||
type ApplicationBase struct {
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Namespace string `json:"namespace"`
|
||||
Project *ProjectBase `json:"project"`
|
||||
Description string `json:"description"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
@@ -306,7 +312,7 @@ type ApplicationStatisticsResponse struct {
|
||||
type CreateApplicationRequest struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Alias string `json:"alias" validate:"checkalias" optional:"true"`
|
||||
Namespace string `json:"namespace" validate:"checkname"`
|
||||
Project string `json:"project" validate:"checkname"`
|
||||
Description string `json:"description" optional:"true"`
|
||||
Icon string `json:"icon"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
@@ -334,15 +340,15 @@ type EnvBinding struct {
|
||||
|
||||
// EnvBindingBase application env binding
|
||||
type EnvBindingBase struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Alias string `json:"alias" validate:"checkalias" optional:"true"`
|
||||
Description string `json:"description,omitempty" optional:"true"`
|
||||
TargetNames []string `json:"targetNames"`
|
||||
Targets []DeliveryTargetBase `json:"deliveryTargets,omitempty"`
|
||||
ComponentSelector *ComponentSelector `json:"componentSelector" optional:"true"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
AppDeployName string `json:"appDeployName"`
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Alias string `json:"alias" validate:"checkalias" optional:"true"`
|
||||
Description string `json:"description,omitempty" optional:"true"`
|
||||
TargetNames []string `json:"targetNames"`
|
||||
Targets []NameAlias `json:"deliveryTargets,omitempty"`
|
||||
ComponentSelector *ComponentSelector `json:"componentSelector" optional:"true"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
AppDeployName string `json:"appDeployName"`
|
||||
}
|
||||
|
||||
// DetailEnvBindingResponse defines the response of env-binding details
|
||||
@@ -456,28 +462,26 @@ type ApplicationTemplateVersion struct {
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
}
|
||||
|
||||
// ListNamespaceResponse namesace list model
|
||||
type ListNamespaceResponse struct {
|
||||
Namespaces []NamespaceBase `json:"namespaces"`
|
||||
// ListProjectResponse list project response body
|
||||
type ListProjectResponse struct {
|
||||
Projects []*ProjectBase `json:"projects"`
|
||||
}
|
||||
|
||||
// NamespaceBase namespace base model
|
||||
type NamespaceBase struct {
|
||||
// ProjectBase project base model
|
||||
type ProjectBase struct {
|
||||
Name string `json:"name"`
|
||||
Alias string `json:"alias"`
|
||||
Description string `json:"description"`
|
||||
Namespace string `json:"namespace"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
}
|
||||
|
||||
// CreateNamespaceRequest create namespace request body
|
||||
type CreateNamespaceRequest struct {
|
||||
// CreateProjectRequest create project request body
|
||||
type CreateProjectRequest struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// NamespaceDetailResponse namespace detail response
|
||||
type NamespaceDetailResponse struct {
|
||||
NamespaceBase
|
||||
Alias string `json:"alias" validate:"checkalias" optional:"true"`
|
||||
Description string `json:"description" optional:"true"`
|
||||
}
|
||||
|
||||
// ListDefinitionResponse list definition response model
|
||||
@@ -705,7 +709,7 @@ type ApplicationTrait struct {
|
||||
// CreateDeliveryTargetRequest create delivery target request body
|
||||
type CreateDeliveryTargetRequest struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Namespace string `json:"namespace" validate:"checkname"`
|
||||
Project string `json:"project" validate:"checkname"`
|
||||
Alias string `json:"alias,omitempty" validate:"checkalias" optional:"true"`
|
||||
Description string `json:"description,omitempty" optional:"true"`
|
||||
Cluster *ClusterTarget `json:"cluster,omitempty"`
|
||||
@@ -731,16 +735,16 @@ type DetailDeliveryTargetResponse struct {
|
||||
DeliveryTargetBase
|
||||
}
|
||||
|
||||
// ListDeliveryTargetResponse list delivery target response body
|
||||
type ListDeliveryTargetResponse struct {
|
||||
DeliveryTargets []DeliveryTargetBase `json:"deliveryTargets"`
|
||||
Total int64 `json:"total"`
|
||||
// ListTargetResponse list delivery target response body
|
||||
type ListTargetResponse struct {
|
||||
Targets []DeliveryTargetBase `json:"targets"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// DeliveryTargetBase deliveryTarget base model
|
||||
type DeliveryTargetBase struct {
|
||||
Name string `json:"name" validate:"checkname"`
|
||||
Namespace string `json:"namespace" validate:"checkname"`
|
||||
Name string `json:"name"`
|
||||
Project *ProjectBase `json:"project"`
|
||||
Alias string `json:"alias,omitempty" validate:"checkalias" optional:"true"`
|
||||
Description string `json:"description,omitempty" optional:"true"`
|
||||
Cluster *ClusterTarget `json:"cluster,omitempty"`
|
||||
|
||||
@@ -97,10 +97,17 @@ type applicationUsecaseImpl struct {
|
||||
envBindingUsecase EnvBindingUsecase
|
||||
deliveryTargetUsecase DeliveryTargetUsecase
|
||||
definitionUsecase DefinitionUsecase
|
||||
projectUsecase ProjectUsecase
|
||||
}
|
||||
|
||||
// NewApplicationUsecase new application usecase
|
||||
func NewApplicationUsecase(ds datastore.DataStore, workflowUsecase WorkflowUsecase, envBindingUsecase EnvBindingUsecase, deliveryTargetUsecase DeliveryTargetUsecase, definitionUsecase DefinitionUsecase) ApplicationUsecase {
|
||||
func NewApplicationUsecase(ds datastore.DataStore,
|
||||
workflowUsecase WorkflowUsecase,
|
||||
envBindingUsecase EnvBindingUsecase,
|
||||
deliveryTargetUsecase DeliveryTargetUsecase,
|
||||
definitionUsecase DefinitionUsecase,
|
||||
projectUsecase ProjectUsecase,
|
||||
) ApplicationUsecase {
|
||||
kubecli, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
log.Logger.Fatalf("get kubeclient failure %s", err.Error())
|
||||
@@ -113,14 +120,15 @@ func NewApplicationUsecase(ds datastore.DataStore, workflowUsecase WorkflowUseca
|
||||
kubeClient: kubecli,
|
||||
apply: apply.NewAPIApplicator(kubecli),
|
||||
definitionUsecase: definitionUsecase,
|
||||
projectUsecase: projectUsecase,
|
||||
}
|
||||
}
|
||||
|
||||
// ListApplications list applications
|
||||
func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptions apisv1.ListApplicatioOptions) ([]*apisv1.ApplicationBase, error) {
|
||||
var app = model.Application{}
|
||||
if listOptions.Namespace != "" {
|
||||
app.Namespace = listOptions.Namespace
|
||||
if listOptions.Project != "" {
|
||||
app.Project = listOptions.Project
|
||||
}
|
||||
entitys, err := c.ds.List(ctx, &app, &datastore.ListOptions{})
|
||||
if err != nil {
|
||||
@@ -129,7 +137,7 @@ func (c *applicationUsecaseImpl) ListApplications(ctx context.Context, listOptio
|
||||
var list []*apisv1.ApplicationBase
|
||||
for _, entity := range entitys {
|
||||
appModel := entity.(*model.Application)
|
||||
appBase := c.converAppModelToBase(appModel)
|
||||
appBase := c.converAppModelToBase(ctx, appModel)
|
||||
if listOptions.Query != "" &&
|
||||
!(strings.Contains(appBase.Alias, listOptions.Query) ||
|
||||
strings.Contains(appBase.Name, listOptions.Query) ||
|
||||
@@ -166,7 +174,7 @@ func (c *applicationUsecaseImpl) GetApplication(ctx context.Context, appName str
|
||||
|
||||
// DetailApplication detail application info
|
||||
func (c *applicationUsecaseImpl) DetailApplication(ctx context.Context, app *model.Application) (*apisv1.DetailApplicationResponse, error) {
|
||||
base := c.converAppModelToBase(app)
|
||||
base := c.converAppModelToBase(ctx, app)
|
||||
policys, err := c.queryApplicationPolicys(ctx, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -255,19 +263,27 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis
|
||||
Name: req.Name,
|
||||
Alias: req.Alias,
|
||||
Description: req.Description,
|
||||
Namespace: req.Namespace,
|
||||
Icon: req.Icon,
|
||||
Labels: req.Labels,
|
||||
}
|
||||
// check app name.
|
||||
exit, err := c.ds.IsExist(ctx, &application)
|
||||
exist, err := c.ds.IsExist(ctx, &application)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("check application name is exist failure %s", err.Error())
|
||||
return nil, bcode.ErrApplicationExist
|
||||
}
|
||||
if exit {
|
||||
if exist {
|
||||
return nil, bcode.ErrApplicationExist
|
||||
}
|
||||
|
||||
// check project
|
||||
project, err := c.projectUsecase.GetProject(ctx, req.Project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
application.Namespace = project.Namespace
|
||||
application.Project = project.Name
|
||||
|
||||
if req.YamlConfig != "" {
|
||||
var oamApp v1beta1.Application
|
||||
if err := yaml.Unmarshal([]byte(req.YamlConfig), &oamApp); err != nil {
|
||||
@@ -310,7 +326,7 @@ func (c *applicationUsecaseImpl) CreateApplication(ctx context.Context, req apis
|
||||
return nil, err
|
||||
}
|
||||
// render app base info.
|
||||
base := c.converAppModelToBase(&application)
|
||||
base := c.converAppModelToBase(ctx, &application)
|
||||
return base, nil
|
||||
}
|
||||
|
||||
@@ -355,7 +371,7 @@ func (c *applicationUsecaseImpl) UpdateApplication(ctx context.Context, app *mod
|
||||
if err := c.ds.Put(ctx, app); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.converAppModelToBase(app), nil
|
||||
return c.converAppModelToBase(ctx, app), nil
|
||||
}
|
||||
|
||||
func (c *applicationUsecaseImpl) saveApplicationComponent(ctx context.Context, app *model.Application, components []common.ApplicationComponent) error {
|
||||
@@ -831,17 +847,23 @@ func (c *applicationUsecaseImpl) renderOAMApplication(ctx context.Context, appMo
|
||||
return app, nil
|
||||
}
|
||||
|
||||
func (c *applicationUsecaseImpl) converAppModelToBase(app *model.Application) *apisv1.ApplicationBase {
|
||||
func (c *applicationUsecaseImpl) converAppModelToBase(ctx context.Context, app *model.Application) *apisv1.ApplicationBase {
|
||||
appBase := &apisv1.ApplicationBase{
|
||||
Name: app.Name,
|
||||
Alias: app.Alias,
|
||||
Namespace: app.Namespace,
|
||||
CreateTime: app.CreateTime,
|
||||
UpdateTime: app.UpdateTime,
|
||||
Description: app.Description,
|
||||
Icon: app.Icon,
|
||||
Labels: app.Labels,
|
||||
}
|
||||
project, err := c.projectUsecase.GetProject(ctx, app.Project)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("query project info failure %s", err.Error())
|
||||
}
|
||||
if project != nil {
|
||||
appBase.Project = convertProjectModel2Base(project)
|
||||
}
|
||||
return appBase
|
||||
}
|
||||
|
||||
|
||||
@@ -50,12 +50,16 @@ var _ = Describe("Test application usecase function", func() {
|
||||
envBindingUsecase *envBindingUsecaseImpl
|
||||
deliveryTargetUsecase *deliveryTargetUsecaseImpl
|
||||
definitionUsecase *definitionUsecaseImpl
|
||||
projectUsecase *projectUsecaseImpl
|
||||
testProject = "app-project"
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
workflowUsecase = &workflowUsecaseImpl{ds: ds}
|
||||
definitionUsecase = &definitionUsecaseImpl{kubeClient: k8sClient}
|
||||
envBindingUsecase = &envBindingUsecaseImpl{ds: ds, workflowUsecase: workflowUsecase, kubeClient: k8sClient, definitionUsecase: definitionUsecase}
|
||||
deliveryTargetUsecase = &deliveryTargetUsecaseImpl{ds: ds}
|
||||
projectUsecase = &projectUsecaseImpl{ds: ds, kubeClient: k8sClient}
|
||||
appUsecase = &applicationUsecaseImpl{
|
||||
ds: ds,
|
||||
workflowUsecase: workflowUsecase,
|
||||
@@ -64,13 +68,17 @@ var _ = Describe("Test application usecase function", func() {
|
||||
envBindingUsecase: envBindingUsecase,
|
||||
definitionUsecase: definitionUsecase,
|
||||
deliveryTargetUsecase: deliveryTargetUsecase,
|
||||
projectUsecase: projectUsecase,
|
||||
}
|
||||
})
|
||||
|
||||
It("Test CreateApplication function", func() {
|
||||
By("test sample create")
|
||||
_, err := projectUsecase.CreateProject(context.TODO(), v1.CreateProjectRequest{Name: testProject})
|
||||
Expect(err).Should(BeNil())
|
||||
req := v1.CreateApplicationRequest{
|
||||
Name: "test-app",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
EnvBinding: []*v1.EnvBinding{{
|
||||
Name: "dev",
|
||||
@@ -95,7 +103,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
Expect(err).Should(Succeed())
|
||||
req = v1.CreateApplicationRequest{
|
||||
Name: "test-app-sadasd",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -107,7 +115,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
|
||||
req = v1.CreateApplicationRequest{
|
||||
Name: "test-app-sadasd2",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -122,7 +130,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
Expect(err).Should(Succeed())
|
||||
req = v1.CreateApplicationRequest{
|
||||
Name: "test-app-sadasd3",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -135,7 +143,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
By("Test create app with env binding")
|
||||
req = v1.CreateApplicationRequest{
|
||||
Name: "test-app-sadasd4",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -159,7 +167,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd4")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
|
||||
})
|
||||
|
||||
@@ -170,7 +178,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
|
||||
It("Test ListApplications and filter by targetName function", func() {
|
||||
list, err := appUsecase.ListApplications(context.TODO(), v1.ListApplicatioOptions{
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
TargetName: "dev-target"})
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(len(list), 2)).Should(BeEmpty())
|
||||
@@ -179,7 +187,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DetailApplication function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
|
||||
detail, err := appUsecase.DetailApplication(context.TODO(), appModel)
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -190,7 +198,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test ListComponents function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
|
||||
components, err := appUsecase.ListComponents(context.TODO(), appModel, v1.ListApplicationComponentOptions{})
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -216,7 +224,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DetailComponent function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
|
||||
detail, err := appUsecase.DetailComponent(context.TODO(), appModel, "hello-world-server")
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -228,7 +236,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test AddComponent function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
base, err := appUsecase.AddComponent(context.TODO(), appModel, v1.CreateComponentRequest{
|
||||
Name: "test2",
|
||||
Description: "this is a test2 component",
|
||||
@@ -244,7 +252,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DetailComponent function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
detailResponse, err := appUsecase.DetailComponent(context.TODO(), appModel, "test2")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(detailResponse.DependsOn[0], "data-worker")).Should(BeEmpty())
|
||||
@@ -255,7 +263,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test AddPolicy function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
_, err = appUsecase.AddPolicy(context.TODO(), appModel, v1.CreatePolicyRequest{
|
||||
Name: EnvBindingPolicyDefaultName,
|
||||
Description: "this is a test2 policy",
|
||||
@@ -276,7 +284,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test ListPolicies function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
|
||||
policies, err := appUsecase.ListPolicies(context.TODO(), appModel)
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -286,7 +294,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DetailPolicy function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
detail, err := appUsecase.DetailPolicy(context.TODO(), appModel, EnvBindingPolicyDefaultName)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(detail.Properties).ShouldNot(BeNil())
|
||||
@@ -296,7 +304,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test UpdatePolicy function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
base, err := appUsecase.UpdatePolicy(context.TODO(), appModel, EnvBindingPolicyDefaultName, v1.UpdatePolicyRequest{
|
||||
Type: "env-binding",
|
||||
Properties: `{"envs":{}}`,
|
||||
@@ -308,7 +316,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DeletePolicy function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
err = appUsecase.DeletePolicy(context.TODO(), appModel, EnvBindingPolicyDefaultName)
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
@@ -389,7 +397,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test DeleteComponent function", func() {
|
||||
appModel, err := appUsecase.GetApplication(context.TODO(), "test-app-sadasd")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(appModel.Namespace, "test-app-namespace")).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appModel.Project, testProject)).Should(BeEmpty())
|
||||
err = appUsecase.DeleteComponent(context.TODO(), appModel, "test2")
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
@@ -454,7 +462,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
It("Test ApplicationEnvRecycle function", func() {
|
||||
req := v1.CreateApplicationRequest{
|
||||
Name: "app-env-recycle" + "-dev",
|
||||
Namespace: "test-app-namespace",
|
||||
Project: testProject,
|
||||
Description: "this is a test app with env",
|
||||
}
|
||||
base, err := appUsecase.CreateApplication(context.TODO(), req)
|
||||
@@ -463,7 +471,7 @@ var _ = Describe("Test application usecase function", func() {
|
||||
|
||||
err = envBindingUsecase.ApplicationEnvRecycle(context.TODO(), &model.Application{
|
||||
Name: "app-env-recycle",
|
||||
Namespace: "test-app-namespace",
|
||||
Namespace: "project-" + testProject,
|
||||
}, &model.EnvBinding{Name: "dev"})
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
|
||||
@@ -184,7 +184,7 @@ func (c *clusterUsecaseImpl) ListKubeClusters(ctx context.Context, query string,
|
||||
}
|
||||
|
||||
func joinClusterByKubeConfigString(ctx context.Context, k8sClient client.Client, clusterName string, kubeConfig string) (string, error) {
|
||||
tmpFileName := fmt.Sprintf("/tmp/cluster-secret-%s-%s-%d.kubeconfig", clusterName, utils.RandomString(8), time.Now().UnixNano())
|
||||
tmpFileName := fmt.Sprintf("/tmp/cluster-secret-%s-%d.kubeconfig", utils.RandomString(8), time.Now().UnixNano())
|
||||
if err := ioutil.WriteFile(tmpFileName, []byte(kubeConfig), 0600); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to write kubeconfig to temp file %s", tmpFileName)
|
||||
}
|
||||
|
||||
@@ -301,6 +301,9 @@ func patchSchema(defaultSchema, customSchema []*utils.UIParameter) []*utils.UIPa
|
||||
if cusSchema.Sort != 0 {
|
||||
dSchema.Sort = cusSchema.Sort
|
||||
}
|
||||
if cusSchema.Additional != nil {
|
||||
dSchema.Additional = cusSchema.Additional
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(defaultSchema, func(i, j int) bool {
|
||||
@@ -335,6 +338,13 @@ func renderUIParameter(key, label string, property *openapi3.SchemaRef, required
|
||||
if property.Value.Properties != nil {
|
||||
parameter.SubParameters = renderDefaultUISchema(property.Value)
|
||||
}
|
||||
if property.Value.AdditionalProperties != nil {
|
||||
parameter.SubParameters = renderDefaultUISchema(property.Value.AdditionalProperties.Value)
|
||||
var enable = true
|
||||
value := property.Value.AdditionalProperties.Value
|
||||
parameter.AdditionalParameter = renderUIParameter(value.Title, utils.FirstUpper(value.Title), property.Value.AdditionalProperties, value.Required)
|
||||
parameter.Additional = &enable
|
||||
}
|
||||
parameter.Validate = &utils.Validate{}
|
||||
parameter.Validate.DefaultValue = property.Value.Default
|
||||
for _, enum := range property.Value.Enum {
|
||||
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
@@ -163,12 +165,23 @@ var _ = Describe("Test namespace usecase functions", func() {
|
||||
|
||||
func TestAddDefinitionUISchema(t *testing.T) {
|
||||
du := NewDefinitionUsecase()
|
||||
cdata, err := ioutil.ReadFile("./testdata/ui-custom-schema.yaml")
|
||||
schemaFiles, err := ioutil.ReadDir("../../../../vela-templates/definitions/uischema")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = du.AddDefinitionUISchema(context.TODO(), "webservice", "component", string(cdata))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
for _, sf := range schemaFiles {
|
||||
if !sf.IsDir() {
|
||||
typeNames := strings.SplitN(sf.Name(), "-", 2)
|
||||
cdata, err := ioutil.ReadFile(path.Join("../../../../vela-templates/definitions/uischema", sf.Name()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
definitionName := strings.Replace(typeNames[1], path.Ext(sf.Name()), "", -1)
|
||||
_, err = du.AddDefinitionUISchema(context.TODO(), definitionName, typeNames[0], string(cdata))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("create ui schema %s for %s definition", definitionName, typeNames[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,37 +34,39 @@ type DeliveryTargetUsecase interface {
|
||||
DeleteDeliveryTarget(ctx context.Context, deliveryTargetName string) error
|
||||
CreateDeliveryTarget(ctx context.Context, req apisv1.CreateDeliveryTargetRequest) (*apisv1.DetailDeliveryTargetResponse, error)
|
||||
UpdateDeliveryTarget(ctx context.Context, deliveryTarget *model.DeliveryTarget, req apisv1.UpdateDeliveryTargetRequest) (*apisv1.DetailDeliveryTargetResponse, error)
|
||||
ListDeliveryTargets(ctx context.Context, page, pageSize int, namespace string) (*apisv1.ListDeliveryTargetResponse, error)
|
||||
ListDeliveryTargets(ctx context.Context, page, pageSize int, project string) (*apisv1.ListTargetResponse, error)
|
||||
}
|
||||
|
||||
type deliveryTargetUsecaseImpl struct {
|
||||
ds datastore.DataStore
|
||||
ds datastore.DataStore
|
||||
projectUsecase ProjectUsecase
|
||||
}
|
||||
|
||||
// NewDeliveryTargetUsecase new DeliveryTarget usecase
|
||||
func NewDeliveryTargetUsecase(ds datastore.DataStore) DeliveryTargetUsecase {
|
||||
func NewDeliveryTargetUsecase(ds datastore.DataStore, projectUsecase ProjectUsecase) DeliveryTargetUsecase {
|
||||
return &deliveryTargetUsecaseImpl{
|
||||
ds: ds,
|
||||
ds: ds,
|
||||
projectUsecase: projectUsecase,
|
||||
}
|
||||
}
|
||||
|
||||
func (dt *deliveryTargetUsecaseImpl) ListDeliveryTargets(ctx context.Context, page, pageSize int, namespace string) (*apisv1.ListDeliveryTargetResponse, error) {
|
||||
func (dt *deliveryTargetUsecaseImpl) ListDeliveryTargets(ctx context.Context, page, pageSize int, project string) (*apisv1.ListTargetResponse, error) {
|
||||
deliveryTarget := model.DeliveryTarget{}
|
||||
if namespace != "" {
|
||||
deliveryTarget.Namespace = namespace
|
||||
if project != "" {
|
||||
deliveryTarget.Project = project
|
||||
}
|
||||
deliveryTargets, err := dt.ds.List(ctx, &deliveryTarget, &datastore.ListOptions{Page: page, PageSize: pageSize})
|
||||
deliveryTargets, err := dt.ds.List(ctx, &deliveryTarget, &datastore.ListOptions{Page: page, PageSize: pageSize, SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := &apisv1.ListDeliveryTargetResponse{
|
||||
DeliveryTargets: []apisv1.DeliveryTargetBase{},
|
||||
resp := &apisv1.ListTargetResponse{
|
||||
Targets: []apisv1.DeliveryTargetBase{},
|
||||
}
|
||||
for _, raw := range deliveryTargets {
|
||||
dt, ok := raw.(*model.DeliveryTarget)
|
||||
target, ok := raw.(*model.DeliveryTarget)
|
||||
if ok {
|
||||
resp.DeliveryTargets = append(resp.DeliveryTargets, *convertFromDeliveryTargetModel(dt))
|
||||
resp.Targets = append(resp.Targets, *(dt.convertFromDeliveryTargetModel(ctx, target)))
|
||||
}
|
||||
}
|
||||
count, err := dt.ds.Count(ctx, &deliveryTarget, nil)
|
||||
@@ -92,6 +94,7 @@ func (dt *deliveryTargetUsecaseImpl) DeleteDeliveryTarget(ctx context.Context, d
|
||||
|
||||
func (dt *deliveryTargetUsecaseImpl) CreateDeliveryTarget(ctx context.Context, req apisv1.CreateDeliveryTargetRequest) (*apisv1.DetailDeliveryTargetResponse, error) {
|
||||
deliveryTarget := convertCreateReqToDeliveryTargetModel(req)
|
||||
|
||||
// check deliveryTarget name.
|
||||
exit, err := dt.ds.IsExist(ctx, &deliveryTarget)
|
||||
if err != nil {
|
||||
@@ -101,6 +104,14 @@ func (dt *deliveryTargetUsecaseImpl) CreateDeliveryTarget(ctx context.Context, r
|
||||
if exit {
|
||||
return nil, bcode.ErrDeliveryTargetExist
|
||||
}
|
||||
// check project
|
||||
project, err := dt.projectUsecase.GetProject(ctx, req.Project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deliveryTarget.Namespace = project.Namespace
|
||||
deliveryTarget.Project = project.Name
|
||||
|
||||
if err := dt.ds.Add(ctx, &deliveryTarget); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -118,7 +129,7 @@ func (dt *deliveryTargetUsecaseImpl) UpdateDeliveryTarget(ctx context.Context, d
|
||||
// DetailDeliveryTarget detail DeliveryTarget
|
||||
func (dt *deliveryTargetUsecaseImpl) DetailDeliveryTarget(ctx context.Context, deliveryTarget *model.DeliveryTarget) (*apisv1.DetailDeliveryTargetResponse, error) {
|
||||
return &apisv1.DetailDeliveryTargetResponse{
|
||||
DeliveryTargetBase: *convertFromDeliveryTargetModel(deliveryTarget),
|
||||
DeliveryTargetBase: *dt.convertFromDeliveryTargetModel(ctx, deliveryTarget),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -144,7 +155,6 @@ func convertUpdateReqToDeliveryTargetModel(deliveryTarget *model.DeliveryTarget,
|
||||
func convertCreateReqToDeliveryTargetModel(req apisv1.CreateDeliveryTargetRequest) model.DeliveryTarget {
|
||||
deliveryTarget := model.DeliveryTarget{
|
||||
Name: req.Name,
|
||||
Namespace: req.Namespace,
|
||||
Alias: req.Alias,
|
||||
Description: req.Description,
|
||||
Cluster: (*model.ClusterTarget)(req.Cluster),
|
||||
@@ -153,12 +163,11 @@ func convertCreateReqToDeliveryTargetModel(req apisv1.CreateDeliveryTargetReques
|
||||
return deliveryTarget
|
||||
}
|
||||
|
||||
func convertFromDeliveryTargetModel(deliveryTarget *model.DeliveryTarget) *apisv1.DeliveryTargetBase {
|
||||
func (dt *deliveryTargetUsecaseImpl) convertFromDeliveryTargetModel(ctx context.Context, deliveryTarget *model.DeliveryTarget) *apisv1.DeliveryTargetBase {
|
||||
var appNum int64 = 0
|
||||
// TODO: query app num in target
|
||||
return &apisv1.DeliveryTargetBase{
|
||||
targetBase := &apisv1.DeliveryTargetBase{
|
||||
Name: deliveryTarget.Name,
|
||||
Namespace: deliveryTarget.Namespace,
|
||||
Alias: deliveryTarget.Alias,
|
||||
Description: deliveryTarget.Description,
|
||||
Cluster: (*apisv1.ClusterTarget)(deliveryTarget.Cluster),
|
||||
@@ -167,4 +176,13 @@ func convertFromDeliveryTargetModel(deliveryTarget *model.DeliveryTarget) *apisv
|
||||
UpdateTime: deliveryTarget.UpdateTime,
|
||||
AppNum: appNum,
|
||||
}
|
||||
|
||||
project, err := dt.projectUsecase.GetProject(ctx, deliveryTarget.Project)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("query project info failure %s", err.Error())
|
||||
}
|
||||
if project != nil {
|
||||
targetBase.Project = convertProjectModel2Base(project)
|
||||
}
|
||||
return targetBase
|
||||
}
|
||||
|
||||
@@ -30,14 +30,20 @@ import (
|
||||
var _ = Describe("Test delivery target usecase functions", func() {
|
||||
var (
|
||||
deliveryTargetUsecase *deliveryTargetUsecaseImpl
|
||||
projectUsecase *projectUsecaseImpl
|
||||
testProject = "target-project"
|
||||
)
|
||||
BeforeEach(func() {
|
||||
deliveryTargetUsecase = &deliveryTargetUsecaseImpl{ds: ds}
|
||||
projectUsecase = &projectUsecaseImpl{ds: ds, kubeClient: k8sClient}
|
||||
deliveryTargetUsecase = &deliveryTargetUsecaseImpl{ds: ds, projectUsecase: projectUsecase}
|
||||
})
|
||||
It("Test CreateDeliveryTarget function", func() {
|
||||
_, err := projectUsecase.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
req := apisv1.CreateDeliveryTargetRequest{
|
||||
Name: "test-delivery-target",
|
||||
Namespace: "test-namespace",
|
||||
Project: testProject,
|
||||
Alias: "test-alias",
|
||||
Description: "this is a deliveryTarget",
|
||||
Cluster: &apisv1.ClusterTarget{ClusterName: "cluster-dev", Namespace: "dev"},
|
||||
|
||||
@@ -356,11 +356,11 @@ func convertEnvbindingModelToBase(app *model.Application, envBinding *model.EnvB
|
||||
dt := dte.(*model.DeliveryTarget)
|
||||
dtMap[dt.Name] = dt
|
||||
}
|
||||
var targets []apisv1.DeliveryTargetBase
|
||||
var targets []apisv1.NameAlias
|
||||
for _, targetName := range envBinding.TargetNames {
|
||||
dt := dtMap[targetName]
|
||||
if dt != nil {
|
||||
targets = append(targets, *convertFromDeliveryTargetModel(dt))
|
||||
targets = append(targets, apisv1.NameAlias{Name: dt.Name, Alias: dt.Alias})
|
||||
}
|
||||
}
|
||||
ebb := &apisv1.EnvBindingBase{
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/clients"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
|
||||
)
|
||||
|
||||
// NamespaceUsecase namespace manage usecase.
|
||||
// Namespace acts as the tenant isolation model on the control side.
|
||||
type NamespaceUsecase interface {
|
||||
ListNamespaces(ctx context.Context) ([]apisv1.NamespaceBase, error)
|
||||
CreateNamespace(ctx context.Context, req apisv1.CreateNamespaceRequest) (*apisv1.NamespaceBase, error)
|
||||
}
|
||||
|
||||
// AnnotationDescription set namespace description in annotation
|
||||
const AnnotationDescription string = "description"
|
||||
|
||||
// LabelCreator set namesapce creator in labels
|
||||
const LabelCreator string = "creator"
|
||||
|
||||
type namespaceUsecaseImpl struct {
|
||||
kubeClient client.Client
|
||||
}
|
||||
|
||||
// NewNamespaceUsecase new namespace usecase
|
||||
func NewNamespaceUsecase() NamespaceUsecase {
|
||||
kubecli, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
log.Logger.Fatalf("get kubeclient failure %s", err.Error())
|
||||
}
|
||||
return &namespaceUsecaseImpl{kubeClient: kubecli}
|
||||
}
|
||||
|
||||
// ListNamespaces list controller cluster namespaces
|
||||
func (n *namespaceUsecaseImpl) ListNamespaces(ctx context.Context) ([]apisv1.NamespaceBase, error) {
|
||||
|
||||
// TODO: Consider whether to query only namespaces created by Vela
|
||||
var kubeNamespaces corev1.NamespaceList
|
||||
if err := n.kubeClient.List(ctx, &kubeNamespaces, &client.ListOptions{}); err != nil {
|
||||
log.Logger.Errorf("query namespace list from cluster failure %s", err.Error())
|
||||
return nil, bcode.ErrNamespaceQuery
|
||||
}
|
||||
var namespaces []apisv1.NamespaceBase
|
||||
for _, namesapce := range kubeNamespaces.Items {
|
||||
namespaces = append(namespaces, apisv1.NamespaceBase{
|
||||
Name: namesapce.Name,
|
||||
Description: namesapce.Annotations[AnnotationDescription],
|
||||
CreateTime: namesapce.CreationTimestamp.Time,
|
||||
UpdateTime: namesapce.CreationTimestamp.Time,
|
||||
})
|
||||
}
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
// CreateNamespace create namespace to controller cluster
|
||||
func (n *namespaceUsecaseImpl) CreateNamespace(ctx context.Context, req apisv1.CreateNamespaceRequest) (*apisv1.NamespaceBase, error) {
|
||||
if err := n.kubeClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: req.Name,
|
||||
Labels: map[string]string{
|
||||
LabelCreator: "kubevela",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
AnnotationDescription: req.Description,
|
||||
},
|
||||
},
|
||||
Spec: corev1.NamespaceSpec{},
|
||||
}); err != nil {
|
||||
if apierrors.IsAlreadyExists(err) {
|
||||
return nil, bcode.ErrNamespaceIsExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &apisv1.NamespaceBase{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
143
pkg/apiserver/rest/usecase/project.go
Normal file
143
pkg/apiserver/rest/usecase/project.go
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/clients"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/model"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
)
|
||||
|
||||
// ProjectUsecase project manage usecase.
|
||||
type ProjectUsecase interface {
|
||||
GetProject(ctx context.Context, projectName string) (*model.Project, error)
|
||||
ListProjects(ctx context.Context) ([]*apisv1.ProjectBase, error)
|
||||
CreateProject(ctx context.Context, req apisv1.CreateProjectRequest) (*apisv1.ProjectBase, error)
|
||||
}
|
||||
|
||||
type projectUsecaseImpl struct {
|
||||
ds datastore.DataStore
|
||||
kubeClient client.Client
|
||||
}
|
||||
|
||||
// NewProjectUsecase new project usecase
|
||||
func NewProjectUsecase(ds datastore.DataStore) ProjectUsecase {
|
||||
kubecli, err := clients.GetKubeClient()
|
||||
if err != nil {
|
||||
log.Logger.Fatalf("get kubeclient failure %s", err.Error())
|
||||
}
|
||||
return &projectUsecaseImpl{kubeClient: kubecli, ds: ds}
|
||||
}
|
||||
|
||||
// GetProject get project
|
||||
func (p *projectUsecaseImpl) GetProject(ctx context.Context, projectName string) (*model.Project, error) {
|
||||
project := &model.Project{Name: projectName}
|
||||
if err := p.ds.Get(ctx, project); err != nil {
|
||||
if errors.Is(err, datastore.ErrRecordNotExist) {
|
||||
return nil, bcode.ErrProjectIsNotExist
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return project, nil
|
||||
}
|
||||
|
||||
// ListProjects list projects
|
||||
func (p *projectUsecaseImpl) ListProjects(ctx context.Context) ([]*apisv1.ProjectBase, error) {
|
||||
var project = model.Project{}
|
||||
entitys, err := p.ds.List(ctx, &project, &datastore.ListOptions{SortBy: []datastore.SortOption{{Key: "createTime", Order: datastore.SortOrderDescending}}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var projects []*apisv1.ProjectBase
|
||||
for _, entity := range entitys {
|
||||
project := entity.(*model.Project)
|
||||
projects = append(projects, convertProjectModel2Base(project))
|
||||
}
|
||||
return projects, nil
|
||||
}
|
||||
|
||||
// CreateProject create project
|
||||
func (p *projectUsecaseImpl) CreateProject(ctx context.Context, req apisv1.CreateProjectRequest) (*apisv1.ProjectBase, error) {
|
||||
|
||||
exist, err := p.ds.IsExist(ctx, &model.Project{Name: req.Name})
|
||||
if err != nil {
|
||||
log.Logger.Errorf("check project name is exist failure %s", err.Error())
|
||||
return nil, bcode.ErrProjectIsExist
|
||||
}
|
||||
if exist {
|
||||
return nil, bcode.ErrProjectIsExist
|
||||
}
|
||||
|
||||
new := &model.Project{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Alias: req.Alias,
|
||||
Namespace: fmt.Sprintf("project-%s", req.Name),
|
||||
}
|
||||
|
||||
// create namespace at first
|
||||
if err := p.kubeClient.Create(ctx, &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: new.Namespace,
|
||||
Labels: map[string]string{
|
||||
oam.LabelProjectNamesapce: new.Name,
|
||||
},
|
||||
},
|
||||
Spec: corev1.NamespaceSpec{},
|
||||
}); err != nil {
|
||||
if !apierrors.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := p.ds.Add(ctx, new); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &apisv1.ProjectBase{
|
||||
Name: new.Name,
|
||||
Alias: new.Alias,
|
||||
Namespace: new.Namespace,
|
||||
Description: new.Description,
|
||||
CreateTime: new.CreateTime,
|
||||
UpdateTime: new.UpdateTime,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertProjectModel2Base(project *model.Project) *apisv1.ProjectBase {
|
||||
return &apisv1.ProjectBase{
|
||||
Name: project.Name,
|
||||
Namespace: project.Namespace,
|
||||
Description: project.Description,
|
||||
Alias: project.Alias,
|
||||
CreateTime: project.CreateTime,
|
||||
UpdateTime: project.UpdateTime,
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
. "github.com/onsi/ginkgo"
|
||||
@@ -26,25 +27,26 @@ import (
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
var _ = Describe("Test namespace usecase functions", func() {
|
||||
var _ = Describe("Test project usecase functions", func() {
|
||||
var (
|
||||
namespaceUsecase *namespaceUsecaseImpl
|
||||
projectUsecase *projectUsecaseImpl
|
||||
)
|
||||
BeforeEach(func() {
|
||||
namespaceUsecase = &namespaceUsecaseImpl{kubeClient: k8sClient}
|
||||
projectUsecase = &projectUsecaseImpl{kubeClient: k8sClient, ds: ds}
|
||||
})
|
||||
It("Test CreateNamespace function", func() {
|
||||
req := apisv1.CreateNamespaceRequest{
|
||||
Name: "test-namespace",
|
||||
Description: "this is a namespace description 王二",
|
||||
It("Test Createproject function", func() {
|
||||
req := apisv1.CreateProjectRequest{
|
||||
Name: "test-project",
|
||||
Description: "this is a project description 王二",
|
||||
}
|
||||
base, err := namespaceUsecase.CreateNamespace(context.TODO(), req)
|
||||
base, err := projectUsecase.CreateProject(context.TODO(), req)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(base.Description, req.Description)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(base.Namespace, fmt.Sprintf("project-%s", req.Name))).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("Test ListNamespace function", func() {
|
||||
_, err := namespaceUsecase.ListNamespaces(context.TODO())
|
||||
It("Test ListProject function", func() {
|
||||
_, err := projectUsecase.ListProjects(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
})
|
||||
112
pkg/apiserver/rest/usecase/testdata/ui-schema.yaml
vendored
112
pkg/apiserver/rest/usecase/testdata/ui-schema.yaml
vendored
@@ -102,14 +102,6 @@
|
||||
label: ReadinessProbe
|
||||
sort: 13
|
||||
subParameters:
|
||||
- description: How often, in seconds, to execute the probe.
|
||||
jsonKey: periodSeconds
|
||||
label: PeriodSeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 10
|
||||
required: true
|
||||
- description: Minimum consecutive successes for the probe to be considered successful
|
||||
after having failed.
|
||||
jsonKey: successThreshold
|
||||
@@ -182,22 +174,6 @@
|
||||
label: HttpGet
|
||||
sort: 100
|
||||
subParameters:
|
||||
- description: The endpoint, relative to the port, to which the HTTP GET request
|
||||
should be directed.
|
||||
jsonKey: path
|
||||
label: Path
|
||||
sort: 100
|
||||
uiType: Input
|
||||
validate:
|
||||
required: true
|
||||
- description: The TCP socket within the container to which the HTTP GET request
|
||||
should be directed.
|
||||
jsonKey: port
|
||||
label: Port
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
required: true
|
||||
- description: ""
|
||||
jsonKey: httpHeaders
|
||||
label: HttpHeaders
|
||||
@@ -219,6 +195,22 @@
|
||||
required: true
|
||||
uiType: Structs
|
||||
validate: {}
|
||||
- description: The endpoint, relative to the port, to which the HTTP GET request
|
||||
should be directed.
|
||||
jsonKey: path
|
||||
label: Path
|
||||
sort: 100
|
||||
uiType: Input
|
||||
validate:
|
||||
required: true
|
||||
- description: The TCP socket within the container to which the HTTP GET request
|
||||
should be directed.
|
||||
jsonKey: port
|
||||
label: Port
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
required: true
|
||||
uiType: Group
|
||||
validate: {}
|
||||
- description: Number of seconds after the container is started before the first
|
||||
@@ -230,6 +222,14 @@
|
||||
validate:
|
||||
defaultValue: 0
|
||||
required: true
|
||||
- description: How often, in seconds, to execute the probe.
|
||||
jsonKey: periodSeconds
|
||||
label: PeriodSeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 10
|
||||
required: true
|
||||
uiType: Group
|
||||
validate: {}
|
||||
- description: Instructions for assessing whether the container is alive.
|
||||
@@ -237,32 +237,6 @@
|
||||
label: LivenessProbe
|
||||
sort: 15
|
||||
subParameters:
|
||||
- description: Number of seconds after the container is started before the first
|
||||
probe is initiated.
|
||||
jsonKey: initialDelaySeconds
|
||||
label: InitialDelaySeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 0
|
||||
required: true
|
||||
- description: How often, in seconds, to execute the probe.
|
||||
jsonKey: periodSeconds
|
||||
label: PeriodSeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 10
|
||||
required: true
|
||||
- description: Minimum consecutive successes for the probe to be considered successful
|
||||
after having failed.
|
||||
jsonKey: successThreshold
|
||||
label: SuccessThreshold
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 1
|
||||
required: true
|
||||
- description: Instructions for assessing container health by probing a TCP socket.
|
||||
Either this attribute or the exec attribute or the httpGet attribute MUST be
|
||||
specified. This attribute is mutually exclusive with both the exec attribute
|
||||
@@ -365,14 +339,34 @@
|
||||
required: true
|
||||
uiType: Group
|
||||
validate: {}
|
||||
- description: Number of seconds after the container is started before the first
|
||||
probe is initiated.
|
||||
jsonKey: initialDelaySeconds
|
||||
label: InitialDelaySeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 0
|
||||
required: true
|
||||
- description: How often, in seconds, to execute the probe.
|
||||
jsonKey: periodSeconds
|
||||
label: PeriodSeconds
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 10
|
||||
required: true
|
||||
- description: Minimum consecutive successes for the probe to be considered successful
|
||||
after having failed.
|
||||
jsonKey: successThreshold
|
||||
label: SuccessThreshold
|
||||
sort: 100
|
||||
uiType: Number
|
||||
validate:
|
||||
defaultValue: 1
|
||||
required: true
|
||||
uiType: Group
|
||||
validate: {}
|
||||
- description: Specify image pull secrets for your service
|
||||
jsonKey: imagePullSecrets
|
||||
label: ImagePullSecrets
|
||||
sort: 100
|
||||
uiType: Strings
|
||||
validate: {}
|
||||
- description: Which port do you want customer traffic sent to
|
||||
disable: true
|
||||
jsonKey: port
|
||||
@@ -382,6 +376,12 @@
|
||||
validate:
|
||||
defaultValue: 80
|
||||
required: true
|
||||
- description: Specify image pull secrets for your service
|
||||
jsonKey: imagePullSecrets
|
||||
label: ImagePullSecrets
|
||||
sort: 100
|
||||
uiType: Strings
|
||||
validate: {}
|
||||
- description: Declare volumes and volumeMounts
|
||||
disable: true
|
||||
jsonKey: volumes
|
||||
|
||||
@@ -43,18 +43,27 @@ var _ = Describe("Test workflow usecase functions", func() {
|
||||
var (
|
||||
workflowUsecase *workflowUsecaseImpl
|
||||
appUsecase *applicationUsecaseImpl
|
||||
projectUsecase *projectUsecaseImpl
|
||||
testProject = "workflow-project"
|
||||
)
|
||||
BeforeEach(func() {
|
||||
workflowUsecase = &workflowUsecaseImpl{ds: ds, kubeClient: k8sClient, apply: apply.NewAPIApplicator(k8sClient)}
|
||||
appUsecase = &applicationUsecaseImpl{ds: ds, kubeClient: k8sClient, apply: apply.NewAPIApplicator(k8sClient), envBindingUsecase: &envBindingUsecaseImpl{
|
||||
ds: ds,
|
||||
workflowUsecase: workflowUsecase,
|
||||
}}
|
||||
projectUsecase = &projectUsecaseImpl{ds: ds, kubeClient: k8sClient}
|
||||
appUsecase = &applicationUsecaseImpl{ds: ds, kubeClient: k8sClient,
|
||||
apply: apply.NewAPIApplicator(k8sClient),
|
||||
projectUsecase: projectUsecase,
|
||||
envBindingUsecase: &envBindingUsecaseImpl{
|
||||
ds: ds,
|
||||
workflowUsecase: workflowUsecase,
|
||||
}}
|
||||
|
||||
})
|
||||
It("Test CreateWorkflow function", func() {
|
||||
_, err := projectUsecase.CreateProject(context.TODO(), apisv1.CreateProjectRequest{Name: testProject})
|
||||
Expect(err).Should(BeNil())
|
||||
reqApp := apisv1.CreateApplicationRequest{
|
||||
Name: appName,
|
||||
Namespace: "default",
|
||||
Project: testProject,
|
||||
Description: "this is a test app",
|
||||
EnvBinding: []*apisv1.EnvBinding{{
|
||||
Name: "dev",
|
||||
@@ -62,9 +71,8 @@ var _ = Describe("Test workflow usecase functions", func() {
|
||||
TargetNames: []string{"dev-target"},
|
||||
}},
|
||||
}
|
||||
_, err := appUsecase.CreateApplication(context.TODO(), reqApp)
|
||||
_, err = appUsecase.CreateApplication(context.TODO(), reqApp)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
req := apisv1.CreateWorkflowRequest{
|
||||
Name: "test-workflow-1",
|
||||
Description: "this is a workflow",
|
||||
|
||||
@@ -16,8 +16,8 @@ limitations under the License.
|
||||
|
||||
package bcode
|
||||
|
||||
// ErrNamespaceQuery query namespace failure from k8s api
|
||||
var ErrNamespaceQuery = NewBcode(500, 30001, "query namespace list from cluster failure")
|
||||
// ErrProjectIsExist project name is exist
|
||||
var ErrProjectIsExist = NewBcode(400, 30001, "project name is exist")
|
||||
|
||||
// ErrNamespaceIsExist namespace name is exist
|
||||
var ErrNamespaceIsExist = NewBcode(400, 30002, "namespace name is exist")
|
||||
// ErrProjectIsNotExist project is not exist
|
||||
var ErrProjectIsNotExist = NewBcode(404, 30002, "project is not exist")
|
||||
|
||||
17
pkg/apiserver/rest/utils/bcode/project.go
Normal file
17
pkg/apiserver/rest/utils/bcode/project.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package bcode
|
||||
@@ -29,10 +29,12 @@ type UIParameter struct {
|
||||
Validate *Validate `json:"validate,omitempty"`
|
||||
JSONKey string `json:"jsonKey"`
|
||||
UIType string `json:"uiType"`
|
||||
// means only can be read.
|
||||
// means disable parameter in ui
|
||||
Disable *bool `json:"disable,omitempty"`
|
||||
SubParameterGroupOption []GroupOption `json:"subParameterGroupOption,omitempty"`
|
||||
SubParameters []*UIParameter `json:"subParameters,omitempty"`
|
||||
AdditionalParameter *UIParameter `json:"additionalParameter,omitempty"`
|
||||
Additional *bool `json:"additional,omitempty"`
|
||||
}
|
||||
|
||||
// GroupOption define multiple data structure composition options.
|
||||
|
||||
@@ -505,7 +505,7 @@ 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.ListApplicatioOptions{
|
||||
Namespace: req.QueryParameter("namespace"),
|
||||
Project: req.QueryParameter("project"),
|
||||
TargetName: req.QueryParameter("targetName"),
|
||||
Query: req.QueryParameter("query"),
|
||||
})
|
||||
|
||||
@@ -51,7 +51,7 @@ type DeliveryTargetWebService struct {
|
||||
// GetWebService get web service
|
||||
func (dt *DeliveryTargetWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/deliveryTargets").
|
||||
ws.Path(versionPrefix+"/targets").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for deliveryTarget manage")
|
||||
@@ -61,11 +61,11 @@ func (dt *DeliveryTargetWebService) GetWebService() *restful.WebService {
|
||||
ws.Route(ws.GET("/").To(dt.listDeliveryTargets).
|
||||
Doc("list deliveryTarget").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.QueryParameter("namesapce", "Query the delivery target belonging to a namespace").DataType("string")).
|
||||
Param(ws.QueryParameter("project", "Query the target belong to project").DataType("string")).
|
||||
Param(ws.QueryParameter("page", "Page for paging").DataType("integer")).
|
||||
Param(ws.QueryParameter("pageSize", "PageSize for paging").DataType("integer")).
|
||||
Returns(200, "", apis.ListDeliveryTargetResponse{}).
|
||||
Writes(apis.ListDeliveryTargetResponse{}).Do(returns200, returns500))
|
||||
Returns(200, "", apis.ListTargetResponse{}).
|
||||
Writes(apis.ListTargetResponse{}).Do(returns200, returns500))
|
||||
|
||||
ws.Route(ws.POST("/").To(dt.createDeliveryTarget).
|
||||
Doc("create deliveryTarget").
|
||||
@@ -204,7 +204,7 @@ func (dt *DeliveryTargetWebService) listDeliveryTargets(req *restful.Request, re
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
deliveryTargets, err := dt.deliveryTargetUsecase.ListDeliveryTargets(req.Request.Context(), page, pageSize, req.QueryParameter("namespace"))
|
||||
deliveryTargets, err := dt.deliveryTargetUsecase.ListDeliveryTargets(req.Request.Context(), page, pageSize, req.QueryParameter("project"))
|
||||
if err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
|
||||
@@ -26,54 +26,54 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
|
||||
)
|
||||
|
||||
type namespaceWebService struct {
|
||||
namespaceUsecase usecase.NamespaceUsecase
|
||||
type projectWebService struct {
|
||||
projectUsecase usecase.ProjectUsecase
|
||||
}
|
||||
|
||||
// NewNamespaceWebService new namespace webservice
|
||||
func NewNamespaceWebService(namespaceUsecase usecase.NamespaceUsecase) WebService {
|
||||
return &namespaceWebService{namespaceUsecase: namespaceUsecase}
|
||||
// NewProjectWebService new project webservice
|
||||
func NewProjectWebService(projectUsecase usecase.ProjectUsecase) WebService {
|
||||
return &projectWebService{projectUsecase: projectUsecase}
|
||||
}
|
||||
|
||||
func (n *namespaceWebService) GetWebService() *restful.WebService {
|
||||
func (n *projectWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/namespaces").
|
||||
ws.Path(versionPrefix+"/projects").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for namespace manage")
|
||||
Doc("api for project manage")
|
||||
|
||||
tags := []string{"namespace"}
|
||||
tags := []string{"project"}
|
||||
|
||||
ws.Route(ws.GET("/").To(n.listNamespaces).
|
||||
Doc("list all namespaces").
|
||||
ws.Route(ws.GET("/").To(n.listprojects).
|
||||
Doc("list all projects").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Returns(200, "", apis.ListNamespaceResponse{}).
|
||||
Writes(apis.ListNamespaceResponse{}))
|
||||
Returns(200, "", apis.ListProjectResponse{}).
|
||||
Writes(apis.ListProjectResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/").To(n.createNamespace).
|
||||
Doc("create namespace").
|
||||
ws.Route(ws.POST("/").To(n.createproject).
|
||||
Doc("create a project").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Reads(apis.CreateNamespaceRequest{}).
|
||||
Returns(200, "", apis.NamespaceDetailResponse{}).
|
||||
Writes(apis.NamespaceDetailResponse{}))
|
||||
Reads(apis.CreateProjectRequest{}).
|
||||
Returns(200, "", apis.ProjectBase{}).
|
||||
Writes(apis.ProjectBase{}))
|
||||
return ws
|
||||
}
|
||||
|
||||
func (n *namespaceWebService) listNamespaces(req *restful.Request, res *restful.Response) {
|
||||
namespaces, err := n.namespaceUsecase.ListNamespaces(req.Request.Context())
|
||||
func (n *projectWebService) listprojects(req *restful.Request, res *restful.Response) {
|
||||
projects, err := n.projectUsecase.ListProjects(req.Request.Context())
|
||||
if err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
if err := res.WriteEntity(apis.ListNamespaceResponse{Namespaces: namespaces}); err != nil {
|
||||
if err := res.WriteEntity(apis.ListProjectResponse{Projects: projects}); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (n *namespaceWebService) createNamespace(req *restful.Request, res *restful.Response) {
|
||||
func (n *projectWebService) createproject(req *restful.Request, res *restful.Response) {
|
||||
// Verify the validity of parameters
|
||||
var createReq apis.CreateNamespaceRequest
|
||||
var createReq apis.CreateProjectRequest
|
||||
if err := req.ReadEntity(&createReq); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
@@ -83,7 +83,7 @@ func (n *namespaceWebService) createNamespace(req *restful.Request, res *restful
|
||||
return
|
||||
}
|
||||
// Call the usecase layer code
|
||||
namespaceBase, err := n.namespaceUsecase.CreateNamespace(req.Request.Context(), createReq)
|
||||
projectBase, err := n.projectUsecase.CreateProject(req.Request.Context(), createReq)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("create application failure %s", err.Error())
|
||||
bcode.ReturnError(req, res, err)
|
||||
@@ -91,7 +91,7 @@ func (n *namespaceWebService) createNamespace(req *restful.Request, res *restful
|
||||
}
|
||||
|
||||
// Write back response data
|
||||
if err := res.WriteEntity(apis.NamespaceDetailResponse{NamespaceBase: *namespaceBase}); err != nil {
|
||||
if err := res.WriteEntity(projectBase); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
@@ -28,34 +28,34 @@ var _ = Describe("Test validate function", func() {
|
||||
It("Test check name validate ", func() {
|
||||
Expect(cmp.Diff(nameRegexp.MatchString("///Asd asda "), false)).Should(BeEmpty())
|
||||
var app0 = apisv1.CreateApplicationRequest{
|
||||
Name: "a",
|
||||
Namespace: "namespace",
|
||||
Name: "a",
|
||||
Project: "namespace",
|
||||
}
|
||||
err := validate.Struct(&app0)
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
var app1 = apisv1.CreateApplicationRequest{
|
||||
Name: "Asdasd",
|
||||
Namespace: "namespace",
|
||||
Name: "Asdasd",
|
||||
Project: "namespace",
|
||||
}
|
||||
err = validate.Struct(&app1)
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
var app2 = apisv1.CreateApplicationRequest{
|
||||
Name: "asdasd asdasd ++",
|
||||
Namespace: "namespace",
|
||||
Name: "asdasd asdasd ++",
|
||||
Project: "namespace",
|
||||
}
|
||||
err = validate.Struct(&app2)
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
|
||||
var app3 = apisv1.CreateApplicationRequest{
|
||||
Name: "asdasd",
|
||||
Namespace: "namespace",
|
||||
Name: "asdasd",
|
||||
Project: "namespace",
|
||||
}
|
||||
err = validate.Struct(&app3)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
var app4 = apisv1.CreateApplicationRequest{
|
||||
Name: "asdasd-asdasd",
|
||||
Namespace: "namespace",
|
||||
Name: "asdasd-asdasd",
|
||||
Project: "namespace",
|
||||
}
|
||||
err = validate.Struct(&app4)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
@@ -60,17 +60,17 @@ func returns500(b *restful.RouteBuilder) {
|
||||
func Init(ds datastore.DataStore) {
|
||||
clusterUsecase := usecase.NewClusterUsecase(ds)
|
||||
workflowUsecase := usecase.NewWorkflowUsecase(ds)
|
||||
deliveryTargetUsecase := usecase.NewDeliveryTargetUsecase(ds)
|
||||
namespaceUsecase := usecase.NewNamespaceUsecase()
|
||||
projectUsecase := usecase.NewProjectUsecase(ds)
|
||||
deliveryTargetUsecase := usecase.NewDeliveryTargetUsecase(ds, projectUsecase)
|
||||
oamApplicationUsecase := usecase.NewOAMApplicationUsecase()
|
||||
velaQLUsecase := usecase.NewVelaQLUsecase()
|
||||
definitionUsecase := usecase.NewDefinitionUsecase()
|
||||
addonUsecase := usecase.NewAddonUsecase()
|
||||
envBindingUsecase := usecase.NewEnvBindingUsecase(ds, workflowUsecase, definitionUsecase)
|
||||
applicationUsecase := usecase.NewApplicationUsecase(ds, workflowUsecase, envBindingUsecase, deliveryTargetUsecase, definitionUsecase)
|
||||
applicationUsecase := usecase.NewApplicationUsecase(ds, workflowUsecase, envBindingUsecase, deliveryTargetUsecase, definitionUsecase, projectUsecase)
|
||||
RegistWebService(NewClusterWebService(clusterUsecase))
|
||||
RegistWebService(NewApplicationWebService(applicationUsecase, envBindingUsecase, workflowUsecase))
|
||||
RegistWebService(NewNamespaceWebService(namespaceUsecase))
|
||||
RegistWebService(NewProjectWebService(projectUsecase))
|
||||
RegistWebService(NewDefinitionWebservice(definitionUsecase))
|
||||
RegistWebService(NewAddonWebService(addonUsecase))
|
||||
RegistWebService(NewEnabledAddonWebService(addonUsecase))
|
||||
|
||||
@@ -19,10 +19,13 @@ package http
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/registry"
|
||||
)
|
||||
@@ -54,7 +57,13 @@ func (c *HTTPCmd) Run(meta *registry.Meta) (res interface{}, err error) {
|
||||
method = meta.String("method")
|
||||
u = meta.String("url")
|
||||
)
|
||||
var r io.Reader
|
||||
var (
|
||||
r io.Reader
|
||||
client = &http.Client{
|
||||
Transport: &http.Transport{},
|
||||
Timeout: time.Second * 3,
|
||||
}
|
||||
)
|
||||
if obj := meta.Obj.Lookup("request"); obj.Exists() {
|
||||
if v := obj.Lookup("body"); v.Exists() {
|
||||
r, err = v.Reader()
|
||||
@@ -83,7 +92,43 @@ func (c *HTTPCmd) Run(meta *registry.Meta) (res interface{}, err error) {
|
||||
}
|
||||
req.Header = header
|
||||
req.Trailer = trailer
|
||||
resp, err := c.Client.Do(req)
|
||||
|
||||
if tlsConfig := meta.Obj.Lookup("tls_config"); tlsConfig.Exists() {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
NextProtos: []string{"http/1.1"},
|
||||
},
|
||||
}
|
||||
ca := tlsConfig.Lookup("ca")
|
||||
if caCrt, err := ca.String(); err != nil {
|
||||
return nil, errors.WithMessage(err, "parse ca")
|
||||
} else {
|
||||
pool := x509.NewCertPool()
|
||||
pool.AppendCertsFromPEM([]byte(caCrt))
|
||||
tr.TLSClientConfig.RootCAs = pool
|
||||
}
|
||||
|
||||
cert := tlsConfig.Lookup("client_crt")
|
||||
key := tlsConfig.Lookup("client_key")
|
||||
if cert.Exists() && key.Exists() {
|
||||
crtData, err := cert.String()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyData, err := key.String()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cliCrt, err := tls.X509KeyPair([]byte(crtData), []byte(keyData))
|
||||
if err != nil {
|
||||
return nil, errors.WithMessage(err, "parse client keypair")
|
||||
}
|
||||
tr.TLSClientConfig.Certificates = []tls.Certificate{cliCrt}
|
||||
}
|
||||
|
||||
client.Transport = tr
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ limitations under the License.
|
||||
package http
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -27,6 +30,7 @@ import (
|
||||
"cuelang.org/go/cue"
|
||||
"github.com/bmizerany/assert"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/http/testdata"
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/registry"
|
||||
)
|
||||
|
||||
@@ -96,6 +100,29 @@ func TestHTTPCmdRun(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestHTTPSRun(t *testing.T) {
|
||||
s := newMockHttpsServer()
|
||||
defer s.Close()
|
||||
r := cue.Runtime{}
|
||||
reqInst, err := r.Compile("-", `method: "GET"
|
||||
url: "https://127.0.0.1:8443/api/v1/token?val=test-token"`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
reqInst, _ = reqInst.Fill(decodeCert(testdata.MockCerts.Ca), "tls_config", "ca")
|
||||
reqInst, _ = reqInst.Fill(decodeCert(testdata.MockCerts.ClientCrt), "tls_config", "client_crt")
|
||||
reqInst, _ = reqInst.Fill(decodeCert(testdata.MockCerts.ClientKey), "tls_config", "client_key")
|
||||
|
||||
runner, _ := newHTTPCmd(cue.Value{})
|
||||
got, err := runner.Run(®istry.Meta{Obj: reqInst.Value()})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
body := (got.(map[string]interface{}))["body"].(string)
|
||||
|
||||
assert.Equal(t, "{\"token\":\"test-token\"}", body)
|
||||
}
|
||||
|
||||
// NewMock mock the http server
|
||||
func NewMock() *httptest.Server {
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -118,3 +145,40 @@ func NewMock() *httptest.Server {
|
||||
ts.Start()
|
||||
return ts
|
||||
}
|
||||
|
||||
func newMockHttpsServer() *httptest.Server {
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
fmt.Printf("Expected 'GET' request, got '%s'", r.Method)
|
||||
}
|
||||
if r.URL.EscapedPath() != "/api/v1/token" {
|
||||
fmt.Printf("Expected request to '/person', got '%s'", r.URL.EscapedPath())
|
||||
}
|
||||
r.ParseForm()
|
||||
token := r.Form.Get("val")
|
||||
tokenBytes, _ := json.Marshal(map[string]interface{}{"token": token})
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(tokenBytes)
|
||||
}))
|
||||
l, _ := net.Listen("tcp", "127.0.0.1:8443")
|
||||
ts.Listener.Close()
|
||||
ts.Listener = l
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
pool.AppendCertsFromPEM([]byte(decodeCert(testdata.MockCerts.Ca)))
|
||||
cert, _ := tls.X509KeyPair([]byte(decodeCert(testdata.MockCerts.ServerCrt)), []byte(decodeCert(testdata.MockCerts.ServerKey)))
|
||||
ts.TLS = &tls.Config{
|
||||
ClientCAs: pool,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
NextProtos: []string{"http/1.1"},
|
||||
}
|
||||
ts.StartTLS()
|
||||
return ts
|
||||
}
|
||||
|
||||
func decodeCert(in string) string {
|
||||
out, _ := base64.StdEncoding.DecodeString(in)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
39
pkg/builtin/http/testdata/certs.go
vendored
Normal file
39
pkg/builtin/http/testdata/certs.go
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package testdata
|
||||
|
||||
var (
|
||||
_ = `LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBcHRMN21JQmdaaDVEd1FYYkJXaHRSeURGK01qaytQeStNU1Vyck5pc1EyeXF4cnphCjhEeWw5a0pRWW5oMnVYVFV1RnBzbDRhM1J5dEJaVkdrMDNQT0RXOWJIblR2QUNPZHJjMnR2WmR5ZXRXU1ZtQ2cKOHhuc3Y3WHVQS0VGb0VwakVaMDdCWjY2blFIRDg2MHFMeGFGRWtMNHk2MzU5SThWVlRBYk5RejVPQ3dmM29mUQpMN0JPL2RVNUJtRTNXTDhhVHF3SXRSa0hJeE5pWCs4OWU2Z3dCY3RHdUZLR3ZacFhGaW1VeXA1Y0crVWI2RzkyCi9KUTZJWm45dGFIZ3NFYWIvWUNwZ2U1Rkp5WVR1dzVlakhRajRYNVh3ZVRKU0tsN0UwUmZhMjl5VnM5aXdhNDQKcmVNSzVXR2hVUFl6T1o0MURGZnU1MmJnMjVPODF6QWJFSFpLUndJREFRQUJBb0lCQUNUVUJ2OFB1RGhURGhvYQp0Tk5vemxjWmdSci9IcTFvL29QUzlPVmZvQWZ5Z1hFR1dEOFk1SHFOQVRuNzVobmpGT0x0ODNNd0psM3J5ckFYCmFnL1VUUFRpVkhkUTBVSnltbWk0TTFiYmpFWlp4OGlSNUhaR2p1Rnp4SGhXQSt2ekFCUHZaZ3hEa21iKzhNZG0KdngxT0YycUVwbkF3cERHOU5MUnR2bFBqM1ZEczhVODU2c2hWeDdBdFE3RGJUWkQwdEpsQ0pzTzR5TitjL1oxOApiRzJKNDB2RWFLalVGTE9HNitScE43NEZLeGtvOFJJejZxeERQMk5VMUg1ajVVVi9tZXdRdDBsRTNqbEc5MmcvCnVwTngyK0xnYUkrMWhCR3AzV2prQlRWcWloZWxrUk5XZkNLczdXOHJtYk83V3MvK2cwcVNidnAvUjBWQWpQd0MKdGt4SENFRUNnWUVBM2s3K0hOVkNZY0YxN2k2ZTJnNTJDVHV0cDJBYzkvSUNMdVJzNGFRZlB4MkxFc2VDalJnNgovaHNsOGpLbmRDS1JQdTBJbkoxckF4NzVrZXBKZWpWcTBIbkFEN2VtcVhuMDN0UjJmb3hvbkxBOEtQMzdSSnJqClhlZ0k5NiswWUU3QUY5dWZqQVhPeXpFU3RQVkNSVDlJOFRMSlEwRFhraW56bDhVUm5aZ1RjdmtDZ1lFQXdCdFYKLzNnbFR5Z0syNTFpMS9FakdrK3I3THF5NzdCY29LVzZHTm91K0FiQ3gxalhZVE1URDNTRXVyMzBueHB6VWNkdgpIbEI1NkI2Q1JmRkdXN0o1U0tkeXI5WmhQUUtITUQ1TkZhbm00S1F4NmZmVFhubExRdnhhT2c2TFRnTDRSdjFyCjVaeUdEbDhBKzRRckpNVk1OOTZOVEY1VDB0TXRUaHlIVnpLbHR6OENnWUJ3Q3BQYjZFZUtpVHhzakthVzg4N2QKbkd4Sy9RL2NqdVkyeC8xd1E0MVQvQW5KcnkvRytMMVNzRkFSbnlIeVVER3Y2enI1NUFTNUQvVnNhdzRaUDY3VAozMmpEQXlaR0tDY1gzekRSV3VhbWdkUHdQUUZVZEZPL1VtQ2lwTFZlREpLWDg2S1hxWjJ0bnMvMHo5OVVreTZxCkVaU0tCclllL25HOHZoL0FzNUtwMFFLQmdRQzFxT1BncWFkMk8rSlFuSHE4d3UwejAwVTduYXpabFlkeDdtV1YKWExUdm04MFNuME5FU2Z6ckwzN1g3QXJuYlNiQm5YckpTc2FNcGxVQWVORFVvMmVuT1pqdENDZDVmdXVCeGxnMApkUzY3SE9tS1d1ekl1S0JmM3F3Zm5HTkV5UEFvaVRvL3JZempDQm13dmVIaWFxUFJiU1Ztb3doWEk1VUMrVjFPCktybWtGd0tCZ1FEVERDWlg1WWQ5ZUdXZG1OM3pUU2Z6YkRrRkxqZkYyYTVBK2lDL281TmoyVmpHRG4xTjRvVUwKajF0dVZLb0xoVjhVZzd0Lzc4V0V0UkRnK1p3QVZhSW84bE1zU244dDVQNFFrY2pkSDI4bHpFaTQwWHpxQkF0Lwpoalppb1pNN2ZHUmJWK29yakZSQ2tZWnNaMUdua2FrbG5Mdk4vYVRuM25HV2tEZjFaZGM0YVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==` //ca.key
|
||||
caCrt = `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNyakNDQVpZQ0NRRDV0K3E3ZkswSlVEQU5CZ2txaGtpRzl3MEJBUXNGQURBWk1SY3dGUVlEVlFRRERBNHEKTG10bGRXSmxkbVZzWVM1cGJ6QWVGdzB5TVRFeE1qSXdPRFEyTlRsYUZ3MHpOVEE0TURFd09EUTJOVGxhTUJreApGekFWQmdOVkJBTU1EaW91YTJWMVltVjJaV3hoTG1sdk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBCk1JSUJDZ0tDQVFFQXB0TDdtSUJnWmg1RHdRWGJCV2h0UnlERitNamsrUHkrTVNVcnJOaXNRMnlxeHJ6YThEeWwKOWtKUVluaDJ1WFRVdUZwc2w0YTNSeXRCWlZHazAzUE9EVzliSG5UdkFDT2RyYzJ0dlpkeWV0V1NWbUNnOHhucwp2N1h1UEtFRm9FcGpFWjA3Qlo2Nm5RSEQ4NjBxTHhhRkVrTDR5NjM1OUk4VlZUQWJOUXo1T0N3ZjNvZlFMN0JPCi9kVTVCbUUzV0w4YVRxd0l0UmtISXhOaVgrODllNmd3QmN0R3VGS0d2WnBYRmltVXlwNWNHK1ViNkc5Mi9KUTYKSVpuOXRhSGdzRWFiL1lDcGdlNUZKeVlUdXc1ZWpIUWo0WDVYd2VUSlNLbDdFMFJmYTI5eVZzOWl3YTQ0cmVNSwo1V0doVVBZek9aNDFERmZ1NTJiZzI1TzgxekFiRUhaS1J3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCCkFRQWJ1dGZjbENOZVhTaldBR0NSb2tyTVN2Z0VvMlZEdnE4Y1lEN3hIT3gzRllQRWE0Rk01VC9uSXVsNGJxSCsKY09mOCtMOTZXTGNUUnpNRnhrMmNKT2VKV3hFMDkzcDN2dHRZMFUrOGZ4T1FIY3JxK1N3U0dPTUpWTHhEcGtPNApscFVpc0JYOENGQld5VG9vN05WRy9FZGRVS1FHa2ttaGJMdXJIZStHTnFmT0VpS01GYm1PRHBzZ1Zqc0oxK2hPCjZDWG8zZW01Mlh4eVZqbGtoNzBJK29UMW5PeGFYSEhwK0NNT2JPSXkzcFhMejJROWNmRU1uTlZrVTBDMmFaeksKS1ViMGZXOTlpbjBJRmlUd0NkQlhRTlRpMzh6bVEvUUlEYlJEQTJFREtMa2pZRzdUUFR4Wm9xL04rQUQ3ZElLWQpyaE56TXB6cGhhRGR4Ymt3cmlHRGQ5TEkKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==`
|
||||
serverKey = `LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBemdMMTJpL0gwaXk5MGhLb0sySUwrbnIvRDB0RGlPdVlwYk5NUktCTTJyMGtCblhCClJUdU1peWNWMUd5OGlwQ1FLMmwwV1E3dDJpTStLT1BBTFYxQ0thNEtpTlg5M015cWlmVFVBc3YzemRtNkhiZFMKa3owcUlOYTBoZTBaclA3M3g0YWZHRmJ2SXRwU1pWQThwSUhrc281SHFhcTRndTcwVUhRSlhZcFIrRjlKY3l3eAppWTZ4S0x6QWNGcjlsdktZdlVaWitRR1FUbWh4TFFtKzI5cUJsZXIvRGpEQzlkZjM2blFkSU5wdUpIak1tZXI2CnZQVU5CekQ5OWliT3NpYVBxMlo1VHRuY3U0TlRzKzlLN09BWnhLK1d4VVp6c3pKbnhHNjgxR010MXJ1anBIVlMKSGIrYmh2ek9aRmt6aFhWVE5wL0FYMElNdy92K3hpZzl3WXkyK1FJREFRQUJBb0lCQVFESmFObUdWRnB1NERGQgpGZDUyYzZnMFhsWEpWUk1VNVFsYlR2MU14cy84dHhobWZHL1ZTUS94NStlT3hEUmM0Rk1qTGptQzdIYWNZd0pkCnBiVDRaUW5QaUFsaW1KeFdaMzUvMiszL1Fmem1zMndqcTF3KytYaWJuRzNuMWRQWmIzaytDQjY1QkIxT0hOYWIKbUtPQlRrRVNWTW81VmVDSW1pZ2dGQ0luNHBpYlVvSXpHcmdabVRsTmlQTjFPb2FNNk9IcEorZDVGNDFNdGYwbgpJYjAyTVYzdUtZb1hqUWtFYytBL3B3WDJ0TVlGUTMza3NwTlZjSURnYU4zUWRsb3IxQXhDN0xQaStKeTZNelY1CmJ4VDhlcFhZN2VmUFhqblR0VmVHQWFUNThJSFdWS29ncmt6V21xdHROMUtzc2RBWGpja1NWRksxL0U5V1c4Q28KWDBTa3VpUFJBb0dCQVA1SERCSDZkRURqbVp0TVVFeHEwNWlwcWxSbFhnYUdYT01lT0VIZ1VSVzhEdnJiNC9zLwo4cEswUWZCUUpkYTIwT1d0dVprSDNYWEVnNktjL0NyMWZIQU9uNElmOFI1NlJNRUpWUnhvTzlBZWZVem9nZjAvCndWUlpmZmRUTkhKV2E3VExJaVdNdXpmY2k0bTdldnZkNkpUS3lzTlRvREJuemM0ZFpzcGhxWHh0QW9HQkFNOW8KTnBqSmxsZDBrUENicFRtRjZMRGpBMzAvaS9DRzlVNEoxaUFrQno3SzA2TU9ENDA3TlZ5QTV0V2p5QjlSTThnbwpMcjZhK1g3MDN2YWVMZDZQcDY2UnlDbzU4RWFhcFk2SFQvTGVNSGRzUllEdk9PU2pOT0FtbkJxcFFVR1Z2ZVhTClpCN2srclpVK3g2UktEblFod3crZGsveUZkZmJ5VmxhTDRKVFZiVTlBb0dCQVBOYUNYbzNTUVZGRGFBc0EvbHUKajMxZWUwMzBDVzJUTDlpSTlteE5neXlhNDNjLzlNdGpZd0wyRXRrcnkxclhjY3N1WFI3UkFTaVJYeTNFc2kxbQo3YVhNeU9sZktvTHhuMVZqV2hvcXczdWxnbU9WYmJweVJ0TTBKck1KNVhxN3JLN0ZiYk9rSVJVUU5GY25uMGJuCkZJMDZHNTJlTGdQRmhKaUxXUEc5VDlodEFvR0JBS1JrWEluamxqZEJYRFJwbVo4clpWRDJ6bWd5dXc5dFdQZCsKMG1wdFJCVGdITGtyeHVYUlhTMHh1a1R4YVFoeGkxS0ZqdTlpMUlodFBHQks1ZDUzREpoUVVsQXQxaVdRSTlNQgpxenU4SXJ3MVpDMmE3d1JCM0FJaWVDNmxvdVNCOUo4NWtFUHdpRXVHdGZmM1krUFhSWU5ONnViWTRibFRLcGVZCjVQa3Vaa3VkQW9HQVozTHg0UGNnK3RSR0dsclR0WllXZmNxT3FDcUIya0NCa2tDVnlvWW9qSzM4a21CNVJ0QmQKZzBnMTc5TGdUTWE0Y0ZWRUhyZC9xU2RRQVZiTmxyRDh4MjJNYnJMam1aa05aOXQ1alpJSWQwRVRxYTJBNC8rNApOV05HeU12b0ttTmMxcFd2UEJiT1R1RHp2WEg3YnZzbXAzallucjJQU09WaFU1RGdJRHpEQTJBPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==`
|
||||
serverCrt = `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMzekNDQWNlZ0F3SUJBZ0lKQU55SVoyTElxQTNqTUEwR0NTcUdTSWIzRFFFQkJRVUFNQmt4RnpBVkJnTlYKQkFNTURpb3VhMlYxWW1WMlpXeGhMbWx2TUI0WERUSXhNVEV5TWpBNU16UXpORm9YRFRNMU1EZ3dNVEE1TXpRegpORm93R0RFV01CUUdBMVVFQXd3TktpNXJkV0psZG1Wc1lTNXBiekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBTTRDOWRvdng5SXN2ZElTcUN0aUMvcDYvdzlMUTRqcm1LV3pURVNnVE5xOUpBWjEKd1VVN2pJc25GZFJzdklxUWtDdHBkRmtPN2RvalBpamp3QzFkUWltdUNvalYvZHpNcW9uMDFBTEw5ODNadWgyMwpVcE05S2lEV3RJWHRHYXorOThlR254aFc3eUxhVW1WUVBLU0I1TEtPUjZtcXVJTHU5RkIwQ1YyS1VmaGZTWE1zCk1ZbU9zU2k4d0hCYS9aYnltTDFHV2ZrQmtFNW9jUzBKdnR2YWdaWHEvdzR3d3ZYWDkrcDBIU0RhYmlSNHpKbnEKK3J6MURRY3cvZlltenJJbWo2dG1lVTdaM0x1RFU3UHZTdXpnR2NTdmxzVkdjN015WjhSdXZOUmpMZGE3bzZSMQpVaDIvbTRiOHptUlpNNFYxVXphZndGOUNETVA3L3NZb1BjR010dmtDQXdFQUFhTXJNQ2t3Q1FZRFZSMFRCQUl3CkFEQUxCZ05WSFE4RUJBTUNCZUF3RHdZRFZSMFJCQWd3Qm9jRWZ3QUFBVEFOQmdrcWhraUc5dzBCQVFVRkFBT0MKQVFFQUJNbUhSZG4rS043QWZTL3JicHI2dGx6SHBoRFJud29KR0NxSkZYZjdabUN1TEF3NzVsTlhxOUxka2NJeApSZXhleXk2cnk2SmF6RGN4OVltWHVnZzFtTTlrWE5kTmc0NmVSangzRk4vL2FRUFJOMHNuTDVOaXRyM0kvdEJmCkxNdlduUisrQ2tZSnFtM1NuTnRicVR0cDhodTZKWnVRUVh2WWM0ZEg5VmJRM2d3UzFSUzdhQ0RBZHlLZEhnSFQKZmN3VnNqZmk2TzhLdlROaG43aU1LWERZQUhiWXh3ekpsdjBEWFhuZjhmRlo3U09FT3VkbGM5Y3hOQW0xVlBjZAo1YXcwR0hvbWMxNTdHU244UmpWenlJOHRPdGE4WU9uaU9SOE5qNElzMExRQXF3VjJ1OU52Zkg3bkJMUjg3d1Z2CmFxUmxaWE5uOG5qcWgwdzZkc3BUWjRwQWFBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==`
|
||||
clientCrt = `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5VENDQWJHZ0F3SUJBZ0lKQU55SVoyTElxQTNpTUEwR0NTcUdTSWIzRFFFQkJRVUFNQmt4RnpBVkJnTlYKQkFNTURpb3VhMlYxWW1WMlpXeGhMbWx2TUI0WERUSXhNVEV5TWpBNE5UVTFNRm9YRFRNMU1EZ3dNVEE0TlRVMQpNRm93RmpFVU1CSUdBMVVFQXd3TGRHVnpkRjlzYVdwcFlXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQzhZNGU1ZElYd3FaL1dWOFVLMEhVc2toRlRmTytxMC96VU9CZVl0amplNFQrTmhlc2oKS0tkLzhWLzBYZTY5ck5CYXE3RVBhYUFReDVYYTF1aGh2SWRXU2F2QWhmaTgwd3lXSy9reUtKR0xsaTZleTZtLwpjZkdxRVJ5eUtnc2NoZWFrQ3dCajArZkxnVUZ5aVM0MzVubnVZZ2Y0MXFmRVJ1azREUExDVk9uRE13dXBmQkdyClNacmY2U0R3Z0V3SnV2QVlhQ0owcE91NkovRzhkMVNOb3I4UFlGQjBFbGl2d2ZESk9CRjFvMEg2elYzMHZ1bVoKRzM0anpoNjh3aThPNG1TZjZCbi9XMlEyckNvY1FlSE9nUVRGcHVtdC9qYy9lMnhlRFpOd3RpS25OMTdWa3o1QwpXVGxpUEZuQlRWTWZCeHEyOGNIemtzaTVBRDZ5bVlRMkNzcTVBZ01CQUFHakZ6QVZNQk1HQTFVZEpRUU1NQW9HCkNDc0dBUVVGQndNQ01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQnpKRnFlUk9BRDZ0ZkVrNElsNGxvbDI4OGIKaFZMMnRXdThXbGtDdHFQaFNOR0hkeWJQcGdLL3dCajQzS3FGcFRMVGo0TStDT0cwR08xZDVMK1lROHdHOHJGQQpHWTd3ZndQLzRlenpzSzNocmI5NnNpdm04TUZqdXRzSEdzenFWRkZ0UXBNWkhBTm5FQXY0ZkxGSEtQM0ZubmkyCnpjYmwrVXNQWFk3QU5NelpOelIwQVdLWmxwbm5hMUpuQWtzQnBBTzlweFRKOU55MzhVNlc0SERrN2gyVk5BUHAKbGpxRmNoYXdjTkN1MDIzV2hhWWxuNGowTG9NRlh0NDJNMXgxL2R4SnQxNUlnNFB5LysrbmZRbmtvN09vSmVpVAppb0lNc3VBcmNJaG1MSU8zZzFTNVJtNzJ6NDUwSXV0blFWQUc3MVQ0alZyR3libHhnMWpGVjFXWHJ1V2MKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==`
|
||||
clientKey = `LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdkdPSHVYU0Y4S21mMWxmRkN0QjFMSklSVTN6dnF0UDgxRGdYbUxZNDN1RS9qWVhyCkl5aW5mL0ZmOUYzdXZhelFXcXV4RDJtZ0VNZVYydGJvWWJ5SFZrbXJ3SVg0dk5NTWxpdjVNaWlSaTVZdW5zdXAKdjNIeHFoRWNzaW9MSElYbXBBc0FZOVBueTRGQmNva3VOK1o1N21JSCtOYW54RWJwT0F6eXdsVHB3ek1McVh3UgpxMG1hMytrZzhJQk1DYnJ3R0dnaWRLVHJ1aWZ4dkhkVWphSy9EMkJRZEJKWXI4SHd5VGdSZGFOQitzMWQ5TDdwCm1SdCtJODRldk1JdkR1SmtuK2daLzF0a05xd3FIRUhoem9FRXhhYnByZjQzUDN0c1hnMlRjTFlpcHpkZTFaTSsKUWxrNVlqeFp3VTFUSHdjYXR2SEI4NUxJdVFBK3NwbUVOZ3JLdVFJREFRQUJBb0lCQUhYYjZ1aTZucVUrNmRHbQpYWTd6ZGFzcHd3OHhaWnZCUGpiaTFOaGtnRlhvSStOOWVlc29Id3FyVHZYSjRuZmw2d0FlMUFvcGNjdXRvZklrCmE0UGg5K1dpOTRIZUR3ekxHTi9HcVFPWlg5MHRXd05idFZvaGhpaDR4alFzbTREL3dKaTJqVXJuSXVndGVHMlkKcDBLdnZXN0hBK2ZKRzNKdlRxOFRZcmp6ZUwvMlYzUnRSbk1oNldjcWI0cWpRb2NZWkR3VU43MVBVYURrUTRLSApWdHNNSjloc0dBUDFDVFRQckZZR1daRUZiN0xtZGNRemJyWVZyQnhwaGRoZGpqUXBjVzAySjZHU1ZrY0NMeFkvCnVRYnpZS0RkUXU1SHJKbVpiNjlFRmJWZHp3OTh3alIvNyt0dUhmdlJzYkUxRWdKWlQxNkhSUHEwbW1mMWxHM3EKNm9ZbnNCRUNnWUVBNVd2SEE4bWliMVpYWiszaXN3SUh0SlZ5WGJWM0Y4ejZ5UHRaK2ZNa1ljY3BBb3g0SDRTbgp1azllN2NlN0lhMDJueXlwTmlIaXZMRXZ3dGlqNjlBQ3I1WWpMMzlDMUlYbjJYMUg3V2FKaHF2K21zOW5ybmV0CmRqY0RtZXJRRHBVU0IzbXFLQlhXY2dVaXA4NUVYMlo5SzhPbnRhNXV6MG8vb2R4a0VTdWM3M1VDZ1lFQTBqYlAKUVBjY1N4RmRsVDFEcjg0WWhkUDJzQUJ6YUpoWDNzUm44NnhBTWk4aW9PY05lMTh1cVFBdk4rQWpRQUFndlkyOQo3dVdRcXB1SlFueG9NcGJMVjdjSkw2aHBlekpEL2lhZDVzREpyMC9jTWVhK3JSWVFQK2xxSW9YZTI2TlZPZnNHCmZGNkpHZUdvUGpRTmVKM1FSV0NaMEo0UkRob242YjZCWHVFVTZiVUNnWUVBczlCRGpiNXQ1K0crWkNEWlBBQnQKVmFhRW10bnQyK08yOCt1OVcrQ3NOVTdKMzh1Rkl2N3dEMkRDUUkvNUphNERUOExMWlRndDVFTGo4azJtUE44dQpHNzBMR3VFZDJrQ1J0YTh4dnVwTkJCYXVXVndTSVhaL3FGWDZKcHNhTXpPM2k5QmFBMDBLWlJlTlVBU2xKampJCkJwTTFVWHJFTXdnNDAzNVBsLzJjNVRrQ2dZQnRmL054cWNicEs0Q043cjNGWkJ2T0NsMmp6SGhSY1puRUJwY0gKalNCYmc4WUwvbzg5UnBWdG54VDVqQjJRaHdDRy9NQ0ZJcnU2d3c0NnZjY2hJditGRDJrUGxEQnQ1ZjhZOGxDcQpGSjU2WGFVYnNWQjlwTktPR0M0YkVaVEc0RXZTeWZuVTZ3R0xvOG9ack0rZmxzVVlmbnRnK2hWMFBSZXhZSFRQClVYdXRTUUtCZ1FDck9WeHBqNXFKdmMyaUZrMXNoWDRXeDBYbHpzZzI3QkdUNy9zYmtrMHMxT1ViZEZueTErTUkKNUVpVU1xUHM5TU5IOWZxbHNmMEJCS1BXMW0wVFAvSHo2OHFrRm80cnJrZVlMYmYvYVN2OWFJNnRodGJTWUoyUQpKTm9qeW1Ea2ZFbmNDOTNsMUV5alF0Y1lJSGNDWFRGMlhibXVwdEtlT2lqeC84c3FTOUVkRmc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==`
|
||||
MockCerts = struct {
|
||||
Ca string
|
||||
ServerKey string
|
||||
ServerCrt string
|
||||
ClientCrt string
|
||||
ClientKey string
|
||||
}{
|
||||
Ca: caCrt,
|
||||
ServerCrt: serverCrt,
|
||||
ServerKey: serverKey,
|
||||
ClientKey: clientKey,
|
||||
ClientCrt: clientCrt,
|
||||
}
|
||||
)
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/workflow/providers/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -53,6 +55,7 @@ func (h *AppHandler) GenerateApplicationSteps(ctx context.Context,
|
||||
kube.Install(handlerProviders, h.r.Client, h.Dispatch, h.Delete)
|
||||
oamProvider.Install(handlerProviders, app, h.applyComponentFunc(
|
||||
appParser, appRev, af), h.renderComponentFunc(appParser, appRev, af))
|
||||
http.Install(handlerProviders, h.r.Client, app.Namespace)
|
||||
taskDiscover := tasks.NewTaskDiscover(handlerProviders, h.r.pd, h.r.Client, h.r.dm)
|
||||
multiclusterProvider.Install(handlerProviders, h.r.Client, app)
|
||||
terraformProvider.Install(handlerProviders, app, func(comp common.ApplicationComponent) (*appfile.Workload, error) {
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/policy/envbinding"
|
||||
errors3 "github.com/oam-dev/kubevela/pkg/utils/errors"
|
||||
)
|
||||
@@ -62,6 +63,20 @@ func ensureResourceTrackerCRDInstalled(ctx context.Context, c client.Client, clu
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureVelaSystemNamespaceInstalled ensures vela namespace to be installed in child cluster
|
||||
func ensureVelaSystemNamespaceInstalled(ctx context.Context, c client.Client, clusterName string, createNamespace string) error {
|
||||
remoteCtx := ContextWithClusterName(ctx, clusterName)
|
||||
if err := c.Get(remoteCtx, types2.NamespacedName{Name: createNamespace}, &v1.Namespace{}); err != nil {
|
||||
if !errors2.IsNotFound(err) {
|
||||
return errors.Wrapf(err, "failed to check vela-system ")
|
||||
}
|
||||
if err = c.Create(remoteCtx, &v1.Namespace{ObjectMeta: v12.ObjectMeta{Name: createNamespace}}); err != nil {
|
||||
return errors.Wrapf(err, "failed to create vela-system namespace")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureClusterNotExists checks if child cluster has already been joined, if joined, error is returned
|
||||
func ensureClusterNotExists(ctx context.Context, c client.Client, clusterName string) error {
|
||||
secret := &v1.Secret{}
|
||||
@@ -173,6 +188,11 @@ func JoinClusterByKubeConfig(_ctx context.Context, k8sClient client.Client, kube
|
||||
_ = k8sClient.Delete(_ctx, secret)
|
||||
return cluster, errors.Wrapf(err, "failed to ensure resourcetracker crd installed in cluster %s", clusterName)
|
||||
}
|
||||
|
||||
if err := ensureVelaSystemNamespaceInstalled(_ctx, k8sClient, clusterName, types.DefaultKubeVelaNS); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create vela namespace in cluster %s", clusterName)
|
||||
}
|
||||
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ const (
|
||||
|
||||
// LabelAddonName indicates the name of the corresponding Addon
|
||||
LabelAddonName = "addons.oam.dev/name"
|
||||
|
||||
// LabelProject Namesapce records the project name of namespace
|
||||
LabelProjectNamesapce = "namespace.oam.dev/project"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
header: [string]: string
|
||||
trailer: [string]: string
|
||||
}
|
||||
tls_config?: secret: string
|
||||
response: {
|
||||
body: string
|
||||
header?: [string]: [...string]
|
||||
|
||||
@@ -17,7 +17,13 @@ limitations under the License.
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/builtin"
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/registry"
|
||||
@@ -33,10 +39,61 @@ const (
|
||||
)
|
||||
|
||||
type provider struct {
|
||||
cli client.Client
|
||||
ns string
|
||||
}
|
||||
|
||||
// Do process http request.
|
||||
func (h *provider) Do(ctx wfContext.Context, v *value.Value, act types.Action) error {
|
||||
tlsConfig, err := v.LookupValue("tls_config")
|
||||
if err == nil {
|
||||
secretName, err := tlsConfig.GetString("secret")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectKey := client.ObjectKey{
|
||||
Namespace: h.ns,
|
||||
Name: secretName,
|
||||
}
|
||||
index := strings.Index(secretName, "/")
|
||||
if index > 0 {
|
||||
objectKey.Namespace = secretName[:index-1]
|
||||
objectKey.Name = secretName[index:]
|
||||
}
|
||||
|
||||
secret := new(v1.Secret)
|
||||
if err := h.cli.Get(context.Background(), objectKey, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
if ca, ok := secret.Data["ca.crt"]; ok {
|
||||
caData, err := base64.StdEncoding.DecodeString(string(ca))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v.FillObject(string(caData), "tls_config", "ca"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if clientCert, ok := secret.Data["client.crt"]; ok {
|
||||
certData, err := base64.StdEncoding.DecodeString(string(clientCert))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v.FillObject(string(certData), "tls_config", "client_crt"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if clientKey, ok := secret.Data["client.key"]; ok {
|
||||
keyData, err := base64.StdEncoding.DecodeString(string(clientKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v.FillObject(string(keyData), "tls_config", "client_key"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
ret, err := builtin.RunTaskByKey("http", cue.Value{}, ®istry.Meta{
|
||||
Obj: v.CueValue(),
|
||||
})
|
||||
@@ -47,8 +104,11 @@ func (h *provider) Do(ctx wfContext.Context, v *value.Value, act types.Action) e
|
||||
}
|
||||
|
||||
// Install register handlers to provider discover.
|
||||
func Install(p providers.Providers) {
|
||||
prd := &provider{}
|
||||
func Install(p providers.Providers, cli client.Client, ns string) {
|
||||
prd := &provider{
|
||||
cli: cli,
|
||||
ns: ns,
|
||||
}
|
||||
p.Register(ProviderName, map[string]providers.Handler{
|
||||
"do": prd.Do,
|
||||
})
|
||||
|
||||
@@ -17,13 +17,25 @@ limitations under the License.
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/test"
|
||||
"gotest.tools/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/http/testdata"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/model/value"
|
||||
"github.com/oam-dev/kubevela/pkg/workflow/providers"
|
||||
)
|
||||
@@ -102,7 +114,7 @@ request:{
|
||||
|
||||
func TestInstall(t *testing.T) {
|
||||
p := providers.NewProviders()
|
||||
Install(p)
|
||||
Install(p, nil, "")
|
||||
h, ok := p.GetHandler("http", "do")
|
||||
assert.Equal(t, ok, true)
|
||||
assert.Equal(t, h != nil, true)
|
||||
@@ -134,3 +146,68 @@ func runMockServer(shutdown chan struct{}) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPSDo(t *testing.T) {
|
||||
s := newMockHttpsServer()
|
||||
defer s.Close()
|
||||
cli := &test.MockClient{
|
||||
MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
secret := obj.(*v1.Secret)
|
||||
*secret = v1.Secret{
|
||||
Data: map[string][]byte{
|
||||
"ca.crt": []byte(testdata.MockCerts.Ca),
|
||||
"client.crt": []byte(testdata.MockCerts.ClientCrt),
|
||||
"client.key": []byte(testdata.MockCerts.ClientKey),
|
||||
},
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
v, err := value.NewValue(`
|
||||
method: "GET"
|
||||
url: "https://127.0.0.1:8443/api/v1/token?val=test-token"
|
||||
`, nil, "")
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, v.FillObject("certs", "tls_config", "secret"))
|
||||
prd := &provider{cli, "default"}
|
||||
err = prd.Do(nil, v, nil)
|
||||
assert.NilError(t, err)
|
||||
|
||||
}
|
||||
|
||||
func newMockHttpsServer() *httptest.Server {
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
fmt.Printf("Expected 'GET' request, got '%s'", r.Method)
|
||||
}
|
||||
if r.URL.EscapedPath() != "/api/v1/token" {
|
||||
fmt.Printf("Expected request to '/person', got '%s'", r.URL.EscapedPath())
|
||||
}
|
||||
r.ParseForm()
|
||||
token := r.Form.Get("val")
|
||||
tokenBytes, _ := json.Marshal(map[string]interface{}{"token": token})
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(tokenBytes)
|
||||
}))
|
||||
l, _ := net.Listen("tcp", "127.0.0.1:8443")
|
||||
ts.Listener.Close()
|
||||
ts.Listener = l
|
||||
|
||||
decode := func(in string) []byte {
|
||||
out, _ := base64.StdEncoding.DecodeString(in)
|
||||
return out
|
||||
}
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
pool.AppendCertsFromPEM(decode(testdata.MockCerts.Ca))
|
||||
cert, _ := tls.X509KeyPair(decode(testdata.MockCerts.ServerCrt), decode(testdata.MockCerts.ServerKey))
|
||||
ts.TLS = &tls.Config{
|
||||
ClientCAs: pool,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
NextProtos: []string{"http/1.1"},
|
||||
}
|
||||
ts.StartTLS()
|
||||
return ts
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ func suspend(step v1beta1.WorkflowStep, opt *types.GeneratorOptions) (types.Task
|
||||
func NewTaskDiscover(providerHandlers providers.Providers, pd *packages.PackageDiscover, cli client.Client, dm discoverymapper.DiscoveryMapper) types.TaskDiscover {
|
||||
// install builtin provider
|
||||
workspace.Install(providerHandlers)
|
||||
http.Install(providerHandlers)
|
||||
convert.Install(providerHandlers)
|
||||
email.Install(providerHandlers)
|
||||
templateLoader := template.NewWorkflowStepTemplateLoader(cli, dm)
|
||||
@@ -122,7 +121,7 @@ func NewViewTaskDiscover(pd *packages.PackageDiscover, cli client.Client, apply
|
||||
query.Install(handlerProviders, cli)
|
||||
time.Install(handlerProviders)
|
||||
kube.Install(handlerProviders, cli, apply, delete)
|
||||
http.Install(handlerProviders)
|
||||
http.Install(handlerProviders, cli, viewNs)
|
||||
convert.Install(handlerProviders)
|
||||
email.Install(handlerProviders)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
@@ -41,7 +42,7 @@ var _ = Describe("Test application rest api", func() {
|
||||
defer GinkgoRecover()
|
||||
var req = apisv1.CreateApplicationRequest{
|
||||
Name: appName,
|
||||
Namespace: appProject,
|
||||
Project: appProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -60,7 +61,7 @@ var _ = Describe("Test application rest api", func() {
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(cmp.Diff(appBase.Name, req.Name)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Description, req.Description)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Namespace, req.Namespace)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Project.Namespace, fmt.Sprintf("project-%s", appProject))).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Labels["test"], req.Labels["test"])).Should(BeEmpty())
|
||||
})
|
||||
|
||||
@@ -80,7 +81,7 @@ var _ = Describe("Test application rest api", func() {
|
||||
Expect(err).Should(Succeed())
|
||||
var req = apisv1.CreateApplicationRequest{
|
||||
Name: appName,
|
||||
Namespace: appProject,
|
||||
Project: appProject,
|
||||
Description: "this is a test app",
|
||||
Icon: "",
|
||||
Labels: map[string]string{"test": "true"},
|
||||
@@ -99,7 +100,6 @@ var _ = Describe("Test application rest api", func() {
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(cmp.Diff(appBase.Name, req.Name)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Description, req.Description)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Namespace, req.Namespace)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(appBase.Labels["test"], req.Labels["test"])).Should(BeEmpty())
|
||||
})
|
||||
|
||||
@@ -138,8 +138,8 @@ var _ = Describe("Test application rest api", func() {
|
||||
var namespace = "default"
|
||||
// create target
|
||||
var createTarget = apisv1.CreateDeliveryTargetRequest{
|
||||
Name: targetName,
|
||||
Namespace: appProject,
|
||||
Name: targetName,
|
||||
Project: appProject,
|
||||
Cluster: &apisv1.ClusterTarget{
|
||||
ClusterName: "local",
|
||||
Namespace: namespace,
|
||||
@@ -147,7 +147,7 @@ var _ = Describe("Test application rest api", func() {
|
||||
}
|
||||
bodyByte, err := json.Marshal(createTarget)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
res, err := http.Post("http://127.0.0.1:8000/api/v1/deliveryTargets", "application/json", bytes.NewBuffer(bodyByte))
|
||||
res, err := http.Post("http://127.0.0.1:8000/api/v1/targets", "application/json", bytes.NewBuffer(bodyByte))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(res).ShouldNot(BeNil())
|
||||
Expect(cmp.Diff(res.StatusCode, 200)).Should(BeEmpty())
|
||||
@@ -186,7 +186,7 @@ var _ = Describe("Test application rest api", func() {
|
||||
Expect(cmp.Diff(response.Status, model.RevisionStatusRunning)).Should(BeEmpty())
|
||||
|
||||
var oam v1beta1.Application
|
||||
err = k8sClient.Get(context.TODO(), types.NamespacedName{Name: appName + "-" + envName, Namespace: appProject}, &oam)
|
||||
err = k8sClient.Get(context.TODO(), types.NamespacedName{Name: appName + "-" + envName, Namespace: fmt.Sprintf("project-%s", appProject)}, &oam)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(cmp.Diff(len(oam.Spec.Components), 2)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(len(oam.Spec.Policies), 1)).Should(BeEmpty())
|
||||
|
||||
@@ -19,6 +19,7 @@ package e2e_apiserver_test
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@@ -28,38 +29,39 @@ import (
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
var _ = Describe("Test namespace rest api", func() {
|
||||
It("Test create namespace", func() {
|
||||
var _ = Describe("Test project rest api", func() {
|
||||
It("Test create project", func() {
|
||||
defer GinkgoRecover()
|
||||
var req = apisv1.CreateNamespaceRequest{
|
||||
var req = apisv1.CreateProjectRequest{
|
||||
Name: "dev-team",
|
||||
Description: "开发环境租户",
|
||||
Description: "KubeVela Project",
|
||||
}
|
||||
bodyByte, err := json.Marshal(req)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
res, err := http.Post("http://127.0.0.1:8000/api/v1/namespaces", "application/json", bytes.NewBuffer(bodyByte))
|
||||
res, err := http.Post("http://127.0.0.1:8000/api/v1/projects", "application/json", bytes.NewBuffer(bodyByte))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(res).ShouldNot(BeNil())
|
||||
Expect(cmp.Diff(res.StatusCode, 200)).Should(BeEmpty())
|
||||
Expect(res.Body).ShouldNot(BeNil())
|
||||
defer res.Body.Close()
|
||||
var namespaceBase apisv1.NamespaceBase
|
||||
err = json.NewDecoder(res.Body).Decode(&namespaceBase)
|
||||
var projectBase apisv1.ProjectBase
|
||||
err = json.NewDecoder(res.Body).Decode(&projectBase)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(cmp.Diff(namespaceBase.Name, req.Name)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(namespaceBase.Description, req.Description)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(projectBase.Name, req.Name)).Should(BeEmpty())
|
||||
Expect(cmp.Diff(projectBase.Namespace, fmt.Sprintf("project-%s", req.Name))).Should(BeEmpty())
|
||||
Expect(cmp.Diff(projectBase.Description, req.Description)).Should(BeEmpty())
|
||||
})
|
||||
|
||||
It("Test list namespace", func() {
|
||||
It("Test list project", func() {
|
||||
defer GinkgoRecover()
|
||||
res, err := http.Get("http://127.0.0.1:8000/api/v1/namespaces")
|
||||
res, err := http.Get("http://127.0.0.1:8000/api/v1/projects")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(res).ShouldNot(BeNil())
|
||||
Expect(cmp.Diff(res.StatusCode, 200)).Should(BeEmpty())
|
||||
Expect(res.Body).ShouldNot(BeNil())
|
||||
defer res.Body.Close()
|
||||
var namespaces apisv1.ListNamespaceResponse
|
||||
err = json.NewDecoder(res.Body).Decode(&namespaces)
|
||||
var projects apisv1.ListProjectResponse
|
||||
err = json.NewDecoder(res.Body).Decode(&projects)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
@@ -17,7 +17,9 @@ limitations under the License.
|
||||
package e2e_apiserver_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -31,6 +33,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/clients"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
arest "github.com/oam-dev/kubevela/pkg/apiserver/rest"
|
||||
apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
var k8sClient client.Client
|
||||
@@ -72,11 +75,19 @@ var _ = BeforeSuite(func() {
|
||||
By("wait for api server to start")
|
||||
Eventually(
|
||||
func() error {
|
||||
res, err := http.Get("http://127.0.0.1:8000/api/v1/namespaces")
|
||||
res, err := http.Get("http://127.0.0.1:8000/api/v1/projects")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode == http.StatusOK {
|
||||
var req = apisv1.CreateProjectRequest{
|
||||
Name: appProject,
|
||||
Description: "test project",
|
||||
}
|
||||
bodyByte, err := json.Marshal(req)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = http.Post("http://127.0.0.1:8000/api/v1/projects", "application/json", bytes.NewBuffer(bodyByte))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
return nil
|
||||
}
|
||||
return errors.New("rest service not ready")
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
- jsonKey: writeConnectionSecretToRef
|
||||
disable: true
|
||||
- jsonKey: providerRef
|
||||
disable: true
|
||||
- jsonKey: region
|
||||
disable: true
|
||||
- jsonKey: instance_name
|
||||
label: InstanceName
|
||||
sort: 1
|
||||
- jsonKey: database_name
|
||||
label: DatabaseName
|
||||
sort: 2
|
||||
- jsonKey: account_name
|
||||
label: AccountName
|
||||
sort: 3
|
||||
- jsonKey: password
|
||||
sort: 4
|
||||
- jsonKey: allocate_public_connection
|
||||
label: AllocatePublicConnection
|
||||
sort: 5
|
||||
- jsonKey: deleteResource
|
||||
label: DeleteResource
|
||||
sort: 10
|
||||
@@ -0,0 +1,2 @@
|
||||
- jsonKey: objects
|
||||
uiType: K8sObjectsCode
|
||||
168
vela-templates/definitions/uischema/component-task.yaml
Normal file
168
vela-templates/definitions/uischema/component-task.yaml
Normal file
@@ -0,0 +1,168 @@
|
||||
- uiType: ImageInput
|
||||
jsonKey: image
|
||||
label: Image
|
||||
sort: 1
|
||||
- jsonKey: restart
|
||||
sort: 2
|
||||
uiType: Select
|
||||
validate:
|
||||
options:
|
||||
- label: Never
|
||||
value: Never
|
||||
- label: OnFailure
|
||||
value: OnFailure
|
||||
- jsonKey: count
|
||||
sort: 3
|
||||
uiType: Number
|
||||
- jsonKey: memory
|
||||
uiType: MemoryNumber
|
||||
sort: 4
|
||||
label: Memory Request&Limit
|
||||
- uiType: CPUNumber
|
||||
jsonKey: cpu
|
||||
sort: 5
|
||||
label: CPU Request&Limit
|
||||
- description: Specify image pull policy for your service
|
||||
jsonKey: imagePullPolicy
|
||||
label: Image Pull Policy
|
||||
uiType: Select
|
||||
sort: 7
|
||||
validate:
|
||||
options:
|
||||
- label: IfNotPresent
|
||||
value: IfNotPresent
|
||||
- label: Always
|
||||
value: Always
|
||||
- label: Never
|
||||
value: Never
|
||||
- jsonKey: cmd
|
||||
label: CMD
|
||||
sort: 9
|
||||
- jsonKey: env
|
||||
sort: 10
|
||||
label: ENV
|
||||
subParameterGroupOption:
|
||||
- label: Add By Value
|
||||
keys:
|
||||
- name
|
||||
- value
|
||||
- label: Add By Secret
|
||||
keys:
|
||||
- name
|
||||
- valueFrom
|
||||
subParameters:
|
||||
- jsonKey: valueFrom
|
||||
label: Secret Selector
|
||||
uiType: InnerGroup
|
||||
subParameters:
|
||||
- jsonKey: configMapKeyRef
|
||||
disable: true
|
||||
- jsonKey: secretKeyRef
|
||||
uiType: Ignore
|
||||
subParameters:
|
||||
- jsonKey: name
|
||||
label: Secret Name
|
||||
uiType: SecretSelect
|
||||
sort: 1
|
||||
- jsonKey: key
|
||||
label: Secret Key
|
||||
uiType: SecretKeySelect
|
||||
sort: 3
|
||||
uiType: Structs
|
||||
- jsonKey: ports
|
||||
label: Service Ports
|
||||
sort: 11
|
||||
subParameters:
|
||||
- jsonKey: port
|
||||
sort: 1
|
||||
- jsonKey: protocol
|
||||
sort: 2
|
||||
- jsonKey: expose
|
||||
sort: 3
|
||||
- jsonKey: volumeMounts
|
||||
label: Persistent Storage
|
||||
description: "Set the path and type that the service needs to persist."
|
||||
uiType: Group
|
||||
subParameters:
|
||||
- jsonKey: secret
|
||||
disable: true
|
||||
- jsonKey: pvc
|
||||
sort: 1
|
||||
- jsonKey: hostPath
|
||||
sort: 3
|
||||
- jsonKey: emptyDir
|
||||
sort: 5
|
||||
sort: 12
|
||||
|
||||
|
||||
- jsonKey: readinessProbe
|
||||
uiType: Group
|
||||
label: ReadinessProbe
|
||||
subParameters:
|
||||
- jsonKey: hostAliases
|
||||
disable: true
|
||||
- jsonKey: timeoutSeconds
|
||||
sort: 1
|
||||
- jsonKey: failureThreshold
|
||||
sort: 4
|
||||
- jsonKey: initialDelaySeconds
|
||||
sort: 7
|
||||
- jsonKey: periodSeconds
|
||||
sort: 9
|
||||
- jsonKey: successThreshold
|
||||
sort: 11
|
||||
- jsonKey: exec
|
||||
sort: 14
|
||||
- jsonKey: httpGet
|
||||
sort: 19
|
||||
subParameters:
|
||||
- jsonKey: port
|
||||
sort: 1
|
||||
- jsonKey: path
|
||||
sort: 3
|
||||
- jsonKey: httpHeaders
|
||||
sort: 5
|
||||
- jsonKey: tcpSocket
|
||||
sort: 19
|
||||
|
||||
sort: 13
|
||||
|
||||
- jsonKey: livenessProbe
|
||||
uiType: Group
|
||||
label: LivenessProbe
|
||||
subParameters:
|
||||
- jsonKey: hostAliases
|
||||
disable: true
|
||||
- jsonKey: timeoutSeconds
|
||||
sort: 1
|
||||
- jsonKey: failureThreshold
|
||||
sort: 4
|
||||
- jsonKey: initialDelaySeconds
|
||||
sort: 7
|
||||
- jsonKey: periodSeconds
|
||||
sort: 9
|
||||
- jsonKey: successThreshold
|
||||
sort: 11
|
||||
- jsonKey: exec
|
||||
sort: 14
|
||||
- jsonKey: httpGet
|
||||
sort: 19
|
||||
subParameters:
|
||||
- jsonKey: port
|
||||
sort: 1
|
||||
- jsonKey: path
|
||||
sort: 3
|
||||
- jsonKey: httpHeaders
|
||||
sort: 5
|
||||
- jsonKey: tcpSocket
|
||||
sort: 19
|
||||
sort: 15
|
||||
|
||||
- jsonKey: annotations
|
||||
sort: 19
|
||||
|
||||
- jsonKey: lables
|
||||
sort: 21
|
||||
|
||||
- jsonKey: volumes
|
||||
disable: true
|
||||
@@ -1,6 +1,6 @@
|
||||
- uiType: ImageInput
|
||||
jsonKey: image
|
||||
label: Application Image
|
||||
label: Image
|
||||
sort: 1
|
||||
- jsonKey: memory
|
||||
uiType: MemoryNumber
|
||||
@@ -26,11 +26,11 @@
|
||||
- jsonKey: exposeType
|
||||
sort: 8
|
||||
- jsonKey: cmd
|
||||
label: Container Start Command
|
||||
label: CMD
|
||||
sort: 9
|
||||
- jsonKey: env
|
||||
sort: 10
|
||||
label: Environments
|
||||
label: ENV
|
||||
subParameterGroupOption:
|
||||
- label: Add By Value
|
||||
keys:
|
||||
@@ -62,9 +62,28 @@
|
||||
- jsonKey: ports
|
||||
label: Service Ports
|
||||
sort: 11
|
||||
subParameters:
|
||||
- jsonKey: port
|
||||
sort: 1
|
||||
- jsonKey: protocol
|
||||
sort: 2
|
||||
- jsonKey: expose
|
||||
sort: 3
|
||||
- jsonKey: volumeMounts
|
||||
label: Persistent Storage
|
||||
description: "Set the path and type that the service needs to persist."
|
||||
uiType: Group
|
||||
subParameters:
|
||||
- jsonKey: configMap
|
||||
disable: true
|
||||
- jsonKey: secret
|
||||
disable: true
|
||||
- jsonKey: pvc
|
||||
sort: 1
|
||||
- jsonKey: hostPath
|
||||
sort: 3
|
||||
- jsonKey: emptyDir
|
||||
sort: 5
|
||||
sort: 12
|
||||
|
||||
- jsonKey: readinessProbe
|
||||
@@ -73,6 +92,30 @@
|
||||
subParameters:
|
||||
- jsonKey: hostAliases
|
||||
disable: true
|
||||
- jsonKey: timeoutSeconds
|
||||
sort: 1
|
||||
- jsonKey: failureThreshold
|
||||
sort: 4
|
||||
- jsonKey: initialDelaySeconds
|
||||
sort: 7
|
||||
- jsonKey: periodSeconds
|
||||
sort: 9
|
||||
- jsonKey: successThreshold
|
||||
sort: 11
|
||||
- jsonKey: exec
|
||||
sort: 14
|
||||
- jsonKey: httpGet
|
||||
sort: 19
|
||||
subParameters:
|
||||
- jsonKey: port
|
||||
sort: 1
|
||||
- jsonKey: path
|
||||
sort: 3
|
||||
- jsonKey: httpHeaders
|
||||
sort: 5
|
||||
- jsonKey: tcpSocket
|
||||
sort: 19
|
||||
|
||||
sort: 13
|
||||
|
||||
- jsonKey: livenessProbe
|
||||
|
||||
Reference in New Issue
Block a user