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