-
Notifications
You must be signed in to change notification settings - Fork 1.8k
*: operator-sdk new command generates project skeleton #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e9e35b2
6d2a016
ceefdc1
c1373f7
31c32cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,61 +1,128 @@ | ||
| package generator | ||
|
|
||
| import ( | ||
| "errors" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| ) | ||
|
|
||
| const defaultFileMode = 0750 | ||
| const ( | ||
| defaultFileMode = 0750 | ||
| cmdDir = "cmd" | ||
| deployDir = "deploy" | ||
| configDir = "config" | ||
| tmpDir = "tmp" | ||
| buildDir = tmpDir + "/build" | ||
| codegenDir = tmpDir + "/codegen" | ||
| pkgDir = "pkg" | ||
| apisDir = pkgDir + "/apis" | ||
| stubDir = pkgDir + "/stub" | ||
| ) | ||
|
|
||
| type Generator struct { | ||
| apiGroup string | ||
| kind string | ||
| // projectName is name of the new operator application | ||
| // and is also the name of the base directory. | ||
| projectName string | ||
| } | ||
|
|
||
| // NewGenerator creates a new scaffold Generator. | ||
| func NewGenerator(apiGroup, kind, projectName string) *Generator { | ||
| return &Generator{apiGroup: apiGroup, kind: kind, projectName: projectName} | ||
| } | ||
|
|
||
| // Render generates the default project structure: | ||
| // | ||
| // ├── <projectName> | ||
| // │ ├── cmd | ||
| // │ │ └── <projectName> | ||
| // │ ├── config | ||
| // │ ├── deploy | ||
| // │ ├── pkg | ||
| // │ │ ├── apis | ||
| // │ │ │ └── <api-dir-name> // computed from apiDirName(apiGroup). | ||
| // │ │ │ └── <api-version> // computed from apiVersion(apiGroup). | ||
| // │ │ └── stub | ||
| // │ └── tmp | ||
| // │ ├── build | ||
| // │ └── codegen | ||
| func (g *Generator) Render() error { | ||
| gopath, ok := os.LookupEnv("GOPATH") | ||
| if !ok { | ||
| return errors.New("GOPATH must be set") | ||
| if err := g.renderCmd(); err != nil { | ||
| return err | ||
| } | ||
| projDir, ok := os.LookupEnv("PROJECT") // github.com/coreos/play | ||
| if !ok { | ||
| return errors.New("PROJECT must be set") | ||
| if err := g.renderConfig(); err != nil { | ||
| return err | ||
| } | ||
| if err := g.renderDeploy(); err != nil { | ||
| return err | ||
| } | ||
| apiGroup, ok := os.LookupEnv("APIGROUP") // play.coreos.com/v1alpha1 | ||
| if !ok { | ||
| return errors.New("PROJECT must be set") | ||
| if err := g.renderPkg(); err != nil { | ||
| return err | ||
| } | ||
| return g.renderTmp() | ||
| } | ||
|
|
||
| projDir = filepath.Join(gopath, "src", projDir) | ||
| err := os.MkdirAll(projDir, defaultFileMode) | ||
| if err != nil { | ||
| func (g *Generator) renderCmd() error { | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, cmdDir, g.projectName), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| // TODO render files. | ||
| return nil | ||
| } | ||
|
|
||
| programName := func() string { | ||
| splits := strings.Split(projDir, "/") | ||
| return splits[len(splits)-1] | ||
| }() | ||
| err = os.MkdirAll(filepath.Join(projDir, "cmd", programName), defaultFileMode) | ||
| if err != nil { | ||
| func (g *Generator) renderConfig() error { | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, configDir), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| // TODO render files. | ||
| return nil | ||
| } | ||
|
|
||
| // pkg/apis/ | ||
| groupName, apiVersion := func() (string, string) { | ||
| splits := strings.Split(apiGroup, "/") | ||
| return strings.Split(splits[0], ".")[0], splits[1] | ||
| }() | ||
| err = os.MkdirAll(filepath.Join(projDir, "pkg/apis", groupName, apiVersion), defaultFileMode) | ||
| if err != nil { | ||
| func (g *Generator) renderDeploy() error { | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, deployDir), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| // TODO render files. | ||
| return nil | ||
| } | ||
|
|
||
| // pkg/controller/ | ||
| err = os.MkdirAll(filepath.Join(projDir, "pkg/controller"), defaultFileMode) | ||
| if err != nil { | ||
| func (g *Generator) renderTmp() error { | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, buildDir), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, codegenDir), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| // TODO render files. | ||
| return nil | ||
| } | ||
|
|
||
| func (g *Generator) renderPkg() error { | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, apisDir, apiDirName(g.apiGroup), apiVersion(g.apiGroup)), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| if err := os.MkdirAll(filepath.Join(g.projectName, stubDir), defaultFileMode); err != nil { | ||
| return err | ||
| } | ||
| // TODO render files. | ||
| return nil | ||
| } | ||
|
|
||
| // apiVersion extracts api version from the given apiGroup. | ||
| func apiVersion(apiGroup string) string { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the APIVersion string is made up of So probably modify this func signature to Similarly use the name
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also just FYI this format is only for CRDs and apis under the rest path
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "v1" is actually legacy now. All new APIs will follow the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took a look of the api-group definition at here https://kubernetes.io/docs/reference/api-overview/#api-groups.
It seems like api-group is equivalent the distinction between
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with what @hasbro17 said. Let's change based on his suggestion. |
||
| return strings.Split(apiGroup, "/")[1] | ||
| } | ||
|
|
||
| // groupName extracts the group name from the givem apiGroup. | ||
| func groupName(apiGroup string) string { | ||
| return strings.Split(apiGroup, "/")[0] | ||
| } | ||
|
|
||
| // apiDirName extracts the name of api directory under ../apis/ from the apiGroup. | ||
| // it uses the first word separated with "." of the groupName as the api directory name. | ||
| // for example, | ||
| // apiDirName("app.example.com/v1alpha1") => "app". | ||
| func apiDirName(apiGroup string) string { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should do some error checking here on the format of the string, like if the user enters
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hasbro17 I have a todo in https://github.com/coreos/operator-sdk/blob/master/commands/operator-sdk/cmd/new.go#L65 for that. I think it is better to check input on top lvl so that the lower lvl code doesn't have to worry about it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fanminshi Can you follow this comment in a new PR?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hongchaodeng it is a TODO inside
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this as part of the Action Items. |
||
| return strings.Split(groupName(apiGroup), ".")[0] | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave space between non operator-sdk imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!