Skip to content

Commit

Permalink
Merge pull request kubevirt#545 from rmohr/openapi-generate-integration
Browse files Browse the repository at this point in the history
Integrate openapi-spec generation with generate target
  • Loading branch information
rmohr authored Nov 7, 2017
2 parents cb49b67 + 296301d commit b6c957e
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 171 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ cmd/virt-launcher/virt-launcher*
cmd/virt-handler/virt-handler*
cmd/virt-api/virt-api*
cmd/virtctl/virtctl*
tools/openapispec/openapispec
manifests/*.yaml
**/bin
bin/*
Expand Down
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,15 @@ script:
- make fmt
- if git diff --name-only | grep 'generated.*.go'; then echo "Content of generated
files changed. Please regenerate and commit them."; false; fi
- if git diff --name-only | grep 'swagger.json' ; then echo "Content of generated
files changed. Please regenerate and commit them." ; false ; fi
- if diff <(git grep -c '') <(git grep -cI '') | egrep -v 'docs/.*\.png|swagger-ui'
| grep '^<'; then echo "Binary files are present in git repostory."; false; fi
- make check
- make build
- if [[ $TRAVIS_REPO_SLUG == "kubevirt/kubevirt" ]]; then $HOME/gopath/bin/goveralls
-service=travis-ci -package=./pkg/... -ignore=$(find -name generated_mock*.go -printf
"%P\n" | paste -d, -s) ; else make test; fi
- make generate-openapi-spec
- if git diff --name-only | grep 'swagger.json' ; then echo "The OpenAPI Specification
was changed. Please run `make generate-openapi-spec` and commit it." ; false ; fi

cache:
directories:
Expand Down
12 changes: 4 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ HASH := md5sum

all: build manifests

generate:
generate: sync
find pkg/ -name "*generated*.go" -exec rm {} -f \;
./hack/build-go.sh generate ${WHAT}
goimports -w -local kubevirt.io cmd/ pkg/ tests/
./hack/bootstrap-ginkgo.sh
(cd tools/openapispec/ && go build)
tools/openapispec/openapispec --dump-api-spec-path api/openapi-spec/swagger.json

build: checksync fmt vet compile

Expand All @@ -27,16 +29,10 @@ test: build
functest:
./hack/build-go.sh functest ${WHAT}

generate-openapi-spec: build
echo -e "apiVersion: v1\nclusters:\n- cluster:\n server: https://127.0.0.1:6443\nkind: Config\n" > .test.kubeconfig
./cmd/virt-api/virt-api \
--kubeconfig .test.kubeconfig \
--dump-api-spec --dump-api-spec-path api/openapi-spec/swagger.json
rm -f .test.kubeconfig

clean:
./hack/build-go.sh clean ${WHAT}
rm ./bin -rf
rm tools/openapispec/openapispec -rf

distclean: clean
rm -rf vendor/
Expand Down
159 changes: 4 additions & 155 deletions cmd/virt-api/virt-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,175 +20,24 @@
package main

import (
"encoding/json"
"flag"
"io/ioutil"
"log"
"net/http"

"github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
kithttp "github.com/go-kit/kit/transport/http"
openapispec "github.com/go-openapi/spec"
"github.com/spf13/pflag"
"golang.org/x/net/context"
"k8s.io/apimachinery/pkg/runtime/schema"

"kubevirt.io/kubevirt/pkg/api/v1"
"kubevirt.io/kubevirt/pkg/healthz"
"kubevirt.io/kubevirt/pkg/kubecli"
klog "kubevirt.io/kubevirt/pkg/log"
mime "kubevirt.io/kubevirt/pkg/rest"
"kubevirt.io/kubevirt/pkg/rest/endpoints"
"kubevirt.io/kubevirt/pkg/rest/filter"
"kubevirt.io/kubevirt/pkg/service"
"kubevirt.io/kubevirt/pkg/virt-api/rest"
"kubevirt.io/kubevirt/pkg/virt-api"
)

type virtAPIApp struct {
Service *service.Service
SwaggerUI string
}

func newVirtAPIApp(host *string, port *int, swaggerUI *string) *virtAPIApp {
return &virtAPIApp{
Service: service.NewService("virt-api", host, port),
SwaggerUI: *swaggerUI,
}
}

func (app *virtAPIApp) Compose() {
ctx := context.Background()
vmGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachines"}
migrationGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "migrations"}
vmrsGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: "virtualmachinereplicasets"}

ws, err := rest.GroupVersionProxyBase(ctx, v1.GroupVersion)
if err != nil {
log.Fatal(err)
}

ws, err = rest.GenericResourceProxy(ws, ctx, vmGVR, &v1.VirtualMachine{}, v1.VirtualMachineGroupVersionKind.Kind, &v1.VirtualMachineList{})
if err != nil {
log.Fatal(err)
}

ws, err = rest.GenericResourceProxy(ws, ctx, migrationGVR, &v1.Migration{}, v1.MigrationGroupVersionKind.Kind, &v1.MigrationList{})
if err != nil {
log.Fatal(err)
}

ws, err = rest.GenericResourceProxy(ws, ctx, vmrsGVR, &v1.VirtualMachineReplicaSet{}, v1.VMReplicaSetGroupVersionKind.Kind, &v1.VirtualMachineReplicaSetList{})
if err != nil {
log.Fatal(err)
}

virtCli, err := kubecli.GetKubevirtClient()
if err != nil {
log.Fatal(err)
}

// TODO, allow Encoder and Decoders per type and combine the endpoint logic
spice := endpoints.MakeGoRestfulWrapper(endpoints.NewHandlerBuilder().Get().
Endpoint(rest.NewSpiceEndpoint(virtCli.RestClient(), vmGVR)).Encoder(
endpoints.NewMimeTypeAwareEncoder(endpoints.NewEncodeINIResponse(http.StatusOK),
map[string]kithttp.EncodeResponseFunc{
mime.MIME_INI: endpoints.NewEncodeINIResponse(http.StatusOK),
mime.MIME_JSON: endpoints.NewEncodeJsonResponse(http.StatusOK),
mime.MIME_YAML: endpoints.NewEncodeYamlResponse(http.StatusOK),
})).Build(ctx))

ws.Route(ws.GET(rest.ResourcePath(vmGVR)+rest.SubResourcePath("spice")).
To(spice).Produces(mime.MIME_INI, mime.MIME_JSON, mime.MIME_YAML).
Param(rest.NamespaceParam(ws)).Param(rest.NameParam(ws)).
Operation("spice").
Doc("Returns a remote-viewer configuration file. Run `man 1 remote-viewer` to learn more about the configuration format."))

ws.Route(ws.GET(rest.ResourcePath(vmGVR) + rest.SubResourcePath("console")).
To(rest.NewConsoleResource(virtCli, virtCli.CoreV1()).Console).
Param(restful.QueryParameter("console", "Name of the serial console to connect to")).
Param(rest.NamespaceParam(ws)).Param(rest.NameParam(ws)).
Operation("console").
Doc("Open a websocket connection to a serial console on the specified VM."))

restful.Add(ws)

ws.Route(ws.GET("/healthz").To(healthz.KubeConnectionHealthzFunc).Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON).Doc("Health endpoint"))
ws, err = rest.ResourceProxyAutodiscovery(ctx, vmGVR)
if err != nil {
log.Fatal(err)
}

restful.Add(ws)

restful.Filter(filter.RequestLoggingFilter())
restful.Filter(restful.OPTIONSFilter())
}

func (app *virtAPIApp) ConfigureOpenAPIService() {
restful.DefaultContainer.Add(restfulspec.NewOpenAPIService(createOpenAPIConfig()))
http.Handle("/swagger-ui/", http.StripPrefix("/swagger-ui/", http.FileServer(http.Dir(app.SwaggerUI))))
}

func createOpenAPIConfig() restfulspec.Config {
return restfulspec.Config{
WebServices: restful.RegisteredWebServices(),
WebServicesURL: "http://localhost:8183",
APIPath: "/swaggerapi",
PostBuildSwaggerObjectHandler: addInfoToSwaggerObject,
}
}

func addInfoToSwaggerObject(swo *openapispec.Swagger) {
swo.Info = &openapispec.Info{
InfoProps: openapispec.InfoProps{
Title: "KubeVirt API, ",
Description: "This is KubeVirt API an add-on for Kubernetes.",
Contact: &openapispec.ContactInfo{
Name: "kubevirt-dev",
Email: "[email protected]",
URL: "https://github.com/kubevirt/kubevirt",
},
License: &openapispec.License{
Name: "Apache 2.0",
URL: "https://www.apache.org/licenses/LICENSE-2.0",
},
},
}
}

func (app *virtAPIApp) Run() {
log.Fatal(http.ListenAndServe(app.Service.Address(), nil))
}

func dumpOpenApiSpec(dumppath *string) {
openapispec := restfulspec.BuildSwagger(createOpenAPIConfig())
data, err := json.MarshalIndent(openapispec, " ", " ")
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile(*dumppath, data, 0644)
if err != nil {
log.Fatal(err)
}
}

func main() {
klog.InitializeLogging("virt-api")
swaggerui := flag.String("swagger-ui", "third_party/swagger-ui", "swagger-ui location")
host := flag.String("listen", "0.0.0.0", "Address and port where to listen on")
port := flag.Int("port", 8183, "Port to listen on")
dumpapispec := flag.Bool("dump-api-spec", false, "Dump OpenApi spec, and exit immediately.")
dumpapispecpath := flag.String("dump-api-spec-path", "openapi.json", "Path to OpenApi dump.")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()

app := newVirtAPIApp(host, port, swaggerui)
app := virt_api.NewVirtAPIApp(*host, *port, *swaggerui)
app.Compose()
if *dumpapispec == true {
dumpOpenApiSpec(dumpapispecpath)
} else {
app.ConfigureOpenAPIService()
app.Run()
}
app.ConfigureOpenAPIService()
app.Run()
}
2 changes: 1 addition & 1 deletion cmd/virt-handler/virt-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func newVirtHandlerApp(host *string, port *int, hostOverride *string, libvirtUri
}

return &virtHandlerApp{
Service: service.NewService("virt-handler", host, port),
Service: service.NewService("virt-handler", *host, *port),
HostOverride: *hostOverride,
LibvirtUri: *libvirtUri,
VirtShareDir: *virtShareDir,
Expand Down
2 changes: 1 addition & 1 deletion cmd/virt-manifest/virt-manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type virtManifestApp struct {

func newVirtManifestApp(host *string, port *int, libvirtUri *string) *virtManifestApp {
return &virtManifestApp{
Service: service.NewService("virt-manifest", host, port),
Service: service.NewService("virt-manifest", *host, *port),
LibvirtUri: *libvirtUri,
}
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ type Service struct {
Port string
}

func NewService(name string, host *string, port *int) *Service {
func NewService(name string, host string, port int) *Service {
return &Service{
Name: name,
Host: *host,
Port: strconv.Itoa(*port),
Host: host,
Port: strconv.Itoa(port),
}
}

Expand Down
Loading

0 comments on commit b6c957e

Please sign in to comment.