Skip to content

Commit

Permalink
Integrate openapi-spec generation with generate target
Browse files Browse the repository at this point in the history
Remove the need of an extra openapi generate build target and generate
everything as part of the normal "make generate" flow.

Signed-off-by: Roman Mohr <[email protected]>
  • Loading branch information
rmohr committed Nov 6, 2017
1 parent cb49b67 commit 296301d
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 296301d

Please sign in to comment.