diff --git a/Makefile b/Makefile index 3951f30de..0fbd0229c 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,7 @@ cross-build: go get github.com/mitchellh/gox@v0.4.0 $(GOBUILD_ENV) $(GOX) -ldflags $(LDFLAGS) -parallel=2 -output="_bin/vela/{{.OS}}-{{.Arch}}/vela" -osarch='$(TARGETS)' ./references/cmd/cli $(GOBUILD_ENV) $(GOX) -ldflags $(LDFLAGS) -parallel=2 -output="_bin/kubectl-vela/{{.OS}}-{{.Arch}}/kubectl-vela" -osarch='$(TARGETS)' ./cmd/plugin + $(GOBUILD_ENV) $(GOX) -ldflags $(LDFLAGS) -parallel=2 -output="_bin/apiserver/{{.OS}}-{{.Arch}}/apiserver" -osarch="$(TARGETS)" ./cmd/apiserver compress: ( \ @@ -104,8 +105,13 @@ compress: $(DIST_DIRS) cp ../../README.md {} \; && \ $(DIST_DIRS) tar -zcf kubectl-vela-{}.tar.gz {} \; && \ $(DIST_DIRS) zip -r kubectl-vela-{}.zip {} \; && \ + cd ../apiserver && \ + $(DIST_DIRS) cp ../../LICENSE {} \; && \ + $(DIST_DIRS) cp ../../README.md {} \; && \ + $(DIST_DIRS) tar -zcf apiserver-{}.tar.gz {} \; && \ + $(DIST_DIRS) zip -r apiserver-{}.zip {} \; && \ cd .. && \ - sha256sum vela/vela-* kubectl-vela/kubectl-vela-* > sha256sums.txt \ + sha256sum vela/vela-* kubectl-vela/kubectl-vela-* apiserver/apiserver-* > sha256sums.txt \ ) # Run against the configured Kubernetes cluster in ~/.kube/config @@ -212,9 +218,10 @@ kind-load: core-test: fmt vet manifests go test ./pkg/... -coverprofile cover.out -# Build vela core manager binary +# Build vela core manager and apiserver binary manager: fmt vet lint manifests $(GOBUILD_ENV) go build -o bin/manager -a -ldflags $(LDFLAGS) ./cmd/core/main.go + $(GOBUILD_ENV) go build -o bin/apiserver -a -ldflags $(LDFLAGS) ./cmd/apiserver/main.go # Run against the configured Kubernetes cluster in ~/.kube/config core-run: fmt vet manifests @@ -331,3 +338,6 @@ check-license-header: check-install-def: ./hack/utils/installdefinition.sh + +proto-gen: + ./hack/apiserver/gen_proto.sh diff --git a/cmd/apiserver/main.go b/cmd/apiserver/main.go new file mode 100644 index 000000000..0361f6db3 --- /dev/null +++ b/cmd/apiserver/main.go @@ -0,0 +1,37 @@ +/* +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 main + +import ( + "log" + + "github.com/oam-dev/kubevela/pkg/apiserver/commands" + "github.com/oam-dev/kubevela/pkg/apiserver/commands/server" +) + +func main() { + app := commands.NewCLI( + "velacp", + "KubeVela control plane", + ) + app.AddCommands( + server.NewServerCommand(), + ) + if err := app.Run(); err != nil { + log.Fatal(err) + } +} diff --git a/go.mod b/go.mod index ded505e6e..0af818d84 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/imdario/mergo v0.3.12 github.com/klauspost/compress v1.10.5 // indirect github.com/kyokomi/emoji v2.2.4+incompatible + github.com/labstack/echo/v4 v4.5.0 github.com/mailru/easyjson v0.7.6 // indirect github.com/mholt/archiver/v3 v3.3.0 github.com/mitchellh/hashstructure/v2 v2.0.1 @@ -61,6 +62,7 @@ require ( go.uber.org/zap v1.18.1 golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d + google.golang.org/protobuf v1.26.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools v2.2.0+incompatible @@ -77,7 +79,7 @@ require ( k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 k8s.io/kubectl v0.21.0 k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471 - open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa + open-cluster-management.io/api v0.0.0-20210804091127-340467ff6239 rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/controller-runtime v0.9.5 sigs.k8s.io/controller-tools v0.2.4 diff --git a/go.sum b/go.sum index 9d6589d38..cd0ff6ee9 100644 --- a/go.sum +++ b/go.sum @@ -575,6 +575,8 @@ 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/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw= @@ -853,6 +855,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 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= @@ -892,8 +898,9 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= @@ -1301,6 +1308,11 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb 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/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +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/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/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= @@ -1416,8 +1428,9 @@ golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= 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/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= @@ -1507,6 +1520,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1608,6 +1623,8 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1635,6 +1652,7 @@ 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= @@ -2016,8 +2034,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= -open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa h1:Jw/Jo3Om1xXgdcn6xDfyREkc48nUcW/DqhMHffLCCww= -open-cluster-management.io/api v0.0.0-20210610125115-f57c747b84aa/go.mod h1:9qiA5h/8kvPQnJEOlAPHVjRO9a1jCmDhGzvgMBvXEaE= +open-cluster-management.io/api v0.0.0-20210804091127-340467ff6239 h1:ToDTkftv88UVZSCqTCzYZTkYoba28z+An08Yrm9aOAA= +open-cluster-management.io/api v0.0.0-20210804091127-340467ff6239/go.mod h1:9qiA5h/8kvPQnJEOlAPHVjRO9a1jCmDhGzvgMBvXEaE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= diff --git a/hack/apiserver/gen_proto.sh b/hack/apiserver/gen_proto.sh new file mode 100755 index 000000000..c5f84305c --- /dev/null +++ b/hack/apiserver/gen_proto.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +PROTOCMD="protoc -I . \ + --go_out=. --go_opt=paths=source_relative \ + " + +for entry in "pkg/apiserver/proto/model"/* +do + if [ "${entry##*.}" = "proto" ]; then + eval $PROTOCMD "${entry}" + fi +done diff --git a/pkg/apiserver/commands/cli.go b/pkg/apiserver/commands/cli.go new file mode 100644 index 000000000..b63345688 --- /dev/null +++ b/pkg/apiserver/commands/cli.go @@ -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 commands + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/oam-dev/kubevela/pkg/apiserver/version" +) + +// CLI for apiserver +type CLI struct { + rootCmd *cobra.Command +} + +// NewCLI create new CLI for apiserver +func NewCLI(name, desc string) *CLI { + a := &CLI{ + rootCmd: &cobra.Command{ + Use: name, + Short: desc, + SilenceErrors: true, + }, + } + versionCmd := &cobra.Command{ + Use: "version", + Short: "Print the information of current binary.", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version.Get()) + }, + } + a.rootCmd.AddCommand(versionCmd) + a.setGlobalFlags() + return a +} + +func (c *CLI) setGlobalFlags() { + // set global flags here +} + +// AddCommands apiserver add command function +func (c *CLI) AddCommands(cmds ...*cobra.Command) { + for _, cmd := range cmds { + c.rootCmd.AddCommand(cmd) + } +} + +// Run apiserver run function +func (c *CLI) Run() error { + return c.rootCmd.Execute() +} diff --git a/pkg/apiserver/commands/server/server.go b/pkg/apiserver/commands/server/server.go new file mode 100644 index 000000000..122ed7ece --- /dev/null +++ b/pkg/apiserver/commands/server/server.go @@ -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 server + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/oam-dev/kubevela/pkg/apiserver/rest" +) + +type server struct { + restCfg rest.Config +} + +// NewServerCommand create server command +func NewServerCommand() *cobra.Command { + s := &server{} + + cmd := &cobra.Command{ + Use: "apiserver", + Short: "Start running apiserver.", + RunE: func(cmd *cobra.Command, args []string) error { + return s.run() + }, + } + + // rest + cmd.Flags().IntVar(&s.restCfg.Port, "port", 8000, "The port number used to serve the http APIs.") + + return cmd +} + +func (s *server) run() error { + ctx := context.Background() + + server, err := rest.New(s.restCfg) + if err != nil { + return fmt.Errorf("create apiserver failed : %w ", err) + } + return server.Run(ctx) +} diff --git a/pkg/apiserver/common/cue.go b/pkg/apiserver/common/cue.go new file mode 100644 index 000000000..67f8ab78d --- /dev/null +++ b/pkg/apiserver/common/cue.go @@ -0,0 +1,133 @@ +/* +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 common + +import ( + "bytes" + "encoding/json" + "fmt" + "regexp" + "strings" + + "cuelang.org/go/cue" + "cuelang.org/go/encoding/openapi" + "github.com/getkin/kin-openapi/openapi3" + + "github.com/oam-dev/kubevela/apis/types" + "github.com/oam-dev/kubevela/pkg/appfile" + "github.com/oam-dev/kubevela/pkg/controller/utils" + oamcue "github.com/oam-dev/kubevela/pkg/cue" +) + +// ErrNoSectionParameterInCue means there is not parameter section in Cue template of a workload +const ErrNoSectionParameterInCue = "capability %s doesn't contain section `parameter`" + +// GenerateCUETemplateProperties get all properties of a capability +func (p *ParseReference) GenerateCUETemplateProperties(capability *types.Capability) (string, error) { + t, err := prepareParameterCue(capability.Name, capability.CueTemplate) + if err != nil { + return "", err + } + + r := cue.Runtime{} + inst, err := r.Compile("", t+oamcue.BaseTemplate) + if err != nil { + return "", err + } + + b, err := openapi.Gen(inst, nil) + if err != nil { + return "", err + } + + var out bytes.Buffer + err = json.Indent(&out, b, "", " ") + if err != nil { + return "", err + } + + schema, err := utils.ConvertOpenAPISchema2SwaggerObject(out.Bytes()) + if err != nil { + return "", err + } + + fixOpenAPISchema("", schema) + + jsonSchema, err := schema.MarshalJSON() + if err != nil { + return "", err + } + + return string(jsonSchema), nil +} + +// Int64Type is int64 type +type Int64Type = int64 + +// StringType is string type +type StringType = string + +// BoolType is bool type +type BoolType = bool + +// prepareParameterCue cuts `parameter` section form definition .cue file +func prepareParameterCue(capabilityName, capabilityTemplate string) (string, error) { + var template string + var withParameterFlag bool + r := regexp.MustCompile("[[:space:]]*parameter:[[:space:]]*{.*") + + for _, text := range strings.Split(capabilityTemplate, "\n") { + if r.MatchString(text) { + // a variable has to be refined as a definition which starts with "#" + text = fmt.Sprintf("parameter: #parameter\n#%s", text) + withParameterFlag = true + } + template += fmt.Sprintf("%s\n", text) + } + + if !withParameterFlag { + return "", fmt.Errorf(ErrNoSectionParameterInCue, capabilityName) + } + return template, nil +} + +// fixOpenAPISchema fixes tainted `description` filed, missing of title `field`. +func fixOpenAPISchema(name string, schema *openapi3.Schema) { + t := schema.Type + switch t { + case "object": + for k, v := range schema.Properties { + s := v.Value + fixOpenAPISchema(k, s) + } + case "array": + fixOpenAPISchema("", schema.Items.Value) + } + if name != "" { + schema.Title = name + } + + description := schema.Description + if strings.Contains(description, appfile.UsageTag) { + description = strings.Split(description, appfile.UsageTag)[1] + } + if strings.Contains(description, appfile.ShortTag) { + description = strings.Split(description, appfile.ShortTag)[0] + description = strings.TrimSpace(description) + } + schema.Description = description +} diff --git a/pkg/apiserver/common/parse.go b/pkg/apiserver/common/parse.go new file mode 100644 index 000000000..d083b82b2 --- /dev/null +++ b/pkg/apiserver/common/parse.go @@ -0,0 +1,74 @@ +/* +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 common + +import ( + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + kruntime "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/apis/types" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" +) + +// ParseReference is used to include the common function `parseParameter` +type ParseReference struct { + Client client.Client +} + +// NewParseReference new parse reference +func NewParseReference(cli client.Client) *ParseReference { + return &ParseReference{Client: cli} +} + +// ParseDefinition parse definition +func (p *ParseReference) ParseDefinition(obj *unstructured.Unstructured, name, ns string) (*model.Definition, error) { + var wd v1beta1.WorkloadDefinition + err := kruntime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &wd) + if err != nil { + return nil, errors.Wrap(err, "fail to convert unstructured data to oam build-in WorkloadDefinition object") + } + + if wd.Spec.Schematic == nil { + return nil, errors.New("fail to get definition schematic") + } + + capability := &types.Capability{ + Name: name, + Namespace: ns, + } + + var jsonSchema string + schematic := wd.Spec.Schematic + if schematic.CUE != nil { + capability.CueTemplate = schematic.CUE.Template + jsonSchema, err = p.GenerateCUETemplateProperties(capability) + if err != nil { + return nil, err + } + } + + return &model.Definition{ + Name: name, + Namespace: ns, + Desc: wd.GetAnnotations()[types.AnnDescription], + Jsonschema: jsonSchema, + }, nil +} diff --git a/pkg/apiserver/common/utils.go b/pkg/apiserver/common/utils.go new file mode 100644 index 000000000..c21a2561e --- /dev/null +++ b/pkg/apiserver/common/utils.go @@ -0,0 +1,27 @@ +/* +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 common + +import "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + +// Reverse reverse properties in list +func Reverse(arr *[]*model.Properties) { + length := len(*arr) + for i := 0; i < length/2; i++ { + (*arr)[i], (*arr)[length-1-i] = (*arr)[length-1-i], (*arr)[i] + } +} diff --git a/pkg/apiserver/log/logger.go b/pkg/apiserver/log/logger.go new file mode 100644 index 000000000..bb028001e --- /dev/null +++ b/pkg/apiserver/log/logger.go @@ -0,0 +1,29 @@ +/* +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 log + +import ( + "go.uber.org/zap" +) + +// Logger Log component +var Logger *zap.SugaredLogger + +func init() { + l, _ := zap.NewProduction() + Logger = l.Sugar() +} diff --git a/pkg/apiserver/proto/model/application.pb.go b/pkg/apiserver/proto/model/application.pb.go new file mode 100644 index 000000000..5a72623d3 --- /dev/null +++ b/pkg/apiserver/proto/model/application.pb.go @@ -0,0 +1,745 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/application.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Application struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Desc string `protobuf:"bytes,3,opt,name=desc,proto3" json:"desc,omitempty"` + // Unix time of the last time when the cluster is updated. + UpdatedAt int64 `protobuf:"varint,4,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + Components []*ComponentType `protobuf:"bytes,5,rep,name=components,proto3" json:"components,omitempty"` + ClusterName string `protobuf:"bytes,6,opt,name=clusterName,proto3" json:"clusterName,omitempty"` + Events []*AppEventType `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` +} + +func (x *Application) Reset() { + *x = Application{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Application) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Application) ProtoMessage() {} + +func (x *Application) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Application.ProtoReflect.Descriptor instead. +func (*Application) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{0} +} + +func (x *Application) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Application) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Application) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Application) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +func (x *Application) GetComponents() []*ComponentType { + if x != nil { + return x.Components + } + return nil +} + +func (x *Application) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +func (x *Application) GetEvents() []*AppEventType { + if x != nil { + return x.Events + } + return nil +} + +type AppYaml struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Yaml string `protobuf:"bytes,1,opt,name=yaml,proto3" json:"yaml,omitempty"` +} + +func (x *AppYaml) Reset() { + *x = AppYaml{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppYaml) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppYaml) ProtoMessage() {} + +func (x *AppYaml) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppYaml.ProtoReflect.Descriptor instead. +func (*AppYaml) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{1} +} + +func (x *AppYaml) GetYaml() string { + if x != nil { + return x.Yaml + } + return "" +} + +type ComponentType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Namespace string `protobuf:"bytes,3,opt,name=namespace,proto3" json:"namespace,omitempty"` + Workload string `protobuf:"bytes,4,opt,name=workload,proto3" json:"workload,omitempty"` + Desc string `protobuf:"bytes,5,opt,name=desc,proto3" json:"desc,omitempty"` + Phase string `protobuf:"bytes,6,opt,name=phase,proto3" json:"phase,omitempty"` + Health bool `protobuf:"varint,7,opt,name=health,proto3" json:"health,omitempty"` + Properties *structpb.Struct `protobuf:"bytes,8,opt,name=properties,proto3" json:"properties,omitempty"` + Traits []*TraitType `protobuf:"bytes,9,rep,name=traits,proto3" json:"traits,omitempty"` +} + +func (x *ComponentType) Reset() { + *x = ComponentType{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComponentType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComponentType) ProtoMessage() {} + +func (x *ComponentType) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComponentType.ProtoReflect.Descriptor instead. +func (*ComponentType) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{2} +} + +func (x *ComponentType) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ComponentType) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *ComponentType) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ComponentType) GetWorkload() string { + if x != nil { + return x.Workload + } + return "" +} + +func (x *ComponentType) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *ComponentType) GetPhase() string { + if x != nil { + return x.Phase + } + return "" +} + +func (x *ComponentType) GetHealth() bool { + if x != nil { + return x.Health + } + return false +} + +func (x *ComponentType) GetProperties() *structpb.Struct { + if x != nil { + return x.Properties + } + return nil +} + +func (x *ComponentType) GetTraits() []*TraitType { + if x != nil { + return x.Traits + } + return nil +} + +type TraitType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` + Properties *structpb.Struct `protobuf:"bytes,3,opt,name=properties,proto3" json:"properties,omitempty"` +} + +func (x *TraitType) Reset() { + *x = TraitType{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TraitType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TraitType) ProtoMessage() {} + +func (x *TraitType) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TraitType.ProtoReflect.Descriptor instead. +func (*TraitType) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{3} +} + +func (x *TraitType) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *TraitType) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *TraitType) GetProperties() *structpb.Struct { + if x != nil { + return x.Properties + } + return nil +} + +type AppEventType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Age string `protobuf:"bytes,3,opt,name=age,proto3" json:"age,omitempty"` + Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *AppEventType) Reset() { + *x = AppEventType{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppEventType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppEventType) ProtoMessage() {} + +func (x *AppEventType) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppEventType.ProtoReflect.Descriptor instead. +func (*AppEventType) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{4} +} + +func (x *AppEventType) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *AppEventType) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *AppEventType) GetAge() string { + if x != nil { + return x.Age + } + return "" +} + +func (x *AppEventType) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type ApplicationListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Applications []*Application `protobuf:"bytes,1,rep,name=applications,proto3" json:"applications,omitempty"` +} + +func (x *ApplicationListResponse) Reset() { + *x = ApplicationListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplicationListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplicationListResponse) ProtoMessage() {} + +func (x *ApplicationListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplicationListResponse.ProtoReflect.Descriptor instead. +func (*ApplicationListResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{5} +} + +func (x *ApplicationListResponse) GetApplications() []*Application { + if x != nil { + return x.Applications + } + return nil +} + +type ApplicationResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Application *Application `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` +} + +func (x *ApplicationResponse) Reset() { + *x = ApplicationResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_application_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplicationResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplicationResponse) ProtoMessage() {} + +func (x *ApplicationResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_application_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplicationResponse.ProtoReflect.Descriptor instead. +func (*ApplicationResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_application_proto_rawDescGZIP(), []int{6} +} + +func (x *ApplicationResponse) GetApplication() *Application { + if x != nil { + return x.Application + } + return nil +} + +var File_pkg_proto_model_application_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_application_proto_rawDesc = []byte{ + 0x0a, 0x21, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x89, 0x02, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x76, 0x65, 0x6c, + 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x70, 0x70, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x1d, 0x0a, + 0x07, 0x41, 0x70, 0x70, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x79, 0x61, 0x6d, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x79, 0x61, 0x6d, 0x6c, 0x22, 0x9f, 0x02, 0x0a, + 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x64, 0x65, 0x73, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x06, 0x74, + 0x72, 0x61, 0x69, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x76, 0x65, + 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x54, 0x72, 0x61, + 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x22, 0x6c, + 0x0a, 0x09, 0x54, 0x72, 0x61, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, + 0x65, 0x73, 0x63, 0x12, 0x37, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x22, 0x66, 0x0a, 0x0c, + 0x41, 0x70, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x5a, 0x0a, 0x17, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3f, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x22, 0x54, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76, + 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x61, 0x6d, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x76, 0x65, 0x6c, + 0x61, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_proto_model_application_proto_rawDescOnce sync.Once + file_pkg_proto_model_application_proto_rawDescData = file_pkg_proto_model_application_proto_rawDesc +) + +func file_pkg_proto_model_application_proto_rawDescGZIP() []byte { + file_pkg_proto_model_application_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_application_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_application_proto_rawDescData) + }) + return file_pkg_proto_model_application_proto_rawDescData +} + +var file_pkg_proto_model_application_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_pkg_proto_model_application_proto_goTypes = []interface{}{ + (*Application)(nil), // 0: vela.api.model.Application + (*AppYaml)(nil), // 1: vela.api.model.AppYaml + (*ComponentType)(nil), // 2: vela.api.model.ComponentType + (*TraitType)(nil), // 3: vela.api.model.TraitType + (*AppEventType)(nil), // 4: vela.api.model.AppEventType + (*ApplicationListResponse)(nil), // 5: vela.api.model.ApplicationListResponse + (*ApplicationResponse)(nil), // 6: vela.api.model.ApplicationResponse + (*structpb.Struct)(nil), // 7: google.protobuf.Struct +} +var file_pkg_proto_model_application_proto_depIdxs = []int32{ + 2, // 0: vela.api.model.Application.components:type_name -> vela.api.model.ComponentType + 4, // 1: vela.api.model.Application.events:type_name -> vela.api.model.AppEventType + 7, // 2: vela.api.model.ComponentType.properties:type_name -> google.protobuf.Struct + 3, // 3: vela.api.model.ComponentType.traits:type_name -> vela.api.model.TraitType + 7, // 4: vela.api.model.TraitType.properties:type_name -> google.protobuf.Struct + 0, // 5: vela.api.model.ApplicationListResponse.applications:type_name -> vela.api.model.Application + 0, // 6: vela.api.model.ApplicationResponse.application:type_name -> vela.api.model.Application + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_application_proto_init() } +func file_pkg_proto_model_application_proto_init() { + if File_pkg_proto_model_application_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_application_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Application); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppYaml); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComponentType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TraitType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppEventType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplicationListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_application_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplicationResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_application_proto_rawDesc, + NumEnums: 0, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_application_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_application_proto_depIdxs, + MessageInfos: file_pkg_proto_model_application_proto_msgTypes, + }.Build() + File_pkg_proto_model_application_proto = out.File + file_pkg_proto_model_application_proto_rawDesc = nil + file_pkg_proto_model_application_proto_goTypes = nil + file_pkg_proto_model_application_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/application.proto b/pkg/apiserver/proto/model/application.proto new file mode 100644 index 000000000..846cd0ad7 --- /dev/null +++ b/pkg/apiserver/proto/model/application.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package vela.api.model; + +import "google/protobuf/struct.proto"; + + +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Application { + + string name = 1; + + string namespace = 2; + + string desc = 3; + + // Unix time of the last time when the cluster is updated. + int64 updated_at = 4; + + repeated ComponentType components = 5; + + string clusterName = 6; + + repeated AppEventType events = 7; +} + +message AppYaml { + string yaml = 1; +} + +message ComponentType { + string name = 1; + string type = 2; + string namespace = 3; + string workload = 4; + string desc = 5; + string phase = 6; + bool health = 7; + google.protobuf.Struct properties = 8; + repeated TraitType traits = 9; +} + +message TraitType { + string type = 1; + string desc = 2; + google.protobuf.Struct properties = 3; +} + +message AppEventType { + string type = 1; + string reason = 2; + string age = 3; + string message = 4; +} + +message ApplicationListResponse { + repeated Application applications = 1; +} + +message ApplicationResponse { + Application application = 1; +} \ No newline at end of file diff --git a/pkg/apiserver/proto/model/capability.pb.go b/pkg/apiserver/proto/model/capability.pb.go new file mode 100644 index 000000000..740f5058d --- /dev/null +++ b/pkg/apiserver/proto/model/capability.pb.go @@ -0,0 +1,348 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/capability.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Capability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` + // Unix time of the last time when the capability is updated. + UpdatedAt int64 `protobuf:"varint,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + // Catalog name. + CatalogName string `protobuf:"bytes,4,opt,name=catalog_name,json=catalogName,proto3" json:"catalog_name,omitempty"` + // Type of the Capability, such as "componentDefinition" or "trait" + Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"` + // JSON schema of the Capability. + JsonSchema string `protobuf:"bytes,6,opt,name=json_schema,json=jsonSchema,proto3" json:"json_schema,omitempty"` +} + +func (x *Capability) Reset() { + *x = Capability{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_capability_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Capability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Capability) ProtoMessage() {} + +func (x *Capability) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_capability_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Capability.ProtoReflect.Descriptor instead. +func (*Capability) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_capability_proto_rawDescGZIP(), []int{0} +} + +func (x *Capability) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Capability) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Capability) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +func (x *Capability) GetCatalogName() string { + if x != nil { + return x.CatalogName + } + return "" +} + +func (x *Capability) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Capability) GetJsonSchema() string { + if x != nil { + return x.JsonSchema + } + return "" +} + +type CapabilityListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Capabilities []*Capability `protobuf:"bytes,1,rep,name=capabilities,proto3" json:"capabilities,omitempty"` +} + +func (x *CapabilityListResponse) Reset() { + *x = CapabilityListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_capability_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CapabilityListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CapabilityListResponse) ProtoMessage() {} + +func (x *CapabilityListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_capability_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CapabilityListResponse.ProtoReflect.Descriptor instead. +func (*CapabilityListResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_capability_proto_rawDescGZIP(), []int{1} +} + +func (x *CapabilityListResponse) GetCapabilities() []*Capability { + if x != nil { + return x.Capabilities + } + return nil +} + +type CapabilityResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Capability *Capability `protobuf:"bytes,1,opt,name=capability,proto3" json:"capability,omitempty"` +} + +func (x *CapabilityResponse) Reset() { + *x = CapabilityResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_capability_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CapabilityResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CapabilityResponse) ProtoMessage() {} + +func (x *CapabilityResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_capability_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CapabilityResponse.ProtoReflect.Descriptor instead. +func (*CapabilityResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_capability_proto_rawDescGZIP(), []int{2} +} + +func (x *CapabilityResponse) GetCapability() *Capability { + if x != nil { + return x.Capability + } + return nil +} + +var File_pkg_proto_model_capability_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_capability_proto_rawDesc = []byte{ + 0x0a, 0x20, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x61, 0x74, 0x61, + 0x6c, 0x6f, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x22, 0x58, 0x0a, 0x16, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x61, + 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x63, 0x61, + 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x50, 0x0a, 0x12, 0x43, 0x61, + 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3a, 0x0a, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x52, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x2b, 0x5a, 0x29, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x61, 0x6d, 0x2d, 0x64, + 0x65, 0x76, 0x2f, 0x76, 0x65, 0x6c, 0x61, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_pkg_proto_model_capability_proto_rawDescOnce sync.Once + file_pkg_proto_model_capability_proto_rawDescData = file_pkg_proto_model_capability_proto_rawDesc +) + +func file_pkg_proto_model_capability_proto_rawDescGZIP() []byte { + file_pkg_proto_model_capability_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_capability_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_capability_proto_rawDescData) + }) + return file_pkg_proto_model_capability_proto_rawDescData +} + +var file_pkg_proto_model_capability_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pkg_proto_model_capability_proto_goTypes = []interface{}{ + (*Capability)(nil), // 0: vela.api.model.Capability + (*CapabilityListResponse)(nil), // 1: vela.api.model.CapabilityListResponse + (*CapabilityResponse)(nil), // 2: vela.api.model.CapabilityResponse +} +var file_pkg_proto_model_capability_proto_depIdxs = []int32{ + 0, // 0: vela.api.model.CapabilityListResponse.capabilities:type_name -> vela.api.model.Capability + 0, // 1: vela.api.model.CapabilityResponse.capability:type_name -> vela.api.model.Capability + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_capability_proto_init() } +func file_pkg_proto_model_capability_proto_init() { + if File_pkg_proto_model_capability_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_capability_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Capability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_capability_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CapabilityListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_capability_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CapabilityResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_capability_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_capability_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_capability_proto_depIdxs, + MessageInfos: file_pkg_proto_model_capability_proto_msgTypes, + }.Build() + File_pkg_proto_model_capability_proto = out.File + file_pkg_proto_model_capability_proto_rawDesc = nil + file_pkg_proto_model_capability_proto_goTypes = nil + file_pkg_proto_model_capability_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/capability.proto b/pkg/apiserver/proto/model/capability.proto new file mode 100644 index 000000000..9d9857ef0 --- /dev/null +++ b/pkg/apiserver/proto/model/capability.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package vela.api.model; +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Capability { + + string name = 1; + + string desc = 2; + + // Unix time of the last time when the capability is updated. + int64 updated_at = 3; + + // Catalog name. + string catalog_name = 4; + + // Type of the Capability, such as "componentDefinition" or "trait" + string type = 5; + + // JSON schema of the Capability. + string json_schema = 6; + +} + +message CapabilityListResponse { + repeated Capability capabilities = 1; +} + +message CapabilityResponse { + Capability capability = 1; +} \ No newline at end of file diff --git a/pkg/apiserver/proto/model/catalog.pb.go b/pkg/apiserver/proto/model/catalog.pb.go new file mode 100644 index 000000000..9c362fa0e --- /dev/null +++ b/pkg/apiserver/proto/model/catalog.pb.go @@ -0,0 +1,344 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/catalog.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Catalog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` + // Unix time of the last time when the catalog is updated. + UpdatedAt int64 `protobuf:"varint,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + // Type of the Catalog, such as "github" for a github repo. + Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` + // URL of the Catalog. + Url string `protobuf:"bytes,5,opt,name=url,proto3" json:"url,omitempty"` + // Auth token used to sync Catalog. + Token string `protobuf:"bytes,6,opt,name=token,proto3" json:"token,omitempty"` +} + +func (x *Catalog) Reset() { + *x = Catalog{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Catalog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Catalog) ProtoMessage() {} + +func (x *Catalog) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Catalog.ProtoReflect.Descriptor instead. +func (*Catalog) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_catalog_proto_rawDescGZIP(), []int{0} +} + +func (x *Catalog) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Catalog) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Catalog) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +func (x *Catalog) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Catalog) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *Catalog) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +type CatalogListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Catalogs []*Catalog `protobuf:"bytes,1,rep,name=catalogs,proto3" json:"catalogs,omitempty"` +} + +func (x *CatalogListResponse) Reset() { + *x = CatalogListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CatalogListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CatalogListResponse) ProtoMessage() {} + +func (x *CatalogListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CatalogListResponse.ProtoReflect.Descriptor instead. +func (*CatalogListResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_catalog_proto_rawDescGZIP(), []int{1} +} + +func (x *CatalogListResponse) GetCatalogs() []*Catalog { + if x != nil { + return x.Catalogs + } + return nil +} + +type CatalogResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Catalog *Catalog `protobuf:"bytes,1,opt,name=catalog,proto3" json:"catalog,omitempty"` +} + +func (x *CatalogResponse) Reset() { + *x = CatalogResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CatalogResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CatalogResponse) ProtoMessage() {} + +func (x *CatalogResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_catalog_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CatalogResponse.ProtoReflect.Descriptor instead. +func (*CatalogResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_catalog_proto_rawDescGZIP(), []int{2} +} + +func (x *CatalogResponse) GetCatalog() *Catalog { + if x != nil { + return x.Catalog + } + return nil +} + +var File_pkg_proto_model_catalog_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_catalog_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, + 0x8c, 0x01, 0x0a, 0x07, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, + 0x65, 0x73, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x4a, + 0x0a, 0x13, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x52, 0x08, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0x44, 0x0a, 0x0f, 0x43, 0x61, + 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, + 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, + 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, + 0x61, 0x6d, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x76, 0x65, 0x6c, 0x61, 0x63, 0x70, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_proto_model_catalog_proto_rawDescOnce sync.Once + file_pkg_proto_model_catalog_proto_rawDescData = file_pkg_proto_model_catalog_proto_rawDesc +) + +func file_pkg_proto_model_catalog_proto_rawDescGZIP() []byte { + file_pkg_proto_model_catalog_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_catalog_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_catalog_proto_rawDescData) + }) + return file_pkg_proto_model_catalog_proto_rawDescData +} + +var file_pkg_proto_model_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pkg_proto_model_catalog_proto_goTypes = []interface{}{ + (*Catalog)(nil), // 0: vela.api.model.Catalog + (*CatalogListResponse)(nil), // 1: vela.api.model.CatalogListResponse + (*CatalogResponse)(nil), // 2: vela.api.model.CatalogResponse +} +var file_pkg_proto_model_catalog_proto_depIdxs = []int32{ + 0, // 0: vela.api.model.CatalogListResponse.catalogs:type_name -> vela.api.model.Catalog + 0, // 1: vela.api.model.CatalogResponse.catalog:type_name -> vela.api.model.Catalog + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_catalog_proto_init() } +func file_pkg_proto_model_catalog_proto_init() { + if File_pkg_proto_model_catalog_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_catalog_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Catalog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_catalog_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CatalogListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_catalog_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CatalogResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_catalog_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_catalog_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_catalog_proto_depIdxs, + MessageInfos: file_pkg_proto_model_catalog_proto_msgTypes, + }.Build() + File_pkg_proto_model_catalog_proto = out.File + file_pkg_proto_model_catalog_proto_rawDesc = nil + file_pkg_proto_model_catalog_proto_goTypes = nil + file_pkg_proto_model_catalog_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/catalog.proto b/pkg/apiserver/proto/model/catalog.proto new file mode 100644 index 000000000..e4adb4c44 --- /dev/null +++ b/pkg/apiserver/proto/model/catalog.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package vela.api.model; +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Catalog { + + string name = 1; + + string desc = 2; + + // Unix time of the last time when the catalog is updated. + int64 updated_at = 3; + + // Type of the Catalog, such as "github" for a github repo. + string type = 4; + + // URL of the Catalog. + string url = 5; + + // Auth token used to sync Catalog. + string token = 6; +} + +message CatalogListResponse { + repeated Catalog catalogs = 1; +} + +message CatalogResponse { + Catalog catalog = 1; +} \ No newline at end of file diff --git a/pkg/apiserver/proto/model/cluster.pb.go b/pkg/apiserver/proto/model/cluster.pb.go new file mode 100644 index 000000000..52c70574e --- /dev/null +++ b/pkg/apiserver/proto/model/cluster.pb.go @@ -0,0 +1,323 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/cluster.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Cluster struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` + // Unix time of the last time when the cluster is updated. + UpdatedAt int64 `protobuf:"varint,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + Kubeconfig string `protobuf:"bytes,4,opt,name=kubeconfig,proto3" json:"kubeconfig,omitempty"` +} + +func (x *Cluster) Reset() { + *x = Cluster{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Cluster) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Cluster) ProtoMessage() {} + +func (x *Cluster) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Cluster.ProtoReflect.Descriptor instead. +func (*Cluster) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_cluster_proto_rawDescGZIP(), []int{0} +} + +func (x *Cluster) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Cluster) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Cluster) GetUpdatedAt() int64 { + if x != nil { + return x.UpdatedAt + } + return 0 +} + +func (x *Cluster) GetKubeconfig() string { + if x != nil { + return x.Kubeconfig + } + return "" +} + +type ClusterListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Clusters []*Cluster `protobuf:"bytes,1,rep,name=clusters,proto3" json:"clusters,omitempty"` +} + +func (x *ClusterListResponse) Reset() { + *x = ClusterListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterListResponse) ProtoMessage() {} + +func (x *ClusterListResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterListResponse.ProtoReflect.Descriptor instead. +func (*ClusterListResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_cluster_proto_rawDescGZIP(), []int{1} +} + +func (x *ClusterListResponse) GetClusters() []*Cluster { + if x != nil { + return x.Clusters + } + return nil +} + +type ClusterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cluster *Cluster `protobuf:"bytes,1,opt,name=cluster,proto3" json:"cluster,omitempty"` +} + +func (x *ClusterResponse) Reset() { + *x = ClusterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterResponse) ProtoMessage() {} + +func (x *ClusterResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_cluster_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterResponse.ProtoReflect.Descriptor instead. +func (*ClusterResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_cluster_proto_rawDescGZIP(), []int{2} +} + +func (x *ClusterResponse) GetCluster() *Cluster { + if x != nil { + return x.Cluster + } + return nil +} + +var File_pkg_proto_model_cluster_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_cluster_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, + 0x70, 0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, + 0x73, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x22, 0x4a, 0x0a, 0x13, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x6c, + 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x44, 0x0a, + 0x0f, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x31, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6f, 0x61, 0x6d, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x76, 0x65, 0x6c, 0x61, 0x63, 0x70, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_proto_model_cluster_proto_rawDescOnce sync.Once + file_pkg_proto_model_cluster_proto_rawDescData = file_pkg_proto_model_cluster_proto_rawDesc +) + +func file_pkg_proto_model_cluster_proto_rawDescGZIP() []byte { + file_pkg_proto_model_cluster_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_cluster_proto_rawDescData) + }) + return file_pkg_proto_model_cluster_proto_rawDescData +} + +var file_pkg_proto_model_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pkg_proto_model_cluster_proto_goTypes = []interface{}{ + (*Cluster)(nil), // 0: vela.api.model.Cluster + (*ClusterListResponse)(nil), // 1: vela.api.model.ClusterListResponse + (*ClusterResponse)(nil), // 2: vela.api.model.ClusterResponse +} +var file_pkg_proto_model_cluster_proto_depIdxs = []int32{ + 0, // 0: vela.api.model.ClusterListResponse.clusters:type_name -> vela.api.model.Cluster + 0, // 1: vela.api.model.ClusterResponse.cluster:type_name -> vela.api.model.Cluster + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_cluster_proto_init() } +func file_pkg_proto_model_cluster_proto_init() { + if File_pkg_proto_model_cluster_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_cluster_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Cluster); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_cluster_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClusterListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_cluster_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClusterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_cluster_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_cluster_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_cluster_proto_depIdxs, + MessageInfos: file_pkg_proto_model_cluster_proto_msgTypes, + }.Build() + File_pkg_proto_model_cluster_proto = out.File + file_pkg_proto_model_cluster_proto_rawDesc = nil + file_pkg_proto_model_cluster_proto_goTypes = nil + file_pkg_proto_model_cluster_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/cluster.proto b/pkg/apiserver/proto/model/cluster.proto new file mode 100644 index 000000000..29d6bdbce --- /dev/null +++ b/pkg/apiserver/proto/model/cluster.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package vela.api.model; +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Cluster { + + string name = 1; + + string desc = 2; + + // Unix time of the last time when the cluster is updated. + int64 updated_at = 3; + + string kubeconfig = 4; +} + +message ClusterListResponse { + repeated Cluster clusters = 1; +} + +message ClusterResponse { + Cluster cluster = 1; +} \ No newline at end of file diff --git a/pkg/apiserver/proto/model/definitions.pb.go b/pkg/apiserver/proto/model/definitions.pb.go new file mode 100644 index 000000000..42a9bc0f1 --- /dev/null +++ b/pkg/apiserver/proto/model/definitions.pb.go @@ -0,0 +1,258 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/definitions.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Definition struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` + Jsonschema string `protobuf:"bytes,3,opt,name=jsonschema,proto3" json:"jsonschema,omitempty"` + Namespace string `protobuf:"bytes,4,opt,name=namespace,proto3" json:"namespace,omitempty"` +} + +func (x *Definition) Reset() { + *x = Definition{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_definitions_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Definition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Definition) ProtoMessage() {} + +func (x *Definition) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_definitions_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Definition.ProtoReflect.Descriptor instead. +func (*Definition) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_definitions_proto_rawDescGZIP(), []int{0} +} + +func (x *Definition) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Definition) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Definition) GetJsonschema() string { + if x != nil { + return x.Jsonschema + } + return "" +} + +func (x *Definition) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +type DefinitionsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Definitions []*Definition `protobuf:"bytes,1,rep,name=definitions,proto3" json:"definitions,omitempty"` +} + +func (x *DefinitionsResponse) Reset() { + *x = DefinitionsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_definitions_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DefinitionsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DefinitionsResponse) ProtoMessage() {} + +func (x *DefinitionsResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_definitions_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DefinitionsResponse.ProtoReflect.Descriptor instead. +func (*DefinitionsResponse) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_definitions_proto_rawDescGZIP(), []int{1} +} + +func (x *DefinitionsResponse) GetDefinitions() []*Definition { + if x != nil { + return x.Definitions + } + return nil +} + +var File_pkg_proto_model_definitions_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_definitions_proto_rawDesc = []byte{ + 0x0a, 0x21, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, + 0x64, 0x65, 0x6c, 0x22, 0x72, 0x0a, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x6a, 0x73, 0x6f, + 0x6e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6a, + 0x73, 0x6f, 0x6e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, + 0x0a, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x2b, 0x5a, 0x29, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x61, 0x6d, 0x2d, 0x64, + 0x65, 0x76, 0x2f, 0x76, 0x65, 0x6c, 0x61, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_pkg_proto_model_definitions_proto_rawDescOnce sync.Once + file_pkg_proto_model_definitions_proto_rawDescData = file_pkg_proto_model_definitions_proto_rawDesc +) + +func file_pkg_proto_model_definitions_proto_rawDescGZIP() []byte { + file_pkg_proto_model_definitions_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_definitions_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_definitions_proto_rawDescData) + }) + return file_pkg_proto_model_definitions_proto_rawDescData +} + +var file_pkg_proto_model_definitions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_pkg_proto_model_definitions_proto_goTypes = []interface{}{ + (*Definition)(nil), // 0: vela.api.model.Definition + (*DefinitionsResponse)(nil), // 1: vela.api.model.DefinitionsResponse +} +var file_pkg_proto_model_definitions_proto_depIdxs = []int32{ + 0, // 0: vela.api.model.DefinitionsResponse.definitions:type_name -> vela.api.model.Definition + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_definitions_proto_init() } +func file_pkg_proto_model_definitions_proto_init() { + if File_pkg_proto_model_definitions_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_definitions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Definition); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_definitions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DefinitionsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_definitions_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_definitions_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_definitions_proto_depIdxs, + MessageInfos: file_pkg_proto_model_definitions_proto_msgTypes, + }.Build() + File_pkg_proto_model_definitions_proto = out.File + file_pkg_proto_model_definitions_proto_rawDesc = nil + file_pkg_proto_model_definitions_proto_goTypes = nil + file_pkg_proto_model_definitions_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/definitions.proto b/pkg/apiserver/proto/model/definitions.proto new file mode 100644 index 000000000..e1ecc1ff7 --- /dev/null +++ b/pkg/apiserver/proto/model/definitions.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package vela.api.model; +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Definition{ + string name = 1; + string desc = 2; + string jsonschema = 3; + string namespace = 4; +} + +message DefinitionsResponse{ + repeated Definition definitions = 1; +} \ No newline at end of file diff --git a/pkg/apiserver/proto/model/schema.pb.go b/pkg/apiserver/proto/model/schema.pb.go new file mode 100644 index 000000000..db0a49af9 --- /dev/null +++ b/pkg/apiserver/proto/model/schema.pb.go @@ -0,0 +1,368 @@ +/* +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. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: pkg/proto/model/schema.proto + +package model + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Schema struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + // repeated Properties properties = 2; + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Jsonschema string `protobuf:"bytes,3,opt,name=jsonschema,proto3" json:"jsonschema,omitempty"` +} + +func (x *Schema) Reset() { + *x = Schema{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_schema_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Schema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Schema) ProtoMessage() {} + +func (x *Schema) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_schema_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Schema.ProtoReflect.Descriptor instead. +func (*Schema) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_schema_proto_rawDescGZIP(), []int{0} +} + +func (x *Schema) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Schema) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Schema) GetJsonschema() string { + if x != nil { + return x.Jsonschema + } + return "" +} + +type Properties struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Tuple []*Tuple `protobuf:"bytes,2,rep,name=tuple,proto3" json:"tuple,omitempty"` + JsonSchema string `protobuf:"bytes,3,opt,name=jsonSchema,proto3" json:"jsonSchema,omitempty"` +} + +func (x *Properties) Reset() { + *x = Properties{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_schema_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Properties) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Properties) ProtoMessage() {} + +func (x *Properties) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_schema_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Properties.ProtoReflect.Descriptor instead. +func (*Properties) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_schema_proto_rawDescGZIP(), []int{1} +} + +func (x *Properties) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Properties) GetTuple() []*Tuple { + if x != nil { + return x.Tuple + } + return nil +} + +func (x *Properties) GetJsonSchema() string { + if x != nil { + return x.JsonSchema + } + return "" +} + +type Tuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + PrintableType string `protobuf:"bytes,3,opt,name=printable_type,json=printableType,proto3" json:"printable_type,omitempty"` + Required bool `protobuf:"varint,4,opt,name=required,proto3" json:"required,omitempty"` + Default string `protobuf:"bytes,5,opt,name=default,proto3" json:"default,omitempty"` +} + +func (x *Tuple) Reset() { + *x = Tuple{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_proto_model_schema_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Tuple) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Tuple) ProtoMessage() {} + +func (x *Tuple) ProtoReflect() protoreflect.Message { + mi := &file_pkg_proto_model_schema_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Tuple.ProtoReflect.Descriptor instead. +func (*Tuple) Descriptor() ([]byte, []int) { + return file_pkg_proto_model_schema_proto_rawDescGZIP(), []int{2} +} + +func (x *Tuple) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Tuple) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Tuple) GetPrintableType() string { + if x != nil { + return x.PrintableType + } + return "" +} + +func (x *Tuple) GetRequired() bool { + if x != nil { + return x.Required + } + return false +} + +func (x *Tuple) GetDefault() string { + if x != nil { + return x.Default + } + return "" +} + +var File_pkg_proto_model_schema_proto protoreflect.FileDescriptor + +var file_pkg_proto_model_schema_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, + 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x5e, + 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, + 0x0a, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x6d, + 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x2b, 0x0a, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x76, 0x65, 0x6c, 0x61, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x2e, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x1e, 0x0a, + 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x22, 0x9a, 0x01, + 0x0a, 0x05, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, + 0x0e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x61, 0x6d, 0x2d, 0x64, 0x65, 0x76, + 0x2f, 0x76, 0x65, 0x6c, 0x61, 0x63, 0x70, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_pkg_proto_model_schema_proto_rawDescOnce sync.Once + file_pkg_proto_model_schema_proto_rawDescData = file_pkg_proto_model_schema_proto_rawDesc +) + +func file_pkg_proto_model_schema_proto_rawDescGZIP() []byte { + file_pkg_proto_model_schema_proto_rawDescOnce.Do(func() { + file_pkg_proto_model_schema_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_proto_model_schema_proto_rawDescData) + }) + return file_pkg_proto_model_schema_proto_rawDescData +} + +var file_pkg_proto_model_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_pkg_proto_model_schema_proto_goTypes = []interface{}{ + (*Schema)(nil), // 0: vela.api.model.Schema + (*Properties)(nil), // 1: vela.api.model.Properties + (*Tuple)(nil), // 2: vela.api.model.Tuple +} +var file_pkg_proto_model_schema_proto_depIdxs = []int32{ + 2, // 0: vela.api.model.Properties.tuple:type_name -> vela.api.model.Tuple + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_pkg_proto_model_schema_proto_init() } +func file_pkg_proto_model_schema_proto_init() { + if File_pkg_proto_model_schema_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_pkg_proto_model_schema_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Schema); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_schema_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Properties); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_proto_model_schema_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Tuple); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pkg_proto_model_schema_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_pkg_proto_model_schema_proto_goTypes, + DependencyIndexes: file_pkg_proto_model_schema_proto_depIdxs, + MessageInfos: file_pkg_proto_model_schema_proto_msgTypes, + }.Build() + File_pkg_proto_model_schema_proto = out.File + file_pkg_proto_model_schema_proto_rawDesc = nil + file_pkg_proto_model_schema_proto_goTypes = nil + file_pkg_proto_model_schema_proto_depIdxs = nil +} diff --git a/pkg/apiserver/proto/model/schema.proto b/pkg/apiserver/proto/model/schema.proto new file mode 100644 index 000000000..8d4703fa8 --- /dev/null +++ b/pkg/apiserver/proto/model/schema.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; +package vela.api.model; + +option go_package = "github.com/oam-dev/velacp/pkg/proto/model"; + +message Schema { + + string description = 1; + +// repeated Properties properties = 2; + string name = 2; + + string jsonschema = 3; + +} + +message Properties{ + string name = 1; + repeated Tuple tuple = 2; + string jsonSchema = 3; +} + +message Tuple { + string name = 1; + string description = 2; + string printable_type = 3; + bool required = 4; + string default = 5; +} \ No newline at end of file diff --git a/pkg/apiserver/rest/apis/catalog.go b/pkg/apiserver/rest/apis/catalog.go new file mode 100644 index 000000000..fd2453931 --- /dev/null +++ b/pkg/apiserver/rest/apis/catalog.go @@ -0,0 +1,40 @@ +/* +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 apis + +import "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + +// CatalogType catalog for list capability +type CatalogType struct { + Name string `json:"name"` + Desc string `json:"desc,omitempty"` + UpdateAt int64 `json:"updateAt,omitempty"` + Type string `json:"type,omitempty"` + URL string `json:"url,omitempty"` + Token string `json:"token,omitempty"` +} + +// CatalogMeta catalog meta +type CatalogMeta struct { + Catalog *model.Catalog `json:"catalog"` +} + +// CatalogRequest catalog request +type CatalogRequest struct { + CatalogType + Method Action `json:"method"` +} diff --git a/pkg/apiserver/rest/apis/types.go b/pkg/apiserver/rest/apis/types.go new file mode 100644 index 000000000..57134effd --- /dev/null +++ b/pkg/apiserver/rest/apis/types.go @@ -0,0 +1,51 @@ +/* +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 apis + +import "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + +// Action action type +type Action string + +// ClusterType cluster type +type ClusterType struct { + Name string `json:"name"` + Desc string `json:"desc,omitempty"` + UpdateAt int64 `json:"updateAt,omitempty"` + Kubeconfig string `json:"kubeconfig"` +} + +// ClusterMeta cluster meta +type ClusterMeta struct { + Cluster *model.Cluster `json:"cluster"` +} + +// ClustersMeta cluster list meta +type ClustersMeta struct { + Clusters []string `json:"clusters"` +} + +// ClusterRequest cluster request +type ClusterRequest struct { + ClusterType + Method Action `json:"method"` +} + +// ClusterVelaStatus status for whether install KubeVela +type ClusterVelaStatus struct { + Installed bool `json:"installed"` +} diff --git a/pkg/apiserver/rest/client/initClient.go b/pkg/apiserver/rest/client/initClient.go new file mode 100644 index 000000000..fc4b603f8 --- /dev/null +++ b/pkg/apiserver/rest/client/initClient.go @@ -0,0 +1,47 @@ +/* +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 client + +import ( + k8sruntime "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + + oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev" +) + +// NewK8sClient init a local k8s client which add oamcore scheme +func NewK8sClient() (client.Client, error) { + conf, err := config.GetConfig() + if err != nil { + return nil, err + } + scheme := k8sruntime.NewScheme() + if err := clientgoscheme.AddToScheme(scheme); err != nil { + return nil, err + } + if err := oamcore.AddToScheme(scheme); err != nil { + return nil, err + } + + k8sClient, err := client.New(conf, client.Options{Scheme: scheme}) + if err != nil { + return nil, err + } + return k8sClient, nil +} diff --git a/pkg/apiserver/rest/rest_server.go b/pkg/apiserver/rest/rest_server.go new file mode 100644 index 000000000..52e69b9ae --- /dev/null +++ b/pkg/apiserver/rest/rest_server.go @@ -0,0 +1,172 @@ +/* +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 rest + +import ( + "context" + "fmt" + "net/http" + + echo "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/pkg/apiserver/log" + initClient "github.com/oam-dev/kubevela/pkg/apiserver/rest/client" + "github.com/oam-dev/kubevela/pkg/apiserver/rest/services" +) + +var _ APIServer = &restServer{} + +// Config config for server +type Config struct { + Port int +} + +// APIServer interface for call api server +type APIServer interface { + Run(context.Context) error +} + +type restServer struct { + server *echo.Echo + k8sClient client.Client + cfg Config +} + +const ( + // DefaultUINamespace default namespace for configmap info management in velaux system + DefaultUINamespace = "velaux-system" +) + +// New create restserver with config data +func New(cfg Config) (APIServer, error) { + client, err := initClient.NewK8sClient() + if err != nil { + return nil, fmt.Errorf("create client for clusterService failed") + } + s := &restServer{ + server: newEchoInstance(), + k8sClient: client, + cfg: cfg, + } + + 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 { + err := s.registerServices() + if err != nil { + return err + } + return s.startHTTP(ctx) +} + +func (s *restServer) registerServices() error { + + // create specific namespace for better resource management + var ns v1.Namespace + if err := s.k8sClient.Get(context.Background(), types.NamespacedName{Name: DefaultUINamespace}, &ns); err != nil && apierrors.IsNotFound(err) { + // not found + ns = v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: DefaultUINamespace, + }, + } + err := s.k8sClient.Create(context.Background(), &ns) + if err != nil { + log.Logger.Errorf("create namespace for velaux system failed %s ", err.Error()) + return err + } + } + // init common client for all service + commonClient, err := initClient.NewK8sClient() + if err != nil { + return err + } + + // capability + capabilityService := services.NewCapabilityService(commonClient) + s.server.GET("/capabilities", capabilityService.ListCapabilities) + s.server.GET("/capabilities/:capabilityName", capabilityService.GetCapability) + s.server.POST("/capabilities/:capabilityName/install", capabilityService.InstallCapability) + + // catalog + catalogService := services.NewCatalogService(commonClient) + s.server.GET("/catalogs", catalogService.ListCatalogs) + s.server.POST("/catalogs", catalogService.AddCatalog) + s.server.PUT("/catalogs", catalogService.UpdateCatalog) + s.server.GET("/catalogs/:catalogName", catalogService.GetCatalog) + s.server.DELETE("/catalogs/:catalogName", catalogService.DelCatalog) + + // cluster + clusterService := services.NewClusterService(commonClient) + s.server.GET("/cluster", clusterService.GetCluster) + s.server.GET("/clusters", clusterService.ListClusters) + s.server.GET("/clusternames", clusterService.GetClusterNames) + s.server.POST("/clusters", clusterService.AddCluster) + s.server.PUT("/clusters", clusterService.UpdateCluster) + s.server.DELETE("/clusters/:clusterName", clusterService.DelCluster) + + // definition + s.server.GET("/clusters/:clusterName/componentdefinitions", clusterService.ListComponentDef) + s.server.GET("/clusters/:clusterName/traitdefinitions", clusterService.ListTraitDef) + + // application + applicationService := services.NewApplicationService(commonClient) + s.server.GET("/clusters/:cluster/applications", applicationService.GetApplications) + s.server.GET("/clusters/:cluster/applications/:application", applicationService.GetApplicationDetail) + s.server.POST("/clusters/:cluster/applications", applicationService.AddApplications) + s.server.POST("/clusters/:cluster/appYaml", applicationService.AddApplicationYaml) + s.server.PUT("/clusters/:cluster/applications", applicationService.UpdateApplications) + s.server.DELETE("/clusters/:cluster/applications/:application", applicationService.RemoveApplications) + + // show Definition schema + schemaService := services.NewSchemaService(commonClient) + s.server.GET("/clusters/:cluster/schema", schemaService.GetWorkloadSchema) + + return nil +} + +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) +} diff --git a/pkg/apiserver/rest/services/application.go b/pkg/apiserver/rest/services/application.go new file mode 100644 index 000000000..671129618 --- /dev/null +++ b/pkg/apiserver/rest/services/application.go @@ -0,0 +1,458 @@ +/* +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" + "fmt" + "net/http" + "sort" + "strconv" + "time" + + "github.com/labstack/echo/v4" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/duration" + yamlutil "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/kubectl/pkg/util/event" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/utils/apply" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + "github.com/oam-dev/kubevela/pkg/apiserver/runtime" +) + +// ApplicationService application service +type ApplicationService struct { + k8sClient client.Client +} + +const ( + // DefaultUINamespace default namespace for configmap info management in velaux system + DefaultUINamespace = "velaux-system" + // DefaultAppNamespace default namespace for application + DefaultAppNamespace = "default" + // DefaultVelaNamespace default namespace for vela system + DefaultVelaNamespace = "vela-system" +) + +// NewApplicationService new application service +func NewApplicationService(client client.Client) *ApplicationService { + + return &ApplicationService{ + k8sClient: client, + } +} + +// GetApplications get applications only with configmap info from cluster +func (s *ApplicationService) GetApplications(c echo.Context) error { + // appName := c.QueryParam("appName") // change to get application + + var cmList v1.ConfigMapList + labels := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "configdata", + }, + } + selector, err := metav1.LabelSelectorAsSelector(labels) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("create label selector for configmap failed : %s", err.Error())) + } + err = s.k8sClient.List(context.Background(), &cmList, &client.ListOptions{ + LabelSelector: selector, + }) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("list configmap for cluster info failed : %s", err.Error())) + } + var appList = make([]*model.Application, 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 + } + app := model.Application{ + Name: c.Name, + Namespace: c.Namespace, + Desc: cmList.Items[i].Data["Desc"], + UpdatedAt: UpdateInt, + } + appList = append(appList, &app) + } + + return c.JSON(http.StatusOK, model.ApplicationListResponse{ + Applications: appList, + }) +} + +// GetApplicationDetail get application detail +func (s *ApplicationService) GetApplicationDetail(c echo.Context) error { + appName := c.Param("application") + clusterName := c.Param("cluster") + + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get client info failed: %s ", err.Error())) + } + + // get application configmap info + var cm v1.ConfigMap + err = s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: appName}, &cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client get configmap for %s failed :%s ", appName, err.Error())) + } + + var app model.Application + + app.Name = appName + app.Desc = cm.Data["Desc"] + app.Namespace = cm.Data["Namespace"] + app.ClusterName = clusterName + app.UpdatedAt, err = strconv.ParseInt(cm.Data["UpdatedAt"], 10, 64) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to resolve update parameter in %s:%s ", clusterName, err.Error())) + } + + var appObj = v1beta1.Application{} + if err := cli.Get(context.Background(), client.ObjectKey{Namespace: DefaultAppNamespace, Name: appName}, &appObj); err != nil { // application crd info + return err + } + + for i, c := range appObj.Status.Services { + comp := model.ComponentType{ + Name: c.Name, + Namespace: DefaultAppNamespace, + Workload: c.WorkloadDefinition.Kind, + Type: appObj.Spec.Components[i].Type, + Health: c.Healthy, + Phase: string(appObj.Status.Phase), + } + app.Components = append(app.Components, &comp) + } + + el := v1.EventList{} + fieldStr := fmt.Sprintf("involvedObject.kind=Application,involvedObject.name=%s,,involvedObject.namespace=%s", appName, app.Namespace) + if err := cli.List(context.Background(), &el, &client.ListOptions{ + Namespace: DefaultAppNamespace, + Raw: &metav1.ListOptions{FieldSelector: fieldStr}, + }); err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client get event failed :%s ", err.Error())) + } + // sort event + sort.Sort(event.SortableEvents(el.Items)) + for _, e := range el.Items { + var age string + if e.Count > 1 { + age = fmt.Sprintf("%s (x%d over %s)", translateTimestampSince(e.LastTimestamp), e.Count, translateTimestampSince(e.FirstTimestamp)) + } else { + age = translateTimestampSince(e.FirstTimestamp) + if e.FirstTimestamp.IsZero() { + age = translateMicroTimestampSince(e.EventTime) + } + } + app.Events = append(app.Events, &model.AppEventType{ + Type: e.Type, + Age: age, + Reason: e.Reason, + Message: e.Message, + }) + } + + return c.JSON(http.StatusOK, model.ApplicationResponse{ + Application: &app, + }) +} + +// AddApplications for add applications to cluster +func (s *ApplicationService) AddApplications(c echo.Context) error { + clusterName := c.Param("cluster") + app := new(model.Application) + if err := c.Bind(app); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("resolve request failed %s ", err.Error())) + } + app.ClusterName = clusterName + isAppExist, err := s.checkAppExist(app.Name) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("check app existed failed :%s ", err.Error())) + } + if isAppExist { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("application %s has existed: %s ", app.Name, err.Error())) + } + + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get client failed: %s ", err.Error())) + } + + expectApp, err := runtime.ParseCoreApplication(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("parse app failed: %s ", err.Error())) + } + if err := cli.Create(context.Background(), &expectApp); err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("create app failed: %s ", err.Error())) + } + + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": app.Name, + "Desc": app.Desc, + "Namespace": app.Namespace, + "UpdatedAt": time.Now().String(), + "ClusterName": clusterName, + } + + label := map[string]string{ + "app": "configdata", + } + cm, err = ToConfigMap(app.Name, DefaultUINamespace, label, configdata) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert config map failed %s ", err.Error())) + } + err = s.k8sClient.Create(context.Background(), cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("create configmap for %s failed: %s ", app.Name, err.Error())) + } + + return c.JSON(http.StatusCreated, model.ApplicationResponse{ + Application: app, + }) +} + +// AddApplicationYaml for add applications with yaml to cluster +func (s *ApplicationService) AddApplicationYaml(c echo.Context) error { + clusterName := c.Param("cluster") + appYaml := new(model.AppYaml) + if err := c.Bind(appYaml); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("resolve request failed %s ", err.Error())) + } + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get client failed: %s ", err.Error())) + } + + decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(appYaml.Yaml)), 100) + var appObj v1beta1.Application + if err = decoder.Decode(&appObj); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("decode for app yaml failed: %s ", err.Error())) + } + if appObj.Namespace == "" { + appObj.Namespace = DefaultAppNamespace + } + + if err := cli.Create(context.Background(), &appObj); err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client app failed: %s ", err.Error())) + } + app, err := runtime.ParseApplicationYaml(&appObj) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client parse app failed: %s ", err.Error())) + } + + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": app.Name, + "Desc": app.Desc, + "UpdatedAt": time.Now().String(), + "ClusterName": clusterName, + } + + label := map[string]string{ + "app": "configdata", + } + cm, err = ToConfigMap(app.Name, DefaultUINamespace, label, configdata) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert config map failed %s ", err.Error())) + } + err = s.k8sClient.Create(context.Background(), cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to create configmap for %s : %s ", app.Name, err.Error())) + } + + return c.JSON(http.StatusOK, model.ApplicationResponse{ + Application: app, + }) +} + +// UpdateApplications for update application +func (s *ApplicationService) UpdateApplications(c echo.Context) error { + clusterName := c.Param("cluster") + app := new(model.Application) + if err := c.Bind(app); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("resolve request failed %s ", err.Error())) + } + app.ClusterName = clusterName + + isAppExist, err := s.checkAppExist(app.Name) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("check app existed failed :%s ", err.Error())) + } + if !isAppExist { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("application %s do not existed: %s ", app.Name, err.Error())) + } + + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get client failed :%s ", err.Error())) + } + + expectApp, err := runtime.ParseCoreApplication(app) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client parse app failed :%s ", err.Error())) + } + expectAppObj, err := k8sruntime.DefaultUnstructuredConverter.ToUnstructured(&expectApp) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert app to unstructrue failed :%s ", err.Error())) + } + + expectAppUnStruct := &unstructured.Unstructured{Object: expectAppObj} + expectAppUnStruct.SetGroupVersionKind(v1beta1.ApplicationKindVersionKind) + + applicator := apply.NewAPIApplicator(cli) + if err := applicator.Apply(context.Background(), expectAppUnStruct); err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("apply app failed :%s ", err.Error())) + } + + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": app.Name, + "Desc": app.Desc, + "UpdatedAt": time.Now().String(), + "ClusterName": clusterName, + } + + label := map[string]string{ + "app": "configdata", + } + cm, err = ToConfigMap(app.Name, DefaultUINamespace, label, configdata) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert config map failed %s ", err.Error())) + } + + err = s.k8sClient.Create(context.Background(), cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to create configmap for %s : %s ", app.Name, err.Error())) + } + + return c.JSON(http.StatusOK, model.ApplicationResponse{ + Application: app, + }) +} + +// RemoveApplications for remove application from cluster +func (s *ApplicationService) RemoveApplications(c echo.Context) error { + appName := c.Param("application") + clusterName := c.Param("cluster") + // get namespace for application + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: appName}, &cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client get configmap failed: %s ", err.Error())) + } + + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get client by name failed: %s ", err.Error())) + } + + application := &model.Application{Name: appName, Namespace: cm.Data["Namespace"]} + expectApp, err := runtime.ParseCoreApplication(application) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("parse app failed: %s ", err.Error())) + } + if err := cli.Delete(context.Background(), &expectApp); err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("delete app failed: %s ", err.Error())) + } + + // delete configmap for app info + cm.SetName(appName) + cm.SetNamespace(DefaultUINamespace) + if err := s.k8sClient.Delete(context.Background(), &cm); err != nil { + return c.JSON(http.StatusInternalServerError, false) + } + + return c.JSON(http.StatusOK, model.ApplicationResponse{ + Application: &model.Application{Name: appName}, + }) +} + +func translateTimestampSince(timestamp metav1.Time) string { + if timestamp.IsZero() { + return "" + } + + return duration.HumanDuration(time.Since(timestamp.Time)) +} + +func translateMicroTimestampSince(timestamp metav1.MicroTime) string { + if timestamp.IsZero() { + return "" + } + + return duration.HumanDuration(time.Since(timestamp.Time)) +} + +// checkAppExist check whether app is existed +func (s *ApplicationService) checkAppExist(appName string) (bool, error) { + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: appName}, &cm) + if err != nil { + if apierrors.IsNotFound(err) { // not found + return false, nil + } + // other error + return false, err + } + // found + return true, nil +} + +// getClientByClusterName get client by cluster name +func (s *ApplicationService) getClientByClusterName(clusterName string) (client.Client, error) { + var cm v1.ConfigMap + // k8sClient is a common client for getting configmap info in current cluster. + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) // cluster configmap info + if err != nil { + return nil, fmt.Errorf("unable to find configmap parameters in %s:%w ", clusterName, err) + } + + // cli is the client running in specific cluster to get specific k8s cr resource. + cli, err := runtime.GetClient([]byte(cm.Data["Kubeconfig"])) + if err != nil { + return nil, err + } + return cli, nil +} + +// ToConfigMap convert map value to configmap format +func ToConfigMap(name, namespace string, label map[string]string, configData map[string]string) (*v1.ConfigMap, error) { + var cm = v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + } + cm.SetName(name) + cm.SetNamespace(namespace) + cm.SetLabels(label) + cm.Data = configData + return &cm, nil +} diff --git a/pkg/apiserver/rest/services/capability.go b/pkg/apiserver/rest/services/capability.go new file mode 100644 index 000000000..e5a3e7bbe --- /dev/null +++ b/pkg/apiserver/rest/services/capability.go @@ -0,0 +1,115 @@ +/* +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" + + "github.com/labstack/echo/v4" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/pkg/apiserver/log" + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" +) + +// CapabilityService capability service +type CapabilityService struct { + k8sClient client.Client +} + +// NewCapabilityService create capability service +func NewCapabilityService(client client.Client) *CapabilityService { + + return &CapabilityService{ + k8sClient: client, + } +} + +// ListCapabilities list method for capability configmap +func (s *CapabilityService) ListCapabilities(c echo.Context) error { + var cmList v1.ConfigMapList + labels := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "capability": "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 capabilityList = make([]*model.Capability, 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 + } + capability := model.Capability{ + Name: c.Name, + UpdatedAt: UpdateInt, + Desc: cmList.Items[i].Data["Desc"], + Type: cmList.Items[i].Data["Type"], + CatalogName: cmList.Items[i].Data["CatalogName"], + JsonSchema: cmList.Items[i].Data["initializer"], + } + capabilityList = append(capabilityList, &capability) + } + return c.JSON(http.StatusOK, model.CapabilityListResponse{Capabilities: capabilityList}) +} + +// GetCapability get method for capability configmap +func (s *CapabilityService) GetCapability(c echo.Context) error { + capabilityName := c.Param("capabilityName") + + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultVelaNamespace, Name: capabilityName}, &cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get config for %s failed %s", capabilityName, err.Error())) + } + var capability = model.Capability{ + Name: capabilityName, + CatalogName: capabilityName, + JsonSchema: cm.Data["initializer"], + } + + return c.JSON(http.StatusOK, model.CapabilityResponse{Capability: &capability}) +} + +// InstallCapability installs a capability into a cluster +// +// TODO: implement this method, +// install logic is same as the `vela` cli, we should find a way to reuse these code: +// https://github.com/oam-dev/kubevela/blob/9a10e967eec8e42a8aa284ddb20fde204696aa69/references/common/capability.go#L88 +func (s *CapabilityService) InstallCapability(c echo.Context) error { + capabilityName := c.Param("capabilityName") + clusterName := c.QueryParam("clusterName") + + log.Logger.Debugf("installing capability %s to cluster %s", capabilityName, clusterName) + + return c.JSON(http.StatusOK, true) +} diff --git a/pkg/apiserver/rest/services/catalog.go b/pkg/apiserver/rest/services/catalog.go new file mode 100644 index 000000000..693828f8f --- /dev/null +++ b/pkg/apiserver/rest/services/catalog.go @@ -0,0 +1,215 @@ +/* +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" + + echo "github.com/labstack/echo/v4" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/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(client client.Client) *CatalogService { + + return &CatalogService{ + k8sClient: client, + } +} + +// ListCatalogs list method for catalog configmap +func (s *CatalogService) ListCatalogs(c echo.Context) error { + var cmList v1.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, model.CatalogListResponse{Catalogs: catalogList}) +} + +// GetCatalog get method for catalog configmap +func (s *CatalogService) GetCatalog(c echo.Context) error { + catalogName := c.Param("catalogName") + + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultVelaNamespace, Name: catalogName}, &cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get config for %s failed %s", catalogName, err.Error())) + } + UpdatedInt, err := strconv.ParseInt(cm.Data["UpdatedAt"], 10, 64) + if err != nil { + return 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, model.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 *v1.ConfigMap + configdata := map[string]string{ + "Name": catalogReq.Name, + "Desc": catalogReq.Desc, + "UpdatedAt": time.Now().String(), + } + + label := map[string]string{ + "catalog": "configdata", + } + cm, err = ToConfigMap(catalogReq.Name, DefaultUINamespace, label, configdata) + if err != nil { + return fmt.Errorf("convert config map failed %w ", err) + } + 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.CatalogMeta{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) + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": catalogReq.Name, + "Desc": catalogReq.Desc, + "UpdatedAt": time.Now().String(), + } + + label := map[string]string{ + "catalog": "configdata", + } + cm, err := ToConfigMap(catalogReq.Name, DefaultUINamespace, label, configdata) + if err != nil { + return fmt.Errorf("convert config map failed %w ", err) + } + 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.CatalogMeta{Catalog: &catalog}) +} + +// DelCatalog delete method for catalog configmap +func (s *CatalogService) DelCatalog(c echo.Context) error { + catalogName := c.Param("catalogName") + + var cm v1.ConfigMap + cm.SetName(catalogName) + cm.SetNamespace(DefaultUINamespace) + 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 v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, 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, + } +} diff --git a/pkg/apiserver/rest/services/cluster.go b/pkg/apiserver/rest/services/cluster.go new file mode 100644 index 000000000..626e0cb42 --- /dev/null +++ b/pkg/apiserver/rest/services/cluster.go @@ -0,0 +1,233 @@ +/* +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" + + echo "github.com/labstack/echo/v4" + v1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis" +) + +// ClusterService cluster service +type ClusterService struct { + k8sClient client.Client +} + +// NewClusterService new cluster service +func NewClusterService(client client.Client) *ClusterService { + + return &ClusterService{ + k8sClient: client, + } +} + +// GetClusterNames list method for all cluster names +func (s *ClusterService) GetClusterNames(c echo.Context) error { + var cmList v1.ConfigMapList + labels := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "cluster": "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 + } + + names := []string{} + for i := range cmList.Items { + names = append(names, cmList.Items[i].Name) + } + + return c.JSON(http.StatusOK, apis.ClustersMeta{Clusters: names}) +} + +// ListClusters list method for all cluster +func (s *ClusterService) ListClusters(c echo.Context) error { + + var cmList v1.ConfigMapList + labels := &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "cluster": "configdata", + }, + } + selector, err := metav1.LabelSelectorAsSelector(labels) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("create label selector for configmap failed : %s", err.Error())) + } + err = s.k8sClient.List(context.Background(), &cmList, &client.ListOptions{ + LabelSelector: selector, + }) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("list configmap for cluster info failed : %s", err.Error())) + } + + var clusterList = make([]*model.Cluster, 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 + } + cluster := model.Cluster{ + Name: c.Name, + UpdatedAt: UpdateInt, + Desc: cmList.Items[i].Data["Desc"], + } + clusterList = append(clusterList, &cluster) + } + + return c.JSON(http.StatusOK, model.ClusterListResponse{Clusters: clusterList}) +} + +// GetCluster get method for cluster +func (s *ClusterService) GetCluster(c echo.Context) error { + clusterName := c.QueryParam("clusterName") + + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("client get configmap for %s failed :%s ", clusterName, err.Error())) + } + var cluster model.Cluster + cluster.Name = cm.Data["Name"] + cluster.Desc = cm.Data["Desc"] + cluster.Kubeconfig = cm.Data["Kubeconfig"] + cluster.UpdatedAt, err = strconv.ParseInt(cm.Data["UpdatedAt"], 10, 64) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to resolve update parameter in %s:%s ", clusterName, err.Error())) + } + + return c.JSON(http.StatusOK, model.ClusterResponse{Cluster: &cluster}) +} + +// AddCluster add method for cluster +func (s *ClusterService) AddCluster(c echo.Context) error { + clusterReq := new(apis.ClusterRequest) + if err := c.Bind(clusterReq); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("resolve request failed %s ", err.Error())) + } + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterReq.Name}, &cm) + if err != nil && apierrors.IsNotFound(err) { + // not found + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("get cluster config failed: %s ", err.Error())) + } + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": clusterReq.Name, + "Desc": clusterReq.Desc, + "UpdatedAt": time.Now().String(), + "Kubecofig": clusterReq.Kubeconfig, + } + label := map[string]string{ + "cluster": "configdata", + } + cm, err = ToConfigMap(clusterReq.Name, DefaultUINamespace, label, configdata) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert config map failed %s ", err.Error())) + } + err = s.k8sClient.Create(context.Background(), cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to create configmap for %s : %s ", clusterReq.Name, err.Error())) + } + } else { + // found + return c.JSON(http.StatusBadRequest, fmt.Sprintf("cluster %s has exist", clusterReq.Name)) + } + cluster := convertToCluster(clusterReq) + return c.JSON(http.StatusCreated, apis.ClusterMeta{Cluster: &cluster}) +} + +// UpdateCluster update method for cluster +func (s *ClusterService) UpdateCluster(c echo.Context) error { + clusterReq := new(apis.ClusterRequest) + if err := c.Bind(clusterReq); err != nil { + return c.JSON(http.StatusBadRequest, fmt.Sprintf("resolve request failed %s ", err.Error())) + } + cluster := convertToCluster(clusterReq) + var cm *v1.ConfigMap + configdata := map[string]string{ + "Name": clusterReq.Name, + "Desc": clusterReq.Desc, + "UpdatedAt": time.Now().String(), + "Kubecofig": clusterReq.Kubeconfig, + } + + label := map[string]string{ + "cluster": "configdata", + } + cm, err := ToConfigMap(clusterReq.Name, DefaultUINamespace, label, configdata) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("convert config map failed %s ", err.Error())) + } + err = s.k8sClient.Update(context.Background(), cm) + if err != nil { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("unable to update configmap for %s : %s ", clusterReq.Name, err.Error())) + } + return c.JSON(http.StatusOK, apis.ClusterMeta{Cluster: &cluster}) +} + +// DelCluster delete method for cluster +func (s *ClusterService) DelCluster(c echo.Context) error { + clusterName := c.Param("clusterName") + var cm v1.ConfigMap + cm.SetName(clusterName) + cm.SetNamespace(DefaultUINamespace) + if err := s.k8sClient.Delete(context.Background(), &cm); err != nil { + return c.JSON(http.StatusInternalServerError, false) + } + return c.JSON(http.StatusOK, true) +} + +// checkClusterExist check whether cluster exist with name +func (s *ClusterService) checkClusterExist(clusterName string) (bool, error) { + var cm v1.ConfigMap + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) + if err != nil && apierrors.IsNotFound(err) { // not found + return false, err + } + // found + return true, nil +} + +// convertToCluster get cluster model from request +func convertToCluster(clusterReq *apis.ClusterRequest) model.Cluster { + return model.Cluster{ + Name: clusterReq.Name, + Desc: clusterReq.Desc, + UpdatedAt: time.Now().Unix(), + Kubeconfig: clusterReq.Kubeconfig, + } +} diff --git a/pkg/apiserver/rest/services/definitions.go b/pkg/apiserver/rest/services/definitions.go new file mode 100644 index 000000000..5040871b9 --- /dev/null +++ b/pkg/apiserver/rest/services/definitions.go @@ -0,0 +1,155 @@ +/* +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" + "encoding/json" + "fmt" + "net/http" + "strconv" + + echo "github.com/labstack/echo/v4" + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + klog "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/apis/types" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + "github.com/oam-dev/kubevela/pkg/apiserver/runtime" +) + +// ListComponentDef list component definitions under cluster +func (s *ClusterService) ListComponentDef(c echo.Context) error { + clusterName := c.Param("clusterName") + exist, err := s.checkClusterExist(clusterName) + if err != nil { + return err + } + if !exist { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("cluster %s not existed", clusterName)) + } + + var cm v1.ConfigMap + // k8sClient is a common client for getting configmap info in current cluster. + err = s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) // cluster configmap info + if err != nil { + return fmt.Errorf("unable to find configmap parameters in %s:%w ", clusterName, err) + } + + // cli is the client running in specific cluster to get specific k8s crd resource. + cli, err := runtime.GetClient([]byte(cm.Data["Kubeconfig"])) + if err != nil { + return err + } + + list := &oamcore.ComponentDefinitionList{} + if err := runtime.List(cli, &client.ListOptions{}, list, list); err != nil { + return err + } + + var definitions []*model.Definition + for _, def := range list.Items { + definition, err := GenDefinition(cli, def.Name, def.Namespace) + if err != nil { + klog.ErrorS(err, "fail to gen definition", "definition", def.Name) + continue + } + + definition.Desc = def.GetAnnotations()[types.AnnDescription] + definitions = append(definitions, definition) + } + + return c.JSON(http.StatusOK, &model.DefinitionsResponse{ + Definitions: definitions, + }) +} + +// ListTraitDef list trait definitions under cluster +func (s *ClusterService) ListTraitDef(c echo.Context) error { + clusterName := c.Param("clusterName") + exist, err := s.checkClusterExist(clusterName) + if err != nil { + return err + } + if !exist { + return c.JSON(http.StatusInternalServerError, fmt.Sprintf("cluster %s not existed", clusterName)) + } + + var cm v1.ConfigMap + // k8sClient is a common client for getting configmap info in current cluster. + err = s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) // cluster configmap info + if err != nil { + return fmt.Errorf("unable to find configmap parameters in %s:%w ", clusterName, err) + } + + // cli is the client running in specific cluster to get specific k8s crd resource. + cli, err := runtime.GetClient([]byte(cm.Data["Kubeconfig"])) + if err != nil { + return err + } + + list := &oamcore.TraitDefinitionList{} + if err := runtime.List(cli, &client.ListOptions{}, list, list); err != nil { + return err + } + + var definitions []*model.Definition + for _, def := range list.Items { + definition, err := GenDefinition(cli, def.Name, def.Namespace) + if err != nil { + klog.ErrorS(err, "fail to gen definition", "definition", def.Name) + continue + } + + definition.Desc = def.GetAnnotations()[types.AnnDescription] + definitions = append(definitions, definition) + } + + return c.JSON(http.StatusOK, &model.DefinitionsResponse{ + Definitions: definitions, + }) +} + +// GenDefinition from configmap get definition jsonSchema +func GenDefinition(cli client.Client, name, namespace string) (*model.Definition, error) { + cm := &v1.ConfigMap{} + cmName := fmt.Sprintf("%s%s", types.CapabilityConfigMapNamePrefix, name) + if err := runtime.Get(cli, cm, cm, cmName, namespace); err != nil { + return nil, errors.Wrap(err, "fail to get definition from configmap") + } + klog.InfoS("success to get def from cm", "cm", cmName, cm.Data) + + jsonSchemaBytes, err := json.Marshal(cm.Data[types.OpenapiV3JSONSchema]) + if err != nil { + return nil, errors.Wrap(err, "fail to marshal definition to string") + } + + jsonSchema, err := strconv.Unquote(string(jsonSchemaBytes)) + if err != nil { + return nil, errors.Wrap(err, "fail to disable escape") + } + + return &model.Definition{ + Name: name, + Namespace: namespace, + Jsonschema: jsonSchema, + }, nil +} diff --git a/pkg/apiserver/rest/services/schema.go b/pkg/apiserver/rest/services/schema.go new file mode 100644 index 000000000..6ace6909c --- /dev/null +++ b/pkg/apiserver/rest/services/schema.go @@ -0,0 +1,115 @@ +/* +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" + + echo "github.com/labstack/echo/v4" + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + + "github.com/oam-dev/kubevela/pkg/apiserver/common" + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" + "github.com/oam-dev/kubevela/pkg/apiserver/runtime" +) + +// SchemaService schema service +type SchemaService struct { + k8sClient client.Client +} + +// NewSchemaService create schema service +func NewSchemaService(client client.Client) *SchemaService { + + return &SchemaService{ + k8sClient: client, + } +} + +// GetWorkloadSchema get workload schema +func (s *SchemaService) GetWorkloadSchema(c echo.Context) error { + definitionName := c.QueryParam("name") + definitionNamespace := c.QueryParam("namespace") + definitionType := c.QueryParam("type") + + clusterName := c.Param("cluster") + cli, err := s.getClientByClusterName(clusterName) + if err != nil { + return err + } + + key := client.ObjectKey{Namespace: definitionNamespace, Name: definitionName} + definition, err := GenDefinitionObj(definitionName, definitionType) + if err != nil { + return err + } + + if err := cli.Get(context.Background(), key, definition); err != nil { + return err + } + + parse := common.NewParseReference(cli) + schema, err := parse.ParseDefinition(definition, definitionName, definitionNamespace) + if err != nil { + return err + } + + return c.JSON(http.StatusOK, &model.DefinitionsResponse{ + Definitions: []*model.Definition{schema}, + }) +} + +// GenDefinitionObj generate definition object +func GenDefinitionObj(name, wType string) (*unstructured.Unstructured, error) { + obj := &unstructured.Unstructured{} + obj.SetName(name) + switch wType { + case "workload": + obj.SetGroupVersionKind(v1beta1.WorkloadDefinitionGroupVersionKind) + case "trait": + obj.SetGroupVersionKind(v1beta1.TraitDefinitionGroupVersionKind) + case "component": + obj.SetGroupVersionKind(v1beta1.ComponentDefinitionGroupVersionKind) + default: + return nil, errors.Errorf("not found definition %s", wType) + } + + return obj, nil +} + +func (s *SchemaService) getClientByClusterName(clusterName string) (client.Client, error) { + var cm v1.ConfigMap + // k8sClient is a common client for getting configmap info in current cluster. + err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: DefaultUINamespace, Name: clusterName}, &cm) // cluster configmap info + if err != nil { + return nil, fmt.Errorf("unable to find configmap parameters in %s:%w ", clusterName, err) + } + + // cli is the client running in specific cluster to get specific k8s cr resource. + cli, err := runtime.GetClient([]byte(cm.Data["Kubeconfig"])) + if err != nil { + return nil, err + } + return cli, nil +} diff --git a/pkg/apiserver/runtime/get.go b/pkg/apiserver/runtime/get.go new file mode 100644 index 000000000..a352aef90 --- /dev/null +++ b/pkg/apiserver/runtime/get.go @@ -0,0 +1,117 @@ +/* +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 runtime + +import ( + "context" + + "github.com/pkg/errors" + crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" + + core "github.com/oam-dev/kubevela/apis/core.oam.dev" +) + +var ( + // Scheme defines the default KubeVela schema + Scheme = k8sruntime.NewScheme() +) + +func init() { + _ = clientgoscheme.AddToScheme(Scheme) + _ = crdv1.AddToScheme(Scheme) + _ = core.AddToScheme(Scheme) + // +kubebuilder:scaffold:scheme +} + +// Get get method for kubernetes resource +func Get(c client.Client, resource k8sruntime.Object, result interface{}, name, namespace string) error { + fun := func(gvk schema.GroupVersionKind, c client.Client) (map[string]interface{}, error) { + key := types.NamespacedName{ + Namespace: namespace, + Name: name, + } + obj, err := get(context.Background(), c, key, gvk) + if err != nil { + return nil, err + } + + return obj.(*unstructured.Unstructured).UnstructuredContent(), nil + } + + return getUnstructuredObj(c, resource, result, fun) +} + +// List list method for kubernetes resource +func List(c client.Client, options client.ListOption, resource k8sruntime.Object, result interface{}) error { + fun := func(gvk schema.GroupVersionKind, c client.Client) (map[string]interface{}, error) { + var obj k8sruntime.Object + obj, err := list(context.Background(), c, gvk, options) + if err != nil { + return nil, errors.Wrap(err, "fail to list resource") + } + + return obj.(*unstructured.UnstructuredList).UnstructuredContent(), nil + } + + return getUnstructuredObj(c, resource, result, fun) +} + +func list(ctx context.Context, a client.Client, gvk schema.GroupVersionKind, listOptions client.ListOption) (k8sruntime.Object, error) { + u := &unstructured.UnstructuredList{} + u.SetGroupVersionKind(gvk) + if err := a.List(ctx, u, listOptions); err != nil { + return nil, errors.Wrap(err, "fail to list resource") + } + + return u, nil +} + +func get(ctx context.Context, c client.Client, namespaceName types.NamespacedName, groupVersion schema.GroupVersionKind) (k8sruntime.Object, error) { + existing := &unstructured.Unstructured{} + existing.GetObjectKind().SetGroupVersionKind(groupVersion) + if err := c.Get(ctx, namespaceName, existing); err != nil { + return nil, errors.Wrap(err, "fail to get resource") + } + + return existing, nil +} + +func getUnstructuredObj(c client.Client, resource k8sruntime.Object, result interface{}, + hook func(schema.GroupVersionKind, client.Client) (map[string]interface{}, error)) error { + gvk, err := apiutil.GVKForObject(resource, Scheme) + if err != nil { + return errors.Wrap(err, "fail to get resource gvk") + } + + obj, err := hook(gvk, c) + if err != nil { + return errors.Wrap(err, "fail to get resource object") + } + + if err := k8sruntime.DefaultUnstructuredConverter.FromUnstructured(obj, result); err != nil { + return errors.Wrap(err, "fail to convert unstructured object to result") + } + + return nil +} diff --git a/pkg/apiserver/runtime/manager.go b/pkg/apiserver/runtime/manager.go new file mode 100644 index 000000000..2259047d1 --- /dev/null +++ b/pkg/apiserver/runtime/manager.go @@ -0,0 +1,37 @@ +/* +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 runtime + +import ( + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/pkg/utils/common" +) + +// GetClient returns a kube client for given kubeConfigData +func GetClient(kubeConfigData []byte) (client.Client, error) { + clientConfig, err := clientcmd.NewClientConfigFromBytes(kubeConfigData) + if err != nil { + return nil, err + } + restConfig, err := clientConfig.ClientConfig() + if err != nil { + return nil, err + } + return client.New(restConfig, client.Options{Scheme: common.Scheme}) +} diff --git a/pkg/apiserver/runtime/parse.go b/pkg/apiserver/runtime/parse.go new file mode 100644 index 000000000..15ead8783 --- /dev/null +++ b/pkg/apiserver/runtime/parse.go @@ -0,0 +1,138 @@ +/* +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 runtime + +import ( + "encoding/json" + + structpb "google.golang.org/protobuf/types/known/structpb" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + corecommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + + "github.com/oam-dev/kubevela/pkg/apiserver/proto/model" +) + +const ( + // DefaultAppNamespace default namespace for application + DefaultAppNamespace = "default" +) + +// ParseCoreApplication parse app info +func ParseCoreApplication(obj *model.Application) (oamcore.Application, error) { + var components []corecommon.ApplicationComponent + app := NewApplication(obj.Name, obj.Namespace) + for _, objComponent := range obj.GetComponents() { + properties, err := objComponent.Properties.MarshalJSON() + if err != nil { + return app, err + } + + var traits []corecommon.ApplicationTrait + for _, objTrait := range objComponent.Traits { + properties, err := objTrait.Properties.MarshalJSON() + if err != nil { + return app, err + } + trait := corecommon.ApplicationTrait{ + Type: objTrait.Type, + Properties: runtime.RawExtension{ + Raw: properties, + }, + } + + traits = append(traits, trait) + } + + component := corecommon.ApplicationComponent{ + Name: objComponent.Name, + Type: objComponent.Type, + Properties: runtime.RawExtension{ + Raw: properties, + }, + Traits: traits, + } + components = append(components, component) + } + app.Spec.Components = components + + return app, nil +} + +// NewApplication create new application +func NewApplication(name, namespace string) oamcore.Application { + if len(namespace) == 0 { + namespace = DefaultAppNamespace + } + + return oamcore.Application{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } +} + +// ParseApplicationYaml parse app in yaml +func ParseApplicationYaml(obj *oamcore.Application) (*model.Application, error) { + var components []*model.ComponentType + for _, objComponent := range obj.Spec.Components { + var comProperties structpb.Struct + comProper, err := objComponent.Properties.MarshalJSON() + if err != nil { + return nil, err + } + err = json.Unmarshal(comProper, &comProperties) + if err != nil { + return nil, err + } + var traits []*model.TraitType + for _, objTrait := range objComponent.Traits { + var traProperties structpb.Struct + traProper, err := objTrait.Properties.MarshalJSON() + if err != nil { + return nil, err + } + err = json.Unmarshal(traProper, &traProperties) + if err != nil { + return nil, err + } + trait := model.TraitType{ + Type: objTrait.Type, + Properties: &traProperties, + } + traits = append(traits, &trait) + } + comp := model.ComponentType{ + Name: objComponent.Name, + Type: objComponent.Type, + Namespace: obj.Namespace, + Properties: &comProperties, + Traits: traits, + } + components = append(components, &comp) + } + app := model.Application{ + Name: obj.Name, + Namespace: obj.Namespace, + UpdatedAt: obj.CreationTimestamp.Unix(), + Components: components, + } + return &app, nil +} diff --git a/pkg/apiserver/version/version.go b/pkg/apiserver/version/version.go new file mode 100644 index 000000000..03b7eff25 --- /dev/null +++ b/pkg/apiserver/version/version.go @@ -0,0 +1,62 @@ +/* +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 version + +import "fmt" + +const unspecified = "unspecified" + +var ( + gitCommit = unspecified + buildDate = unspecified + version = unspecified +) + +// Info for git information +type Info struct { + Version string + GitCommit string + BuildDate string +} + +// Get get info for git +func Get() Info { + i := Info{ + Version: version, + GitCommit: gitCommit, + BuildDate: buildDate, + } + if i.Version == "{version}" { + i.Version = unspecified + } + if i.GitCommit == "{gitCommit}" { + i.GitCommit = unspecified + } + if i.BuildDate == "{buildDate}" { + i.BuildDate = unspecified + } + return i +} + +func (i Info) String() string { + return fmt.Sprintf( + "Version: %s, GitCommit: %s, BuildDate: %s", + i.Version, + i.GitCommit, + i.BuildDate, + ) +}