mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-19 04:26:39 +00:00
Feat: Initialize api for vela dashboard and CLI (#2339)
* Change the web framework to go-restful. * Some API specifications are defined. * Some sample code is provided.
This commit is contained in:
@@ -58,9 +58,6 @@ vela-cli:
|
||||
kubectl-vela:
|
||||
$(GOBUILD_ENV) go build -o bin/kubectl-vela -a -ldflags $(LDFLAGS) ./cmd/plugin/main.go
|
||||
|
||||
dashboard-build:
|
||||
cd references/dashboard && npm install && cd ..
|
||||
|
||||
doc-gen:
|
||||
rm -r docs/en/cli/*
|
||||
go run hack/docgen/gen.go
|
||||
@@ -98,6 +95,9 @@ compress:
|
||||
run:
|
||||
go run ./cmd/core/main.go --application-revision-limit 5
|
||||
|
||||
run-apiserver:
|
||||
go run ./cmd/apiserver/main.go
|
||||
|
||||
# Run go fmt against code
|
||||
fmt: goimports installcue
|
||||
go fmt ./...
|
||||
@@ -239,7 +239,7 @@ manifests: installcue kustomize
|
||||
./vela-templates/gen_definitions.sh
|
||||
go run ./vela-templates/gen_addons.go
|
||||
|
||||
GOLANGCILINT_VERSION ?= v1.31.0
|
||||
GOLANGCILINT_VERSION ?= v1.38.0
|
||||
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
|
||||
HOSTARCH := $(shell uname -m)
|
||||
ifeq ($(HOSTARCH),x86_64)
|
||||
|
||||
+22
-4
@@ -21,6 +21,8 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest"
|
||||
@@ -29,14 +31,30 @@ import (
|
||||
|
||||
func main() {
|
||||
s := &server{}
|
||||
|
||||
flag.IntVar(&s.restCfg.Port, "port", 8000, "The port number used to serve the http APIs.")
|
||||
flag.StringVar(&s.restCfg.BindAddr, "bind-addr", "0.0.0.0:8000", "The bind address used to serve the http APIs.")
|
||||
flag.StringVar(&s.restCfg.MetricPath, "metrics-path", "/metrics", "The path to expose the metrics.")
|
||||
flag.StringVar(&s.restCfg.Datastore.Type, "datastore-type", "kubeapi", "Metadata storage driver type, support kubeapi and mongodb")
|
||||
flag.StringVar(&s.restCfg.Datastore.Database, "datastore-database", "kubevela", "Metadata storage database name, takes effect when the storage driver is mongodb.")
|
||||
flag.StringVar(&s.restCfg.Datastore.URL, "datastore-url", "", "Metadata storage database url,takes effect when the storage driver is mongodb.")
|
||||
flag.Parse()
|
||||
|
||||
if err := s.run(); err != nil {
|
||||
log.Logger.Errorf("failed to run apiserver: %v", err)
|
||||
srvc := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
if err := s.run(); err != nil {
|
||||
log.Logger.Errorf("failed to run apiserver: %v", err)
|
||||
}
|
||||
close(srvc)
|
||||
}()
|
||||
var term = make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-term:
|
||||
log.Logger.Infof("Received SIGTERM, exiting gracefully...")
|
||||
case <-srvc:
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Logger.Infof("See you next time!")
|
||||
}
|
||||
|
||||
type server struct {
|
||||
|
||||
@@ -15,11 +15,15 @@ require (
|
||||
github.com/crossplane/crossplane-runtime v0.14.1-0.20210722005935-0b469fcc77cd
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/deckarep/golang-set v1.7.1
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.3.0
|
||||
github.com/emicklei/go-restful/v3 v3.0.0-rc2
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/gertd/go-pluralize v0.1.7
|
||||
github.com/getkin/kin-openapi v0.34.0
|
||||
github.com/go-logr/logr v0.4.0
|
||||
github.com/go-openapi/spec v0.19.8
|
||||
github.com/go-playground/validator/v10 v10.9.0
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
@@ -27,7 +31,6 @@ require (
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||
github.com/labstack/echo/v4 v4.5.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.1
|
||||
github.com/oam-dev/cluster-gateway v0.0.0-20210907072424-2f8720b116f8
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
|
||||
@@ -45,6 +48,7 @@ require (
|
||||
github.com/tidwall/gjson v1.6.8
|
||||
github.com/wercker/stern v0.0.0-20190705090245-4fa46dd6987f
|
||||
github.com/wonderflow/cert-manager-api v1.0.3
|
||||
go.mongodb.org/mongo-driver v1.3.2
|
||||
go.uber.org/zap v1.18.1
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
|
||||
@@ -402,6 +402,10 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.3.0 h1:tDgSCzQrkk4N+Isos0zGBYX/GTINjmQuP9BvITbEe38=
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.3.0/go.mod h1:bs67E3SEVgSmB3qDuRLqpS0NcpheqtsCCMhW2/jml1E=
|
||||
github.com/emicklei/go-restful/v3 v3.0.0-rc2 h1:UkWzdUozgtjQzYuqSNQy+PuYxD4/DCzYucakgzWKolU=
|
||||
github.com/emicklei/go-restful/v3 v3.0.0-rc2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/proto v1.6.15 h1:XbpwxmuOPrdES97FrSfpyy67SSCV/wBIKXqgJzh6hNw=
|
||||
github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
@@ -558,6 +562,7 @@ github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/
|
||||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.6/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
|
||||
github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
|
||||
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
|
||||
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
|
||||
@@ -569,11 +574,20 @@ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2K
|
||||
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
|
||||
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
|
||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
@@ -642,8 +656,6 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
@@ -685,6 +697,7 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||
@@ -959,6 +972,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg=
|
||||
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||
@@ -970,8 +984,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5 h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=
|
||||
@@ -988,10 +1003,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
|
||||
github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg=
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible h1:np0woGKwx9LiHAQmwZx79Oc0rHpNw3o+3evou4BEPv4=
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
|
||||
github.com/labstack/echo/v4 v4.5.0 h1:JXk6H5PAw9I3GwizqUHhYyS4f45iyGebR/c1xNCeOCY=
|
||||
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
|
||||
@@ -999,6 +1010,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6Fm
|
||||
github.com/ldez/gomoddirectives v0.2.1/go.mod h1:sGicqkRgBOg//JfpXwkB9Hj0X5RyJ7mlACM5B9f6Me4=
|
||||
github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88=
|
||||
github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@@ -1047,7 +1060,6 @@ github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6I
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
@@ -1161,7 +1173,6 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ=
|
||||
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
|
||||
@@ -1262,6 +1273,7 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rK
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.0.0-20180311214515-816c9085562c/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -1358,8 +1370,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 h1:HXr/qUllAWv9riaI4zh2eXWKmCSDqVS/XH1MRHLKRwk=
|
||||
@@ -1508,12 +1522,8 @@ github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVU
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
@@ -1527,7 +1537,9 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/wonderflow/cert-manager-api v1.0.3 h1:xQQMkJNQ12oYyy00jOQUlSKgdraApaURxv3PHFdVTfA=
|
||||
github.com/wonderflow/cert-manager-api v1.0.3/go.mod h1:1Se7MSg11/eNYlo4fWv6vOM55/jTBMOzg2DN1kVFiSc=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
|
||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -1591,6 +1603,7 @@ go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
|
||||
go.mongodb.org/mongo-driver v1.3.2 h1:IYppNjEV/C+/3VPbhHVxQ4t04eVW0cLp0/pNdW++6Ug=
|
||||
go.mongodb.org/mongo-driver v1.3.2/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
|
||||
go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
@@ -1684,8 +1697,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1925,9 +1939,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
@@ -1950,7 +1966,6 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
||||
@@ -2236,8 +2251,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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 datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Config datastore config
|
||||
type Config struct {
|
||||
Type string
|
||||
URL string
|
||||
Database string
|
||||
}
|
||||
|
||||
// DataStore datastore interface
|
||||
type DataStore interface {
|
||||
Add(ctx context.Context, kind string, entity interface{}) error
|
||||
|
||||
Put(ctx context.Context, kind, name string, entity interface{}) error
|
||||
|
||||
Delete(ctx context.Context, kind, name string) error
|
||||
|
||||
Get(ctx context.Context, kind, name string, decodeTo interface{}) error
|
||||
|
||||
// Find executes a find command and returns an iterator over the matching items.
|
||||
Find(ctx context.Context, kind string) (Iterator, error)
|
||||
|
||||
FindOne(ctx context.Context, kind, name string) (Iterator, error)
|
||||
|
||||
IsExist(ctx context.Context, kind, name string) (bool, error)
|
||||
}
|
||||
|
||||
// Iterator dataset query
|
||||
type Iterator interface {
|
||||
// Next gets the next item for this cursor.
|
||||
Next(ctx context.Context) bool
|
||||
|
||||
// Decode will unmarshal the current item into given entity.
|
||||
Decode(entity interface{}) error
|
||||
|
||||
Close(ctx context.Context) error
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
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 kubeapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
)
|
||||
|
||||
type kubeapi struct {
|
||||
// kubeclient client.Client
|
||||
}
|
||||
|
||||
// New new kubeapi datastore instance
|
||||
func New(ctx context.Context, cfg datastore.Config) (datastore.DataStore, error) {
|
||||
return &kubeapi{}, nil
|
||||
}
|
||||
|
||||
// Add add data model
|
||||
func (m *kubeapi) Add(ctx context.Context, kind string, entity interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get get data model
|
||||
func (m *kubeapi) Get(ctx context.Context, kind, name string, decodeTo interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Put update data model
|
||||
func (m *kubeapi) Put(ctx context.Context, kind, name string, entity interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find find data model
|
||||
func (m *kubeapi) Find(ctx context.Context, kind string) (datastore.Iterator, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// FindOne find one data model
|
||||
func (m *kubeapi) FindOne(ctx context.Context, kind, name string) (datastore.Iterator, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// IsExist determine whether data exists.
|
||||
func (m *kubeapi) IsExist(ctx context.Context, kind, name string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Delete delete data
|
||||
func (m *kubeapi) Delete(ctx context.Context, kind, name string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
// Iterator mongo iterator implementation
|
||||
type Iterator struct {
|
||||
cur *mongo.Cursor
|
||||
}
|
||||
|
||||
// Close iterator close
|
||||
func (i *Iterator) Close(ctx context.Context) error {
|
||||
return i.cur.Close(ctx)
|
||||
}
|
||||
|
||||
// Next read next data
|
||||
func (i *Iterator) Next(ctx context.Context) bool {
|
||||
return i.cur.Next(ctx)
|
||||
}
|
||||
|
||||
// Decode decode data
|
||||
func (i *Iterator) Decode(entity interface{}) error {
|
||||
return i.cur.Decode(entity)
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
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 mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"cuelang.org/go/pkg/strings"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
)
|
||||
|
||||
type mongodb struct {
|
||||
client *mongo.Client
|
||||
database string
|
||||
}
|
||||
|
||||
// New new mongodb datastore instance
|
||||
func New(ctx context.Context, cfg datastore.Config) (datastore.DataStore, error) {
|
||||
if strings.HasPrefix(cfg.URL, "mongodb://") {
|
||||
cfg.URL = fmt.Sprintf("mongodb://%s", cfg.URL)
|
||||
}
|
||||
clientOpts := options.Client().ApplyURI(cfg.URL)
|
||||
client, err := mongo.Connect(ctx, clientOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := &mongodb{
|
||||
client: client,
|
||||
database: cfg.Database,
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Add add data model
|
||||
func (m *mongodb) Add(ctx context.Context, kind string, entity interface{}) error {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
_, err := collection.InsertOne(ctx, entity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get get data model
|
||||
func (m *mongodb) Get(ctx context.Context, kind, name string, decodeTo interface{}) error {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
return collection.FindOne(ctx, makeNameFilter(name)).Decode(decodeTo)
|
||||
}
|
||||
|
||||
// Put update data model
|
||||
func (m *mongodb) Put(ctx context.Context, kind, name string, entity interface{}) error {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
_, err := collection.UpdateOne(ctx, makeNameFilter(name), makeEntityUpdate(entity))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find find data model
|
||||
func (m *mongodb) Find(ctx context.Context, kind string) (datastore.Iterator, error) {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
// bson.D{{}} specifies 'all documents'
|
||||
filter := bson.D{}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Iterator{cur: cur}, nil
|
||||
}
|
||||
|
||||
// FindOne find one data model
|
||||
func (m *mongodb) FindOne(ctx context.Context, kind, name string) (datastore.Iterator, error) {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
filter := bson.M{"name": name}
|
||||
cur, err := collection.Find(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Iterator{cur: cur}, nil
|
||||
}
|
||||
|
||||
// IsExist determine whether data exists.
|
||||
func (m *mongodb) IsExist(ctx context.Context, kind, name string) (bool, error) {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
err := collection.FindOne(ctx, makeNameFilter(name)).Err()
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Delete delete data
|
||||
func (m *mongodb) Delete(ctx context.Context, kind, name string) error {
|
||||
collection := m.client.Database(m.database).Collection(kind)
|
||||
// delete at most one document in which the "name" field is "Bob" or "bob"
|
||||
// specify the SetCollation option to provide a collation that will ignore case for string comparisons
|
||||
opts := options.Delete().SetCollation(&options.Collation{
|
||||
Locale: "en_US",
|
||||
Strength: 1,
|
||||
CaseLevel: false,
|
||||
})
|
||||
_, err := collection.DeleteOne(ctx, makeNameFilter(name), opts)
|
||||
return err
|
||||
}
|
||||
|
||||
func makeNameFilter(name string) bson.D {
|
||||
return bson.D{{Key: "name", Value: name}}
|
||||
}
|
||||
|
||||
func makeEntityUpdate(entity interface{}) bson.M {
|
||||
return bson.M{"$set": entity}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apis
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/model"
|
||||
@@ -5,7 +5,7 @@ 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
|
||||
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,
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apis
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// CreateClusterRequest request parameters to create a cluster
|
||||
type CreateClusterRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Icon string `json:"icon"`
|
||||
KubeConfig string `json:"kubeConfig" validate:"required_without=kubeConfigSecret"`
|
||||
KubeConfigSecret string `json:"kubeConfigSecret,omitempty" validate:"required_without=kubeConfig"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// DetailClusterResponse cluster detail information model
|
||||
type DetailClusterResponse struct {
|
||||
ClusterBase
|
||||
ResourceInfo ClusterResourceInfo `json:"resourceInfo"`
|
||||
// remote manage url, eg. ACK cluster manage url.
|
||||
RemoteManageURL string `json:"remoteManageURL,omitempty"`
|
||||
// Dashboard URL
|
||||
DashboardURL string `json:"dashboardURL,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterResourceInfo resource info of cluster
|
||||
type ClusterResourceInfo struct {
|
||||
WorkerNumber int `json:"workerNumber"`
|
||||
MasterNumber int `json:"masterNumber"`
|
||||
MemoryCapacity int64 `json:"memoryCapacity"`
|
||||
CPUCapacity int64 `json:"cpuCapacity"`
|
||||
GPUCapacity int64 `json:"gpuCapacity,omitempty"`
|
||||
StorageClassList []string `json:"storageClassList,omitempty"`
|
||||
}
|
||||
|
||||
// ListClusterResponse list cluster
|
||||
type ListClusterResponse struct {
|
||||
Clusters []ClusterBase `json:"clusters"`
|
||||
}
|
||||
|
||||
// ClusterBase cluster base model
|
||||
type ClusterBase struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Status string `json:"status"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// ListClusterAddonResponse list all addon of the cluster
|
||||
type ListClusterAddonResponse struct {
|
||||
Addons []ClusterAddonBase `json:"addons"`
|
||||
}
|
||||
|
||||
// ClusterAddonBase cluster addon base model
|
||||
type ClusterAddonBase struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// DeatilClusterAddonResponse detail addon info
|
||||
type DeatilClusterAddonResponse struct {
|
||||
ClusterAddonBase
|
||||
}
|
||||
|
||||
// ListApplicationResponse list applications by query params
|
||||
type ListApplicationResponse struct {
|
||||
Applications []*ApplicationBase `json:"applications"`
|
||||
}
|
||||
|
||||
// ApplicationBase application base model
|
||||
type ApplicationBase struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
Description string `json:"description"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
Icon string `json:"icon"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
ClusterBindList []ClusterBase `json:"clusterList,omitempty"`
|
||||
Status string `json:"status"`
|
||||
GatewayRuleList []GatewayRule `json:"gatewayRule"`
|
||||
}
|
||||
|
||||
// RuleType gateway rule type
|
||||
type RuleType string
|
||||
|
||||
const (
|
||||
// HTTPRule Layer 7 HTTP policy.
|
||||
HTTPRule RuleType = "http"
|
||||
// StreamRule Layer 4 policy, such as TCP and UDP
|
||||
StreamRule RuleType = "stream"
|
||||
)
|
||||
|
||||
// GatewayRule application gateway rule
|
||||
type GatewayRule struct {
|
||||
RuleType RuleType `json:"ruleType"`
|
||||
Address string `json:"address"`
|
||||
Protocol string `json:"protocol"`
|
||||
ComponentName string `json:"componentName"`
|
||||
ComponentPort int32 `json:"componentPort"`
|
||||
}
|
||||
|
||||
// CreateApplicationRequest create application request body
|
||||
type CreateApplicationRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Namespace string `json:"namespace" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
ClusterList []string `json:"clusterList,omitempty"`
|
||||
YamlConfig string `json:"yamlConfig,omitempty"`
|
||||
}
|
||||
|
||||
// DetailApplicationResponse application detail
|
||||
type DetailApplicationResponse struct {
|
||||
ApplicationBase
|
||||
Policies []string `json:"policies"`
|
||||
Status string `json:"status"`
|
||||
ResourceInfo ApplicationResourceInfo `json:"resourceInfo"`
|
||||
WorkflowStatus []WorkflowStepStatus `json:"workflowStatus"`
|
||||
}
|
||||
|
||||
// WorkflowStepStatus workflow step status model
|
||||
type WorkflowStepStatus struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
TakeTime time.Duration `json:"takeTime"`
|
||||
}
|
||||
|
||||
// ApplicationResourceInfo application-level resource consumption statistics
|
||||
type ApplicationResourceInfo struct {
|
||||
ComponentNum int `json:"componentNum"`
|
||||
// Others, such as: Memory、CPU、GPU、Storage
|
||||
}
|
||||
|
||||
// ComponentBase component base model
|
||||
type ComponentBase struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
ComponentType string `json:"componentType"`
|
||||
BindClusters []string `json:"bindClusters"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
DependOn []string `json:"dependOn"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
DeployVersion string `json:"deployVersion"`
|
||||
}
|
||||
|
||||
// ComponentListResponse list component
|
||||
type ComponentListResponse struct {
|
||||
Components []ComponentBase `json:"components"`
|
||||
}
|
||||
|
||||
// CreateComponentRequest create component request model
|
||||
type CreateComponentRequest struct {
|
||||
ApplicationName string `json:"appName" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
ComponentType string `json:"componentType" validate:"required"`
|
||||
BindClusters []string `json:"bindClusters"`
|
||||
Properties string `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
// CreateApplicationTemplateRequest create app template request model
|
||||
type CreateApplicationTemplateRequest struct {
|
||||
TemplateName string `json:"templateName" validate:"required"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ApplicationTemplateBase app template model
|
||||
type ApplicationTemplateBase struct {
|
||||
TemplateName string `json:"templateName"`
|
||||
Versions []*ApplicationTemplateVersion `json:"versions,omitempty"`
|
||||
}
|
||||
|
||||
// ApplicationTemplateVersion template version model
|
||||
type ApplicationTemplateVersion struct {
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
CreateUser string `json:"createUser"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
UpdateTime time.Time `json:"updateTime"`
|
||||
}
|
||||
|
||||
// ListNamespaceResponse namesace list model
|
||||
type ListNamespaceResponse struct {
|
||||
Namespaces []NamesapceBase `json:"namesapces"`
|
||||
}
|
||||
|
||||
// NamesapceBase namespace base model
|
||||
type NamesapceBase struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// CreateNamespaceRequest create namespace request body
|
||||
type CreateNamespaceRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// NamesapceDetailResponse namespace detail response
|
||||
type NamesapceDetailResponse struct {
|
||||
NamesapceBase
|
||||
ClusterBind map[string]string `json:"clusterBind"`
|
||||
}
|
||||
|
||||
// ListComponentDefinitionResponse list component dedinition response model
|
||||
type ListComponentDefinitionResponse struct {
|
||||
ComponentDefinitions []ComponentDefinitionBase `json:"componentDefinitions"`
|
||||
}
|
||||
|
||||
// ComponentDefinitionBase component definition base model
|
||||
type ComponentDefinitionBase struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
RequiredParams []Param `json:"requiredParams"`
|
||||
}
|
||||
|
||||
// Param For rendering forms
|
||||
type Param struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
DefaultValue interface{} `json:"defaultValue"`
|
||||
Type string `json:"type"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
@@ -21,20 +21,28 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore/kubeapi"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore/mongodb"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/services"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/webservice"
|
||||
)
|
||||
|
||||
var _ APIServer = &restServer{}
|
||||
|
||||
// Config config for server
|
||||
type Config struct {
|
||||
Port int
|
||||
// api server bind address
|
||||
BindAddr string
|
||||
// monitor metric path
|
||||
MetricPath string
|
||||
|
||||
// Datastore config
|
||||
Datastore datastore.Config
|
||||
}
|
||||
|
||||
// APIServer interface for call api server
|
||||
@@ -43,45 +51,38 @@ type APIServer interface {
|
||||
}
|
||||
|
||||
type restServer struct {
|
||||
server *echo.Echo
|
||||
k8sClient client.Client
|
||||
cfg Config
|
||||
webContainer *restful.Container
|
||||
cfg Config
|
||||
dataStore datastore.DataStore
|
||||
}
|
||||
|
||||
// New create restserver with config data
|
||||
func New(cfg Config) (APIServer, error) {
|
||||
client, err := common.NewK8sClient()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create client for clusterService failed")
|
||||
func New(cfg Config) (a APIServer, err error) {
|
||||
var ds datastore.DataStore
|
||||
switch cfg.Datastore.Type {
|
||||
case "mongodb":
|
||||
ds, err = mongodb.New(context.Background(), cfg.Datastore)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
case "kubeapi":
|
||||
ds, err = kubeapi.New(context.Background(), cfg.Datastore)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create mongodb datastore instance failure %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("not support datastore type %s", cfg.Datastore.Type)
|
||||
}
|
||||
s := &restServer{
|
||||
server: newEchoInstance(),
|
||||
k8sClient: client,
|
||||
cfg: cfg,
|
||||
webContainer: restful.NewContainer(),
|
||||
cfg: cfg,
|
||||
dataStore: ds,
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func newEchoInstance() *echo.Echo {
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
|
||||
e.Use(middleware.Gzip())
|
||||
e.Use(middleware.Logger())
|
||||
e.Pre(middleware.RemoveTrailingSlash())
|
||||
|
||||
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||
AllowOrigins: []string{"*"},
|
||||
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 86400,
|
||||
}))
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (s *restServer) Run(ctx context.Context) error {
|
||||
webservice.Init(ctx)
|
||||
err := s.registerServices()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -94,28 +95,58 @@ func (s *restServer) registerServices() error {
|
||||
/* ************************************************************** */
|
||||
/* ************* Open API Route Group ***************** */
|
||||
/* ************************************************************** */
|
||||
openapi := s.server.Group("/v1")
|
||||
|
||||
// catalog
|
||||
catalogService := services.NewCatalogService(s.k8sClient)
|
||||
openapi.GET("/catalogs", catalogService.ListCatalogs)
|
||||
openapi.POST("/catalogs", catalogService.AddCatalog)
|
||||
openapi.PUT("/catalogs", catalogService.UpdateCatalog)
|
||||
openapi.GET("/catalogs/:catalogName", catalogService.GetCatalog)
|
||||
openapi.DELETE("/catalogs/:catalogName", catalogService.DelCatalog)
|
||||
// Add container filter to enable CORS
|
||||
cors := restful.CrossOriginResourceSharing{
|
||||
ExposeHeaders: []string{},
|
||||
AllowedHeaders: []string{"Content-Type", "Accept"},
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"},
|
||||
CookiesAllowed: true,
|
||||
Container: s.webContainer}
|
||||
s.webContainer.Filter(cors.Filter)
|
||||
|
||||
// application
|
||||
applicationService := services.NewApplicationService(s.k8sClient)
|
||||
openapi.GET("/namespaces/:namespace/applications/:appname", applicationService.GetApplication)
|
||||
openapi.POST("/namespaces/:namespace/applications/:appname", applicationService.CreateOrUpdateApplication)
|
||||
openapi.DELETE("/namespaces/:namespace/applications/:appname", applicationService.DeleteApplication)
|
||||
// Add container filter to respond to OPTIONS
|
||||
s.webContainer.Filter(s.webContainer.OPTIONSFilter)
|
||||
|
||||
// Regist all custom webservice
|
||||
for _, handler := range webservice.GetRegistedWebService() {
|
||||
s.webContainer.Add(handler.GetWebService())
|
||||
}
|
||||
|
||||
config := restfulspec.Config{
|
||||
WebServices: s.webContainer.RegisteredWebServices(), // you control what services are visible
|
||||
APIPath: "/apidocs.json",
|
||||
PostBuildSwaggerObjectHandler: enrichSwaggerObject}
|
||||
s.webContainer.Add(restfulspec.NewOpenAPIService(config))
|
||||
return nil
|
||||
}
|
||||
|
||||
func enrichSwaggerObject(swo *spec.Swagger) {
|
||||
swo.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubevela api doc",
|
||||
Description: "Kubevela api doc",
|
||||
Contact: &spec.ContactInfo{
|
||||
ContactInfoProps: spec.ContactInfoProps{
|
||||
Name: "kubevela",
|
||||
Email: "feedback@mail.kubevela.io",
|
||||
URL: "https://kubevela.io/",
|
||||
},
|
||||
},
|
||||
License: &spec.License{
|
||||
LicenseProps: spec.LicenseProps{
|
||||
Name: "Apache License 2.0",
|
||||
URL: "https://github.com/oam-dev/kubevela/blob/master/LICENSE",
|
||||
},
|
||||
},
|
||||
Version: "v1beta1",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *restServer) startHTTP(ctx context.Context) error {
|
||||
// Start HTTP apiserver
|
||||
log.Logger.Infof("HTTP APIs are being served on port: %d, ctx: %s", s.cfg.Port, ctx)
|
||||
addr := fmt.Sprintf(":%d", s.cfg.Port)
|
||||
return s.server.Start(addr)
|
||||
log.Logger.Infof("HTTP APIs are being served on: %s, ctx: %s", s.cfg.BindAddr, ctx)
|
||||
server := &http.Server{Addr: s.cfg.BindAddr, Handler: s.webContainer}
|
||||
return server.ListenAndServe()
|
||||
}
|
||||
|
||||
@@ -1,122 +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 services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/apis"
|
||||
)
|
||||
|
||||
// ApplicationService serves as Application Open API for request
|
||||
type ApplicationService struct {
|
||||
k8sClient client.Client
|
||||
}
|
||||
|
||||
// NewApplicationService create an application service
|
||||
func NewApplicationService(kc client.Client) *ApplicationService {
|
||||
return &ApplicationService{
|
||||
k8sClient: kc,
|
||||
}
|
||||
}
|
||||
|
||||
// GetApplication will get application status
|
||||
// GET /namespaces/<namespace>/applications/<appname>
|
||||
func (s *ApplicationService) GetApplication(c echo.Context) error {
|
||||
namespace := c.Param("namespace")
|
||||
appName := c.Param("appname")
|
||||
|
||||
ctx := context.TODO()
|
||||
var existApp v1beta1.Application
|
||||
err := s.k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appName}, &existApp)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "application does not exist: " + err.Error()})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "fail to get application: " + err.Error()})
|
||||
}
|
||||
|
||||
var appResp = &apis.ApplicationResponse{
|
||||
APIVersion: existApp.APIVersion,
|
||||
Kind: existApp.Kind,
|
||||
Spec: existApp.Spec,
|
||||
Status: existApp.Status,
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, appResp)
|
||||
}
|
||||
|
||||
// CreateOrUpdateApplication will create or update application
|
||||
// POST /namespaces/<namespace>/applications/<appname>
|
||||
func (s *ApplicationService) CreateOrUpdateApplication(c echo.Context) error {
|
||||
namespace := c.Param("namespace")
|
||||
name := c.Param("appname")
|
||||
appReq := new(apis.ApplicationRequest)
|
||||
if err := c.Bind(appReq); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request body: " + err.Error()})
|
||||
}
|
||||
ctx := context.TODO()
|
||||
var app, existApp v1beta1.Application
|
||||
app.Namespace = namespace
|
||||
app.Name = name
|
||||
app.Spec.Components = appReq.Components
|
||||
app.Spec.Policies = appReq.Policies
|
||||
app.Spec.Workflow = appReq.Workflow
|
||||
err := s.k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &existApp)
|
||||
if err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "fail to get application: " + err.Error()})
|
||||
}
|
||||
err = s.k8sClient.Create(ctx, &app)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "fail to create application: " + err.Error()})
|
||||
}
|
||||
return c.JSON(http.StatusOK, struct{}{})
|
||||
}
|
||||
existApp.Spec = app.Spec
|
||||
err = s.k8sClient.Update(ctx, &existApp)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "fail to update application: " + err.Error()})
|
||||
}
|
||||
return c.JSON(http.StatusOK, struct{}{})
|
||||
}
|
||||
|
||||
// DeleteApplication will delete application
|
||||
// delete /v1/namespaces/<namespace>/applications/<appname>
|
||||
func (s *ApplicationService) DeleteApplication(c echo.Context) error {
|
||||
namespace := c.Param("namespace")
|
||||
appName := c.Param("appname")
|
||||
|
||||
ctx := context.TODO()
|
||||
var existApp v1beta1.Application
|
||||
existApp.Namespace = namespace
|
||||
existApp.Name = appName
|
||||
err := s.k8sClient.Delete(ctx, &existApp)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "application does not exist: " + err.Error()})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "fail to delete application: " + err.Error()})
|
||||
}
|
||||
return c.JSON(http.StatusOK, struct{}{})
|
||||
}
|
||||
@@ -1,272 +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 services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/apis"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
)
|
||||
|
||||
func TestApplicationCreateOrUpdate(t *testing.T) {
|
||||
cw := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
|
||||
appSvc := NewApplicationService(cw)
|
||||
|
||||
appComp1 := common2.ApplicationComponent{
|
||||
Name: "mycomp",
|
||||
Type: "webservice",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"image":"nginx:v1"}`)},
|
||||
}
|
||||
appComp2 := common2.ApplicationComponent{
|
||||
Name: "mycomp2",
|
||||
Type: "webservice",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"image":"nginx:v2"}`)},
|
||||
}
|
||||
tests := map[string]struct {
|
||||
appReq *apis.ApplicationRequest
|
||||
rawReq []byte
|
||||
name string
|
||||
namespace string
|
||||
expHttpCode int
|
||||
expErr string
|
||||
expApp *v1beta1.Application
|
||||
}{
|
||||
"normal create with only component": {
|
||||
appReq: &apis.ApplicationRequest{
|
||||
Components: []common2.ApplicationComponent{appComp1},
|
||||
},
|
||||
expHttpCode: 200,
|
||||
name: "myapp",
|
||||
namespace: "mynamespace",
|
||||
expApp: &v1beta1.Application{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []common2.ApplicationComponent{appComp1},
|
||||
},
|
||||
},
|
||||
},
|
||||
"create with bind error": {
|
||||
rawReq: []byte("XXXX"),
|
||||
expHttpCode: 400,
|
||||
name: "myapp",
|
||||
namespace: "mynamespace",
|
||||
expErr: "invalid request body: code=400",
|
||||
},
|
||||
"normal update with component and trait": {
|
||||
appReq: &apis.ApplicationRequest{
|
||||
Components: []common2.ApplicationComponent{appComp1, appComp2},
|
||||
},
|
||||
expHttpCode: 200,
|
||||
name: "myapp",
|
||||
namespace: "mynamespace",
|
||||
expApp: &v1beta1.Application{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []common2.ApplicationComponent{appComp1, appComp2},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for casename, c := range tests {
|
||||
var err error
|
||||
if c.appReq != nil {
|
||||
c.rawReq, err = json.Marshal(c.appReq)
|
||||
assert.NoError(t, err, casename)
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(c.rawReq))
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec := httptest.NewRecorder()
|
||||
echoCtx := echo.New().NewContext(req, rec)
|
||||
echoCtx.SetParamNames("namespace", "appname")
|
||||
echoCtx.SetParamValues(c.namespace, c.name)
|
||||
|
||||
err = appSvc.CreateOrUpdateApplication(echoCtx)
|
||||
assert.NoError(t, err, casename)
|
||||
|
||||
// check response
|
||||
assert.Equal(t, c.expHttpCode, rec.Code, casename)
|
||||
if c.expErr != "" { // compare return error with map type
|
||||
gotResp := map[string]string{}
|
||||
err = json.Unmarshal(rec.Body.Bytes(), &gotResp)
|
||||
assert.NoError(t, err, casename)
|
||||
assert.True(t, strings.Contains(gotResp["error"], c.expErr), casename)
|
||||
} else { // check app spec in fake cluster
|
||||
var appObj v1beta1.Application
|
||||
err = cw.Get(context.TODO(), client.ObjectKey{Namespace: c.namespace, Name: c.name}, &appObj)
|
||||
assert.NoError(t, err, casename)
|
||||
assert.Equal(t, c.expApp.Spec, appObj.Spec, casename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplicationGet(t *testing.T) {
|
||||
cw := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
|
||||
appSvc := NewApplicationService(cw)
|
||||
|
||||
tests := map[string]struct {
|
||||
rawReq []byte
|
||||
name string
|
||||
namespace string
|
||||
expHttpCode int
|
||||
expErr string
|
||||
expApp *v1beta1.Application
|
||||
}{
|
||||
"normal get method for application": {
|
||||
expHttpCode: 200,
|
||||
name: "commonName",
|
||||
namespace: "commonNamespace",
|
||||
},
|
||||
"get app failed with resource not found": {
|
||||
expHttpCode: 404,
|
||||
name: "notExistName",
|
||||
namespace: "commonNamespace",
|
||||
expErr: "application does not exist",
|
||||
},
|
||||
}
|
||||
// create an application for get
|
||||
createAppForTest(t, appSvc)
|
||||
|
||||
for casename, c := range tests {
|
||||
var err error
|
||||
req := httptest.NewRequest(http.MethodGet, "/", bytes.NewBuffer(c.rawReq))
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec := httptest.NewRecorder()
|
||||
echoCtx := echo.New().NewContext(req, rec)
|
||||
echoCtx.SetParamNames("namespace", "appname")
|
||||
echoCtx.SetParamValues(c.namespace, c.name)
|
||||
|
||||
err = appSvc.GetApplication(echoCtx)
|
||||
assert.NoError(t, err, casename)
|
||||
|
||||
// check response
|
||||
assert.Equal(t, c.expHttpCode, rec.Code, casename)
|
||||
if c.expErr != "" { // compare return error with map type
|
||||
gotResp := map[string]string{}
|
||||
err = json.Unmarshal(rec.Body.Bytes(), &gotResp)
|
||||
assert.NoError(t, err, casename)
|
||||
assert.True(t, strings.Contains(gotResp["error"], c.expErr), casename)
|
||||
} else { // check app spec in fake cluster
|
||||
var gotResp apis.ApplicationResponse
|
||||
err = json.Unmarshal(rec.Body.Bytes(), &gotResp)
|
||||
assert.NoError(t, err, casename)
|
||||
|
||||
var appObj v1beta1.Application
|
||||
err = cw.Get(context.TODO(), client.ObjectKey{Namespace: c.namespace, Name: c.name}, &appObj)
|
||||
assert.NoError(t, err, casename)
|
||||
assert.Equal(t, gotResp.APIVersion, appObj.APIVersion, casename)
|
||||
assert.Equal(t, gotResp.Kind, appObj.Kind, casename)
|
||||
assert.Equal(t, gotResp.Spec, appObj.Spec, casename)
|
||||
assert.Equal(t, gotResp.Status, appObj.Status, casename)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplicationDelete(t *testing.T) {
|
||||
cw := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
|
||||
appSvc := NewApplicationService(cw)
|
||||
|
||||
tests := map[string]struct {
|
||||
rawReq []byte
|
||||
name string
|
||||
namespace string
|
||||
expHttpCode int
|
||||
expErr string
|
||||
}{
|
||||
"normal delete method for application": {
|
||||
expHttpCode: 200,
|
||||
name: "commonName",
|
||||
namespace: "commonNamespace",
|
||||
},
|
||||
"delete app failed with resource not found": {
|
||||
expHttpCode: 404,
|
||||
name: "notExistName",
|
||||
namespace: "commonNamespace",
|
||||
expErr: "application does not exist",
|
||||
},
|
||||
}
|
||||
for casename, c := range tests {
|
||||
// create common app
|
||||
createAppForTest(t, appSvc)
|
||||
var err error
|
||||
req := httptest.NewRequest(http.MethodDelete, "/", bytes.NewBuffer(c.rawReq))
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec := httptest.NewRecorder()
|
||||
echoCtx := echo.New().NewContext(req, rec)
|
||||
echoCtx.SetParamNames("namespace", "appname")
|
||||
echoCtx.SetParamValues(c.namespace, c.name)
|
||||
|
||||
err = appSvc.DeleteApplication(echoCtx)
|
||||
assert.NoError(t, err, casename)
|
||||
|
||||
// check response
|
||||
assert.Equal(t, c.expHttpCode, rec.Code, casename)
|
||||
if c.expErr != "" {
|
||||
gotResp := map[string]string{}
|
||||
err = json.Unmarshal(rec.Body.Bytes(), &gotResp)
|
||||
assert.NoError(t, err, casename)
|
||||
assert.True(t, strings.Contains(gotResp["error"], c.expErr), casename)
|
||||
} else {
|
||||
// checkout app status in fake cluster
|
||||
var appObj v1beta1.Application
|
||||
err = cw.Get(context.TODO(), client.ObjectKey{Namespace: c.namespace, Name: c.name}, &appObj)
|
||||
assert.Equal(t, apierrors.IsNotFound(err), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createAppForTest(t *testing.T, appSvc *ApplicationService) {
|
||||
appComp := common2.ApplicationComponent{
|
||||
Name: "mycomp",
|
||||
Type: "webservice",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"image":"nginx:v1"}`)},
|
||||
}
|
||||
|
||||
var appReq = &apis.ApplicationRequest{
|
||||
Components: []common2.ApplicationComponent{appComp},
|
||||
}
|
||||
|
||||
var rawReq []byte
|
||||
var err error
|
||||
if appReq != nil {
|
||||
rawReq, err = json.Marshal(appReq)
|
||||
assert.NoError(t, err, "marshal request for create app")
|
||||
}
|
||||
req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(rawReq))
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec := httptest.NewRecorder()
|
||||
echoCtx := echo.New().NewContext(req, rec)
|
||||
echoCtx.SetParamNames("namespace", "appname")
|
||||
echoCtx.SetParamValues("commonNamespace", "commonName")
|
||||
|
||||
err = appSvc.CreateOrUpdateApplication(echoCtx)
|
||||
assert.NoError(t, err, "craete application in service")
|
||||
}
|
||||
@@ -1,223 +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 services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
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/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/model"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/apis"
|
||||
)
|
||||
|
||||
// CatalogService catalog service
|
||||
type CatalogService struct {
|
||||
k8sClient client.Client
|
||||
}
|
||||
|
||||
// NewCatalogService new catalog service
|
||||
func NewCatalogService(kc client.Client) *CatalogService {
|
||||
|
||||
return &CatalogService{
|
||||
k8sClient: kc,
|
||||
}
|
||||
}
|
||||
|
||||
// ListCatalogs list method for catalog configmap
|
||||
func (s *CatalogService) ListCatalogs(c echo.Context) error {
|
||||
var cmList corev1.ConfigMapList
|
||||
labels := &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"catalog": "configdata",
|
||||
},
|
||||
}
|
||||
selector, err := metav1.LabelSelectorAsSelector(labels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.k8sClient.List(context.Background(), &cmList, &client.ListOptions{
|
||||
LabelSelector: selector,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var catalogList = make([]*model.Catalog, 0, len(cmList.Items))
|
||||
for i, c := range cmList.Items {
|
||||
UpdateInt, err := strconv.ParseInt(cmList.Items[i].Data["UpdatedAt"], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
catalog := model.Catalog{
|
||||
Name: c.Name,
|
||||
UpdatedAt: UpdateInt,
|
||||
Desc: cmList.Items[i].Data["Desc"],
|
||||
Type: cmList.Items[i].Data["Type"],
|
||||
URL: cmList.Items[i].Data["Url"],
|
||||
Token: cmList.Items[i].Data["Token"],
|
||||
}
|
||||
catalogList = append(catalogList, &catalog)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, apis.CatalogListResponse{Catalogs: catalogList})
|
||||
}
|
||||
|
||||
// GetCatalog get method for catalog configmap
|
||||
func (s *CatalogService) GetCatalog(c echo.Context) error {
|
||||
catalogName := c.Param("catalogName")
|
||||
|
||||
var cm corev1.ConfigMap
|
||||
err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: catalogName}, &cm)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get configMap for %s failed %s", catalogName, err.Error()))
|
||||
}
|
||||
UpdatedInt, err := strconv.ParseInt(cm.Data["UpdatedAt"], 10, 64)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, fmt.Errorf("unable to resolve update parameter in %s: %w ", catalogName, err))
|
||||
}
|
||||
var catalog = model.Catalog{
|
||||
Name: catalogName,
|
||||
Desc: cm.Data["Desc"],
|
||||
UpdatedAt: UpdatedInt,
|
||||
Type: cm.Data["Type"],
|
||||
URL: cm.Data["Url"],
|
||||
Token: cm.Data["Token"],
|
||||
}
|
||||
return c.JSON(http.StatusOK, apis.CatalogResponse{Catalog: &catalog})
|
||||
}
|
||||
|
||||
// AddCatalog add method for catalog configmap
|
||||
func (s *CatalogService) AddCatalog(c echo.Context) error {
|
||||
catalogReq := new(apis.CatalogRequest)
|
||||
if err := c.Bind(catalogReq); err != nil {
|
||||
return err
|
||||
}
|
||||
exist, err := s.checkCatalogExist(catalogReq.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
return c.JSON(http.StatusInternalServerError, fmt.Sprintf("catalog %s exist", catalogReq.Name))
|
||||
}
|
||||
|
||||
var cm *corev1.ConfigMap
|
||||
configdata := map[string]string{
|
||||
"Name": catalogReq.Name,
|
||||
"Desc": catalogReq.Desc,
|
||||
"UpdatedAt": fmt.Sprintf("%d", time.Now().UnixNano()),
|
||||
}
|
||||
|
||||
label := map[string]string{
|
||||
"catalog": "configdata",
|
||||
}
|
||||
cm = toConfigMap(catalogReq.Name, types.DefaultKubeVelaNS, label, configdata)
|
||||
err = s.k8sClient.Create(context.Background(), cm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create configmap for %s : %w ", catalogReq.Name, err)
|
||||
}
|
||||
catalog := convertToCatalog(catalogReq)
|
||||
return c.JSON(http.StatusCreated, apis.CatalogResponse{Catalog: &catalog})
|
||||
}
|
||||
|
||||
// UpdateCatalog update method for catalog configmap
|
||||
func (s *CatalogService) UpdateCatalog(c echo.Context) error {
|
||||
catalogReq := new(apis.CatalogRequest)
|
||||
if err := c.Bind(catalogReq); err != nil {
|
||||
return err
|
||||
}
|
||||
catalog := convertToCatalog(catalogReq)
|
||||
configdata := map[string]string{
|
||||
"Name": catalogReq.Name,
|
||||
"Desc": catalogReq.Desc,
|
||||
"UpdatedAt": time.Now().String(),
|
||||
}
|
||||
|
||||
label := map[string]string{
|
||||
"catalog": "configdata",
|
||||
}
|
||||
cm := toConfigMap(catalogReq.Name, types.DefaultKubeVelaNS, label, configdata)
|
||||
err := s.k8sClient.Update(context.Background(), cm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to update configmap for %s : %w ", catalogReq.Name, err)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, apis.CatalogResponse{Catalog: &catalog})
|
||||
}
|
||||
|
||||
// DelCatalog delete method for catalog configmap
|
||||
func (s *CatalogService) DelCatalog(c echo.Context) error {
|
||||
catalogName := c.Param("catalogName")
|
||||
|
||||
var cm corev1.ConfigMap
|
||||
cm.SetName(catalogName)
|
||||
cm.SetNamespace(types.DefaultKubeVelaNS)
|
||||
if err := s.k8sClient.Delete(context.Background(), &cm); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, false)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, true)
|
||||
}
|
||||
|
||||
// checkCatalogExist check whether catalog exist with name
|
||||
func (s *CatalogService) checkCatalogExist(catalogName string) (bool, error) {
|
||||
var cm corev1.ConfigMap
|
||||
err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: catalogName}, &cm)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) { // not found
|
||||
return false, nil
|
||||
}
|
||||
// other error
|
||||
return false, err
|
||||
}
|
||||
// found
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// convertToCatalog get catalog model from request
|
||||
func convertToCatalog(catalogReq *apis.CatalogRequest) model.Catalog {
|
||||
return model.Catalog{
|
||||
Name: catalogReq.Name,
|
||||
Desc: catalogReq.Desc,
|
||||
UpdatedAt: time.Now().Unix(),
|
||||
Type: catalogReq.Type,
|
||||
URL: catalogReq.URL,
|
||||
Token: catalogReq.Token,
|
||||
}
|
||||
}
|
||||
|
||||
func toConfigMap(name, namespace string, label map[string]string, configData map[string]string) *corev1.ConfigMap {
|
||||
var cm = corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
},
|
||||
}
|
||||
cm.SetName(name)
|
||||
cm.SetNamespace(namespace)
|
||||
cm.SetLabels(label)
|
||||
cm.Data = configData
|
||||
return &cm
|
||||
}
|
||||
@@ -1,80 +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 services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/apis"
|
||||
)
|
||||
|
||||
var _ = Describe("Test Catalog Service", func() {
|
||||
|
||||
var catalogService *CatalogService
|
||||
|
||||
BeforeEach(func() {
|
||||
catalogService = NewCatalogService(k8sClient)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
})
|
||||
|
||||
It("should add catalog successfully", func() {
|
||||
e := echo.New()
|
||||
cr := &apis.CatalogRequest{
|
||||
Name: "test",
|
||||
}
|
||||
b, err := json.Marshal(cr)
|
||||
Expect(err).To(BeNil())
|
||||
req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(b))
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
|
||||
Expect(catalogService.AddCatalog(c)).To(BeNil())
|
||||
checkCatalogResponse(rec, cr, http.StatusCreated)
|
||||
|
||||
req = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
|
||||
rec = httptest.NewRecorder()
|
||||
c = e.NewContext(req, rec)
|
||||
c.SetPath("/v1/catalogs/:catalogName")
|
||||
c.SetParamNames("catalogName")
|
||||
c.SetParamValues(cr.Name)
|
||||
|
||||
Expect(catalogService.GetCatalog(c)).To(BeNil())
|
||||
checkCatalogResponse(rec, cr, http.StatusOK)
|
||||
})
|
||||
})
|
||||
|
||||
func checkCatalogResponse(rec *httptest.ResponseRecorder, cr *apis.CatalogRequest, httpcode int) {
|
||||
Expect(rec.Code).To(Equal(httpcode))
|
||||
|
||||
get := &apis.CatalogResponse{}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), get)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
Expect(get.Catalog.Name).To(Equal(cr.Name))
|
||||
Expect(get.Catalog.UpdatedAt).NotTo(BeZero())
|
||||
}
|
||||
@@ -1,110 +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 services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
oamcorealpha "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
oamstandard "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
|
||||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
|
||||
var cfg *rest.Config
|
||||
var k8sClient client.Client
|
||||
var testEnv *envtest.Environment
|
||||
var testScheme = runtime.NewScheme()
|
||||
|
||||
func TestAPIs(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "APIServer Suite")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter)))
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
By("bootstrapping test environment")
|
||||
var yamlPath string
|
||||
if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set {
|
||||
yamlPath = "../../../../../test/compatibility-test/testdata"
|
||||
} else {
|
||||
yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds")
|
||||
}
|
||||
logf.Log.Info("start application suit test", "yaml_path", yamlPath)
|
||||
testEnv = &envtest.Environment{
|
||||
ControlPlaneStartTimeout: time.Minute,
|
||||
ControlPlaneStopTimeout: time.Minute,
|
||||
UseExistingCluster: pointer.BoolPtr(false),
|
||||
CRDDirectoryPaths: []string{yamlPath, "./testdata/crds/terraform.core.oam.dev_configurations.yaml"},
|
||||
}
|
||||
|
||||
var err error
|
||||
cfg, err = testEnv.Start()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(cfg).ToNot(BeNil())
|
||||
|
||||
err = oamcorealpha.SchemeBuilder.AddToScheme(testScheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = oamstandard.SchemeBuilder.AddToScheme(testScheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = oamcore.SchemeBuilder.AddToScheme(testScheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = clientgoscheme.AddToScheme(testScheme)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
crdv1.AddToScheme(testScheme)
|
||||
|
||||
// +kubebuilder:scaffold:scheme
|
||||
k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(k8sClient).ToNot(BeNil())
|
||||
|
||||
definitonNs := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}}
|
||||
Expect(k8sClient.Create(context.Background(), definitonNs.DeepCopy())).Should(BeNil())
|
||||
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
err := testEnv.Stop()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/datastore"
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
// ClusterUsecase cluster manage
|
||||
type ClusterUsecase interface {
|
||||
CreateKubeCluster(context.Context, apis.CreateClusterRequest) (*apis.ClusterBase, error)
|
||||
}
|
||||
|
||||
type clusterUsecaseImpl struct {
|
||||
ds datastore.DataStore
|
||||
}
|
||||
|
||||
// NewClusterUsecase new cluster usecase
|
||||
func NewClusterUsecase(ds datastore.DataStore) ClusterUsecase {
|
||||
return &clusterUsecaseImpl{ds: ds}
|
||||
}
|
||||
|
||||
func (c *clusterUsecaseImpl) CreateKubeCluster(context.Context, apis.CreateClusterRequest) (*apis.ClusterBase, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-playground/validator/v10"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
)
|
||||
|
||||
// Bcode business error code
|
||||
type Bcode struct {
|
||||
HTTPCode int32 `json:"-"`
|
||||
BusinessCode int32
|
||||
Message string
|
||||
}
|
||||
|
||||
func (b *Bcode) Error() string {
|
||||
return fmt.Sprintf("HTTPCode:%d BusinessCode:%d Message:%s", b.HTTPCode, b.BusinessCode, b.Message)
|
||||
}
|
||||
|
||||
// ReturnError Unified handling of all types of errors, generating a standard return structure.
|
||||
func ReturnError(req *restful.Request, res *restful.Response, err error) {
|
||||
var bcode *Bcode
|
||||
if errors.As(err, &bcode) {
|
||||
if err := res.WriteEntity(err); err != nil {
|
||||
log.Logger.Error("write entity failure %s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
var restfulerr *restful.ServiceError
|
||||
if errors.As(err, restfulerr) {
|
||||
if err := res.WriteEntity(Bcode{HTTPCode: int32(restfulerr.Code), BusinessCode: int32(restfulerr.Code), Message: restfulerr.Message}); err != nil {
|
||||
log.Logger.Error("write entity failure %s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
var validErr *validator.ValidationErrors
|
||||
if errors.As(err, validErr) {
|
||||
if err := res.WriteEntity(Bcode{HTTPCode: 400, BusinessCode: 400, Message: err.Error()}); err != nil {
|
||||
log.Logger.Error("write entity failure %s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
log.Logger.Errorf("Business exceptions, message %s, path:%s method:%s", err.Error(), req.Request.URL, req.Request.Method)
|
||||
if err := res.WriteEntity(Bcode{HTTPCode: 500, BusinessCode: 500, Message: err.Error()}); err != nil {
|
||||
log.Logger.Error("write entity failure %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
type applicationWebService struct {
|
||||
}
|
||||
|
||||
func (c *applicationWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/applications").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for application manage")
|
||||
|
||||
tags := []string{"application"}
|
||||
|
||||
ws.Route(ws.GET("/").To(noop).
|
||||
Doc("list all applications").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
|
||||
Param(ws.QueryParameter("namespace", "Namespace-based search").DataType("string")).
|
||||
Param(ws.QueryParameter("cluster", "Cluster-based search").DataType("string")).
|
||||
Writes(apis.ListApplicationResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/").To(noop).
|
||||
Doc("create one application").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Reads(apis.CreateApplicationRequest{}).
|
||||
Writes(apis.ApplicationBase{}))
|
||||
|
||||
ws.Route(ws.DELETE("/{name}").To(noop).
|
||||
Doc("delete one application").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Writes(apis.ApplicationBase{}))
|
||||
|
||||
ws.Route(ws.GET("/{name}").To(noop).
|
||||
Doc("detail one application").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Writes(apis.DetailApplicationResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/{name}/template").To(noop).
|
||||
Doc("create one application template").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Reads(apis.CreateApplicationTemplateRequest{}).
|
||||
Writes(apis.ApplicationTemplateBase{}))
|
||||
|
||||
ws.Route(ws.POST("/{name}/deploy").To(noop).
|
||||
Doc("deploy or update the application").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Writes(apis.ApplicationBase{}))
|
||||
|
||||
ws.Route(ws.GET("/{name}/components").To(noop).
|
||||
Doc("gets the component topology of the application").
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Writes(apis.ComponentListResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/{name}/components").To(noop).
|
||||
Doc("create component for application").
|
||||
Param(ws.PathParameter("name", "identifier of the application").DataType("string")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Reads(apis.CreateComponentRequest{}).
|
||||
Writes(apis.ComponentBase{}))
|
||||
return ws
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
type catalogWebService struct {
|
||||
}
|
||||
|
||||
func (c *catalogWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path("/v1/catalogs").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for cluster manage")
|
||||
|
||||
tags := []string{"cluster"}
|
||||
|
||||
ws.Route(ws.GET("/").To(noop).
|
||||
Doc("list all clusters").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
|
||||
Writes(apis.ListClusterResponse{}).Do(returns200, returns500))
|
||||
|
||||
return ws
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode"
|
||||
)
|
||||
|
||||
type clusterWebService struct {
|
||||
clusterUsecase usecase.ClusterUsecase
|
||||
}
|
||||
|
||||
func (c *clusterWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/clusters").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for cluster manage")
|
||||
|
||||
tags := []string{"cluster"}
|
||||
|
||||
ws.Route(ws.GET("/").To(noop).
|
||||
Doc("list all clusters").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.QueryParameter("query", "Fuzzy search based on name or description").DataType("string")).
|
||||
Writes(apis.ListClusterResponse{}).Do(returns200, returns500))
|
||||
|
||||
ws.Route(ws.POST("/").To(c.createKubeCluster).
|
||||
Doc("create cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Reads(&apis.CreateClusterRequest{}).
|
||||
Writes(apis.ClusterBase{}))
|
||||
|
||||
ws.Route(ws.GET("/{clusterName}").To(noop).
|
||||
Doc("detail cluster info").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")).
|
||||
Writes(apis.DetailClusterResponse{}))
|
||||
|
||||
// Do not implement this dimension for now.
|
||||
// ws.Route(ws.GET("/{clusterName}/addons").To(noop).
|
||||
// Doc("list cluster addons info").
|
||||
// Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
// Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")).
|
||||
// Writes(apis.ListClusterAddonResponse{}))
|
||||
|
||||
// ws.Route(ws.POST("/{clusterName}/addons").To(noop).
|
||||
// Doc("add addon for the cluster").
|
||||
// Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
// Param(ws.PathParameter("clusterName", "identifier of the cluster").DataType("string")).
|
||||
// Writes(apis.DeatilClusterAddonResponse{}).Returns(200, "", apis.DeatilClusterAddonResponse{}))
|
||||
return ws
|
||||
}
|
||||
|
||||
func (c *clusterWebService) createKubeCluster(req *restful.Request, res *restful.Response) {
|
||||
// Verify the validity of parameters
|
||||
var createReq apis.CreateClusterRequest
|
||||
if err := req.ReadEntity(&createReq); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
if err := validate.Struct(&createReq); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
// Call the usecase layer code
|
||||
clusterBase, err := c.clusterUsecase.CreateKubeCluster(req.Request.Context(), createReq)
|
||||
if err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Write back response data
|
||||
if err := res.WriteEntity(clusterBase); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
type componentDefinitionWebservice struct {
|
||||
}
|
||||
|
||||
func (c *componentDefinitionWebservice) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/componentdefinitions").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for componentdefinition manage")
|
||||
|
||||
tags := []string{"componentdefinition"}
|
||||
|
||||
ws.Route(ws.GET("/").To(noop).
|
||||
Doc("list all componentdefinition").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.QueryParameter("appName", "if specified, query the componentdefinition supported by the cluster where the application resides.").DataType("string")).
|
||||
Param(ws.QueryParameter("clusterName", "if specified, query the componentdefinition supported by the cluster.").DataType("string")).
|
||||
Writes(apis.ListComponentDefinitionResponse{}))
|
||||
return ws
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
type namespaceWebService struct {
|
||||
}
|
||||
|
||||
func (c *namespaceWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(versionPrefix+"/namespaces").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for namespace manage")
|
||||
|
||||
tags := []string{"namespace"}
|
||||
|
||||
ws.Route(ws.GET("/").To(noop).
|
||||
Doc("list all namespaces").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Writes(apis.ListNamespaceResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/").To(noop).
|
||||
Doc("create namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Reads(apis.CreateNamespaceRequest{}).
|
||||
Writes(apis.NamesapceDetailResponse{}))
|
||||
|
||||
ws.Route(ws.GET("/{namespace}").To(noop).
|
||||
Doc("get one namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Writes(apis.NamesapceDetailResponse{}))
|
||||
|
||||
// Compatible with historical apis
|
||||
ws.Route(ws.GET("/{namespace}/applications/:appname").To(noop).
|
||||
Doc("get the specified oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")).
|
||||
Writes(apis.ApplicationResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/{namespace}/applications/:appname").To(noop).
|
||||
Doc("create or update oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")).
|
||||
Reads(apis.ApplicationRequest{}))
|
||||
|
||||
ws.Route(ws.DELETE("/{namespace}/applications/:appname").To(noop).
|
||||
Doc("create or update oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")))
|
||||
return ws
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1"
|
||||
)
|
||||
|
||||
type oamApplicationWebService struct {
|
||||
}
|
||||
|
||||
func (c *oamApplicationWebService) GetWebService() *restful.WebService {
|
||||
ws := new(restful.WebService)
|
||||
ws.Path("/v1").
|
||||
Consumes(restful.MIME_XML, restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON, restful.MIME_XML).
|
||||
Doc("api for oam application manage")
|
||||
|
||||
tags := []string{"oam"}
|
||||
|
||||
ws.Route(ws.GET("/{namespace}/applications/:appname").To(noop).
|
||||
Doc("get the specified oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")).
|
||||
Writes(apis.ApplicationResponse{}))
|
||||
|
||||
ws.Route(ws.POST("/{namespace}/applications/{appname}").To(noop).
|
||||
Doc("create or update oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")).
|
||||
Reads(apis.ApplicationRequest{}))
|
||||
|
||||
ws.Route(ws.DELETE("/{namespace}/applications/:appname").To(noop).
|
||||
Doc("create or update oam application in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Param(ws.PathParameter("namespace", "identifier of the namespace").DataType("string")).
|
||||
Param(ws.PathParameter("appname", "identifier of the oam application").DataType("string")))
|
||||
return ws
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
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 webservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// versionPrefix API version prefix.
|
||||
var versionPrefix = "/api/v1"
|
||||
|
||||
var validate = validator.New()
|
||||
|
||||
// WebService webservice interface
|
||||
type WebService interface {
|
||||
GetWebService() *restful.WebService
|
||||
}
|
||||
|
||||
var registedWebService []WebService
|
||||
|
||||
// RegistWebService regist webservice
|
||||
func RegistWebService(ws WebService) {
|
||||
registedWebService = append(registedWebService, ws)
|
||||
}
|
||||
|
||||
// GetRegistedWebService return registedWebService
|
||||
func GetRegistedWebService() []WebService {
|
||||
return registedWebService
|
||||
}
|
||||
|
||||
func noop(req *restful.Request, resp *restful.Response) {}
|
||||
|
||||
func returns200(b *restful.RouteBuilder) {
|
||||
b.Returns(http.StatusOK, "OK", map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
func returns500(b *restful.RouteBuilder) {
|
||||
b.Returns(http.StatusInternalServerError, "Bummer, something went wrong", nil)
|
||||
}
|
||||
|
||||
// Init init all webservice, pass in the required parameter object.
|
||||
func Init(ctx context.Context) {
|
||||
RegistWebService(&clusterWebService{})
|
||||
RegistWebService(&applicationWebService{})
|
||||
RegistWebService(&namespaceWebService{})
|
||||
RegistWebService(&componentDefinitionWebservice{})
|
||||
RegistWebService(&catalogWebService{})
|
||||
RegistWebService(&oamApplicationWebService{})
|
||||
}
|
||||
Reference in New Issue
Block a user