github.com/mkimuram/operator-sdk@v0.7.1-0.20190410172100-52ad33a4bda0/cmd/operator-sdk/add/api.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package add 16 17 import ( 18 "fmt" 19 20 "github.com/operator-framework/operator-sdk/cmd/operator-sdk/internal/genutil" 21 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold" 22 "github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input" 23 "github.com/operator-framework/operator-sdk/internal/util/projutil" 24 25 log "github.com/sirupsen/logrus" 26 "github.com/spf13/cobra" 27 ) 28 29 var ( 30 apiVersion string 31 kind string 32 headerFile string 33 ) 34 35 func newAddApiCmd() *cobra.Command { 36 apiCmd := &cobra.Command{ 37 Use: "api", 38 Short: "Adds a new api definition under pkg/apis", 39 Long: `operator-sdk add api --kind=<kind> --api-version=<group/version> creates the 40 api definition for a new custom resource under pkg/apis. This command must be 41 run from the project root directory. If the api already exists at 42 pkg/apis/<group>/<version> then the command will not overwrite and return an 43 error. 44 45 This command runs Kubernetes deepcopy and OpenAPI V3 generators on tagged 46 types in all paths under pkg/apis. Go code is generated under 47 pkg/apis/<group>/<version>/zz_generated.{deepcopy,openapi}.go. CRD's are 48 generated, or updated if they exist for a particular group + version + kind, 49 under deploy/crds/<group>_<version>_<kind>_crd.yaml; OpenAPI V3 validation YAML 50 is generated as a 'validation' object. 51 52 Example: 53 $ operator-sdk add api --api-version=app.example.com/v1alpha1 --kind=AppService 54 $ tree pkg/apis 55 pkg/apis/ 56 ├── addtoscheme_app_appservice.go 57 ├── apis.go 58 └── app 59 └── v1alpha1 60 ├── doc.go 61 ├── register.go 62 ├── appservice_types.go 63 ├── zz_generated.deepcopy.go 64 ├── zz_generated.openapi.go 65 $ tree deploy/crds 66 ├── deploy/crds/app_v1alpha1_appservice_cr.yaml 67 ├── deploy/crds/app_v1alpha1_appservice_crd.yaml 68 `, 69 RunE: apiRun, 70 } 71 72 apiCmd.Flags().StringVar(&apiVersion, "api-version", "", "Kubernetes APIVersion that has a format of $GROUP_NAME/$VERSION (e.g app.example.com/v1alpha1)") 73 if err := apiCmd.MarkFlagRequired("api-version"); err != nil { 74 log.Fatalf("Failed to mark `api-version` flag for `add api` subcommand as required") 75 } 76 apiCmd.Flags().StringVar(&kind, "kind", "", "Kubernetes resource Kind name. (e.g AppService)") 77 if err := apiCmd.MarkFlagRequired("kind"); err != nil { 78 log.Fatalf("Failed to mark `kind` flag for `add api` subcommand as required") 79 } 80 apiCmd.Flags().StringVar(&headerFile, "header-file", "", "Path to file containing headers for generated files.") 81 82 return apiCmd 83 } 84 85 func apiRun(cmd *cobra.Command, args []string) error { 86 projutil.MustInProjectRoot() 87 88 // Only Go projects can add apis. 89 if err := projutil.CheckGoProjectCmd(cmd); err != nil { 90 return err 91 } 92 93 log.Infof("Generating api version %s for kind %s.", apiVersion, kind) 94 95 // Create and validate new resource. 96 r, err := scaffold.NewResource(apiVersion, kind) 97 if err != nil { 98 return err 99 } 100 101 absProjectPath := projutil.MustGetwd() 102 103 cfg := &input.Config{ 104 Repo: projutil.CheckAndGetProjectGoPkg(), 105 AbsProjectPath: absProjectPath, 106 } 107 108 s := &scaffold.Scaffold{} 109 err = s.Execute(cfg, 110 &scaffold.Types{Resource: r}, 111 &scaffold.AddToScheme{Resource: r}, 112 &scaffold.Register{Resource: r}, 113 &scaffold.Doc{Resource: r}, 114 &scaffold.CR{Resource: r}, 115 &scaffold.CRD{Resource: r, IsOperatorGo: projutil.IsOperatorGo()}, 116 ) 117 if err != nil { 118 return fmt.Errorf("api scaffold failed: (%v)", err) 119 } 120 121 // update deploy/role.yaml for the given resource r. 122 if err := scaffold.UpdateRoleForResource(r, absProjectPath); err != nil { 123 return fmt.Errorf("failed to update the RBAC manifest for the resource (%v, %v): (%v)", r.APIVersion, r.Kind, err) 124 } 125 126 // Run k8s codegen for deepcopy 127 if err := genutil.K8sCodegen(headerFile); err != nil { 128 return err 129 } 130 131 // Generate a validation spec for the new CRD. 132 if err := genutil.OpenAPIGen(headerFile); err != nil { 133 return err 134 } 135 136 log.Info("API generation complete.") 137 return nil 138 }