prometheus-adapter/vendor/github.com/googleapis/gnostic/generator/main.go
2017-06-26 19:23:05 +03:00

235 lines
7.2 KiB
Go

// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.
// generator generates Protocol Buffer models and support code from
// JSON Schemas. It is used to generate representations of the
// OpenAPI Specification and vendor and specification extensions
// that are added by third-party OpenAPI authors.
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"runtime"
"strings"
"github.com/googleapis/gnostic/jsonschema"
)
const LICENSE = "" +
"// Copyright 2017 Google Inc. All Rights Reserved.\n" +
"//\n" +
"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +
"// you may not use this file except in compliance with the License.\n" +
"// You may obtain a copy of the License at\n" +
"//\n" +
"// http://www.apache.org/licenses/LICENSE-2.0\n" +
"//\n" +
"// Unless required by applicable law or agreed to in writing, software\n" +
"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +
"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
"// See the License for the specific language governing permissions and\n" +
"// limitations under the License.\n"
func proto_options(packageName string) []ProtoOption {
return []ProtoOption{
ProtoOption{
Name: "java_multiple_files",
Value: "true",
Comment: "// This option lets the proto compiler generate Java code inside the package\n" +
"// name (see below) instead of inside an outer class. It creates a simpler\n" +
"// developer experience by reducing one-level of name nesting and be\n" +
"// consistent with most programming languages that don't support outer classes.",
},
ProtoOption{
Name: "java_outer_classname",
Value: "OpenAPIProto",
Comment: "// The Java outer classname should be the filename in UpperCamelCase. This\n" +
"// class is only used to hold proto descriptor, so developers don't need to\n" +
"// work with it directly.",
},
ProtoOption{
Name: "java_package",
Value: "org." + packageName,
Comment: "// The Java package name must be proto package name with proper prefix.",
},
ProtoOption{
Name: "objc_class_prefix",
Value: "OAS",
Comment: "// A reasonable prefix for the Objective-C symbols generated from the package.\n" +
"// It should at a minimum be 3 characters long, all uppercase, and convention\n" +
"// is to use an abbreviation of the package name. Something short, but\n" +
"// hopefully unique enough to not conflict with things that may come along in\n" +
"// the future. 'GPB' is reserved for the protocol buffer implementation itself.",
},
}
}
func GenerateOpenAPIModel(version string) error {
var input string
var filename string
var proto_packagename string
var extension_name string
switch version {
case "v2":
input = "openapi-2.0.json"
filename = "OpenAPIv2"
proto_packagename = "openapi.v2"
extension_name = "vendorExtension"
case "v3":
input = "openapi-3.0.json"
filename = "OpenAPIv3"
proto_packagename = "openapi.v3"
extension_name = "specificationExtension"
default:
return errors.New(fmt.Sprintf("Unknown OpenAPI version %s", version))
}
go_packagename := strings.Replace(proto_packagename, ".", "_", -1)
project_root := os.Getenv("GOPATH") + "/src/github.com/googleapis/gnostic/"
base_schema, err := jsonschema.NewSchemaFromFile(project_root + "jsonschema/schema.json")
if err != nil {
return err
}
base_schema.ResolveRefs()
base_schema.ResolveAllOfs()
openapi_schema, err := jsonschema.NewSchemaFromFile(project_root + filename + "/" + input)
if err != nil {
return err
}
openapi_schema.ResolveRefs()
openapi_schema.ResolveAllOfs()
// build a simplified model of the types described by the schema
cc := NewDomain(openapi_schema, version)
// generators will map these patterns to the associated property names
// these pattern names are a bit of a hack until we find a more automated way to obtain them
cc.PatternNames = map[string]string{
"^x-": extension_name,
// v2
"^/": "path",
"^([0-9]{3})$|^(default)$": "responseCode",
// v3
"^([0-9]{3})$": "responseCode",
"{property}": "property",
"{name}": "name",
"{expression}": "expression",
"/{path}": "path",
"{media-type}": "mediaType",
}
err = cc.Build()
if err != nil {
return err
}
if true {
log.Printf("Type Model:\n%s", cc.Description())
}
// ensure that the target directory exists
err = os.MkdirAll(filename, 0755)
if err != nil {
return err
}
// generate the protocol buffer description
proto := cc.GenerateProto(proto_packagename, LICENSE,
proto_options(go_packagename), []string{"google/protobuf/any.proto"})
proto_filename := project_root + filename + "/" + filename + ".proto"
err = ioutil.WriteFile(proto_filename, []byte(proto), 0644)
if err != nil {
return err
}
// generate the compiler
compiler := cc.GenerateCompiler(go_packagename, LICENSE, []string{
"fmt",
"gopkg.in/yaml.v2",
"strings",
"github.com/googleapis/gnostic/compiler",
})
go_filename := project_root + filename + "/" + filename + ".go"
err = ioutil.WriteFile(go_filename, []byte(compiler), 0644)
if err != nil {
return err
}
// format the compiler
return exec.Command(runtime.GOROOT()+"/bin/gofmt", "-w", go_filename).Run()
}
func usage() string {
return fmt.Sprintf(`
Usage: %s [OPTIONS]
Options:
--v2
Generate Protocol Buffer representation and support code for OpenAPI v2.
Files are read from and written to appropriate locations in the gnostic project directory.
--v3
Generate Protocol Buffer representation and support code for OpenAPI v3
Files are read from and written to appropriate locations in the gnostic project directory.
--extension EXTENSION_SCHEMA [EXTENSIONOPTIONS]
Generate a gnostic extension that reads a set of OpenAPI extensions.
EXTENSION_SCHEMA is the json schema for the OpenAPI extensions to be supported.
EXTENSION_OPTIONS
--out_dir=PATH: Location for writing extension models and support code.
`, path.Base(os.Args[0]))
}
func main() {
var openapi_version = ""
var generate_extensions = false
for i, arg := range os.Args {
if i == 0 {
continue // skip the tool name
}
if arg == "--v2" {
openapi_version = "v2"
} else if arg == "--v3" {
openapi_version = "v3"
} else if arg == "--extension" {
generate_extensions = true
break
} else {
fmt.Printf("Unknown option: %s.\n%s\n", arg, usage())
os.Exit(-1)
}
}
if openapi_version != "" {
err := GenerateOpenAPIModel(openapi_version)
if err != nil {
fmt.Printf("%+v\n", err)
}
} else if generate_extensions {
err := ProcessExtensionGenCommandline(usage())
if err != nil {
fmt.Printf("%+v\n", err)
}
} else {
fmt.Printf("%s\n", usage())
}
}