github.com/jenkins-x/jx-api@v0.0.24/cmd/codegen/app/generate_openapi.go (about) 1 package app 2 3 import ( 4 "go/build" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/jenkins-x/jx-logging/pkg/log" 10 11 "github.com/jenkins-x/jx-api/cmd/codegen/generator" 12 "github.com/jenkins-x/jx-api/cmd/codegen/util" 13 14 "github.com/pkg/errors" 15 16 "github.com/spf13/cobra" 17 ) 18 19 // CreateClientOpenAPIOptions the options for the create client openapi command 20 type CreateClientOpenAPIOptions struct { 21 GenerateOptions 22 Title string 23 Version string 24 ReferenceDocsVersion string 25 OpenAPIDependencies []string 26 OpenAPIOutputDir string 27 ModuleName string 28 } 29 30 var ( 31 createClientOpenAPILong = `This command code generates OpenAPI specs for 32 the specified custom resources. 33 ` 34 35 createClientOpenAPIExample = ` 36 # lets generate client docs 37 codegen openapi 38 --output-package=github.com/jenkins-x/jx-api/pkg/client \ 39 --input-package=github.com/jenkins-x/jx-api/pkg-apis \ 40 --group-with-version=jenkins.io:v1 41 --version=1.2.3 42 --title=Jenkins X 43 44 # You will normally want to add a target to your Makefile that looks like 45 generate-openapi: 46 codegen openapi 47 --output-package=github.com/jenkins-x/jx-api/pkg/client \ 48 --input-package=github.com/jenkins-x/jx-api/pkg/apis \ 49 --group-with-version=jenkins.io:v1 50 --version=${VERSION} 51 --title=${TITLE} 52 53 # and then call 54 make generate-openapi 55 ` 56 ) 57 58 // NewCmdCreateClientOpenAPI creates the command 59 func NewCmdCreateClientOpenAPI(genOpts GenerateOptions) *cobra.Command { 60 o := &CreateClientOpenAPIOptions{ 61 GenerateOptions: genOpts, 62 } 63 64 cobraCmd := &cobra.Command{ 65 Use: "openapi", 66 Short: "Creates OpenAPI specs for Custom Resources", 67 Long: createClientOpenAPILong, 68 Example: createClientOpenAPIExample, 69 70 Run: func(c *cobra.Command, args []string) { 71 o.Cmd = c 72 o.Args = args 73 err := o.Run() 74 util.CheckErr(err) 75 }, 76 } 77 78 wd, err := os.Getwd() 79 if err != nil { 80 log.Logger().Warnf("Error getting working directory for %v\n", err) 81 } 82 83 openAPIDependencies := []string{ 84 "k8s.io/apimachinery?modules:pkg/apis:meta:v1", 85 "k8s.io/apimachinery?modules:pkg/api:resource:", 86 "k8s.io/apimachinery?modules:pkg/util:intstr:", 87 "k8s.io/api?modules::batch:v1", 88 "k8s.io/api?modules::core:v1", 89 "k8s.io/api?modules::rbac:v1", 90 } 91 92 moduleName := strings.TrimPrefix(strings.TrimPrefix(wd, filepath.Join(build.Default.GOPATH, "src")), "/") 93 94 cobraCmd.Flags().StringVarP(&o.OutputBase, "output-base", "", wd, 95 "Output base directory, by default the current working directory") 96 cobraCmd.Flags().StringVarP(&o.BoilerplateFile, optionBoilerplateFile, "", "custom-boilerplate.go.txt", 97 "Custom boilerplate to add to all files if the file is missing it will be ignored") 98 cobraCmd.Flags().StringVarP(&o.InputBase, optionInputBase, "", wd, 99 "Input base (the root of module the OpenAPI is being generated for), by default the current working directory") 100 cobraCmd.Flags().StringVarP(&o.InputPackage, optionInputPackage, "i", "", "Input package (relative to input base), "+ 101 "must specify") 102 cobraCmd.Flags().StringVarP(&o.OutputPackage, optionOutputPackage, "o", "", "Output package, must specify") 103 cobraCmd.Flags().StringVarP(&o.Title, "title", "", "Jenkins X", "Title for OpenAPI, JSON Schema and HTML docs") 104 cobraCmd.Flags().StringVarP(&o.Version, "version", "", "", "Version for OpenAPI, JSON Schema and HTML docs") 105 cobraCmd.Flags().StringArrayVarP(&o.OpenAPIDependencies, "open-api-dependency", "", openAPIDependencies, 106 "Add <path?modules:package:group:apiVersion> dependencies for OpenAPI generation") 107 cobraCmd.Flags().StringVarP(&o.OpenAPIOutputDir, "openapi-output-directory", "", 108 "docs/apidocs", "Output directory for the OpenAPI specs, "+ 109 "relative to the output-base unless absolute. "+ 110 "OpenAPI spec JSON and YAML files are placed in openapi-spec sub directory.") 111 cobraCmd.Flags().StringArrayVarP(&o.GroupsWithVersions, optionGroupWithVersion, "g", make([]string, 0), 112 "group name:version (e.g. jenkins.io:v1) to generate, must specify at least once") 113 cobraCmd.Flags().StringVarP(&o.ModuleName, optionModuleName, "", moduleName, 114 "module name (e.g. github.com/jenkins-x/jx)") 115 cobraCmd.Flags().BoolVarP(&o.Global, global, "", false, "use the users GOPATH") 116 cobraCmd.Flags().StringVarP(&o.SemVer, optionSemVer, "", "", "semantic version to use in packages") 117 return cobraCmd 118 } 119 120 // Run implements this command 121 func (o *CreateClientOpenAPIOptions) Run() error { 122 var err error 123 o.BoilerplateFile, err = generator.GetBoilerplateFile(o.BoilerplateFile) 124 if err != nil { 125 return errors.Wrapf(err, "reading file %s specified by %s", o.BoilerplateFile, optionBoilerplateFile) 126 } 127 if o.InputPackage == "" { 128 return util.MissingOption(optionInputPackage) 129 } 130 if o.OutputPackage == "" { 131 return util.MissingOption(optionOutputPackage) 132 } 133 134 err = o.configure() 135 if err != nil { 136 return errors.Wrapf(err, "ensuring GOPATH is set correctly") 137 } 138 139 if len(o.GroupsWithVersions) < 1 { 140 return util.InvalidOptionf(optionGroupWithVersion, o.GroupsWithVersions, "must specify at least once") 141 } 142 143 cleanupFunc := func() {} 144 145 gopath := util.GoPath() 146 if !o.Global { 147 gopath, err = util.IsolatedGoPath() 148 if err != nil { 149 return errors.Wrapf(err, "getting isolated gopath") 150 } 151 cleanupFunc, err = util.BackupGoModAndGoSum() 152 if err != nil { 153 return errors.Wrapf(err, "backing up go.mod and go.sum") 154 } 155 } 156 157 defer cleanupFunc() 158 159 err = generator.InstallOpenApiGen(o.GeneratorVersion, gopath) 160 if err != nil { 161 return errors.Wrapf(err, "error installing kubernetes openapi tools") 162 } 163 164 if !filepath.IsAbs(o.OpenAPIOutputDir) { 165 o.OpenAPIOutputDir = filepath.Join(o.OutputBase, o.OpenAPIOutputDir) 166 } 167 168 log.Logger().Infof("generating Go code to %s in package %s from package %s\n", o.OutputBase, o.GoPathOutputPackage, o.InputPackage) 169 err = generator.GenerateOpenApi(o.GroupsWithVersions, o.InputPackage, o.GoPathOutputPackage, o.OutputPackage, 170 filepath.Join(build.Default.GOPATH, "src"), o.OpenAPIDependencies, o.InputBase, o.ModuleName, o.BoilerplateFile, gopath, o.SemVer) 171 if err != nil { 172 return errors.Wrapf(err, "generating openapi structs to %s", o.GoPathOutputPackage) 173 } 174 175 log.Logger().Infof("generating OpenAPI spec files to %s from package %s\n", o.OpenAPIOutputDir, filepath.Join(o.InputBase, 176 o.InputPackage)) 177 err = generator.GenerateSchema(o.OpenAPIOutputDir, o.OutputPackage, o.InputBase, o.Title, o.Version, gopath) 178 if err != nil { 179 return errors.Wrapf(err, "generating schema to %s", o.OpenAPIOutputDir) 180 } 181 return nil 182 }