Skip to content

Commit

Permalink
drop support for legacy (v0) projects
Browse files Browse the repository at this point in the history
This is a first in the series of PRs for cleaning up
the technical debt.
  • Loading branch information
droot committed Sep 27, 2018
1 parent 4edfc1f commit 883ca64
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 257 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ install:
-

script:
- TRACE=1 ./testv0.sh
- ./test_existing_projects.sh
- TRACE=1 ./testv1.sh

# TBD. Suppressing for now.
Expand Down
191 changes: 111 additions & 80 deletions cmd/kubebuilder/initproject/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,51 @@ limitations under the License.
package initproject

import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

"github.com/Masterminds/semver"
"github.com/kubernetes-sigs/kubebuilder/cmd/kubebuilder/util"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"sigs.k8s.io/controller-tools/pkg/scaffold"
"sigs.k8s.io/controller-tools/pkg/scaffold/input"
"sigs.k8s.io/controller-tools/pkg/scaffold/manager"
"sigs.k8s.io/controller-tools/pkg/scaffold/project"
)

type initOptions struct {
domain string
copyright string
bazel bool
controllerOnly bool
projectVersion string
projectOptions
}

func AddInit(cmd *cobra.Command) {
o := initOptions{}
o := projectOptions{}

initCmd := &cobra.Command{
Use: "init",
Short: "Initialize a new project",
Long: `Initialize a new project including vendor/ directory and Go package directories.`,
Example: `# Initialize project structure
kubebuilder init --domain mydomain
Long: `Initialize a new project including vendor/ directory and Go package directories.
Writes the following files:
- a boilerplate license file
- a PROJECT file with the domain and repo
- a Makefile to build the project
- a Gopkg.toml with project dependencies
- a Kustomization.yaml for customizating manifests
- a Patch file for customizing image for manager manifests
- a cmd/manager/main.go to run
project will prompt the user to run 'dep ensure' after writing the project files.
`,
Example: `# Scaffold a project using the apache2 license with "The Kubernetes authors" as owners
kubebuilder init --domain example.org --license apache2 --owner "The Kubernetes authors"
`,
Run: func(cmd *cobra.Command, args []string) {
o.runInitRepo()
o.RunInit()
},
}

v0comment := "Works only with project-version v0, "
initCmd.Flags().StringVar(&o.domain, "domain", "", "domain for the API groups")
initCmd.Flags().StringVar(&o.copyright, "copyright", filepath.Join("hack", "boilerplate.go.txt"), v0comment+"Location of copyright boilerplate file.")
initCmd.Flags().BoolVar(&o.bazel, "bazel", false, v0comment+"if true, setup Bazel workspace artifacts")
initCmd.Flags().BoolVar(&o.controllerOnly, "controller-only", false, v0comment+"if true, setup controller only")
initCmd.Flags().StringVar(&o.projectVersion, "project-version", "v1", "if set to v0, init project with kubebuilder legacy version")

initCmd.Flags().BoolVar(
&o.dep, "dep", true, "if specified, determines whether dep will be used.")
o.depFlag = initCmd.Flag("dep")
Expand All @@ -76,56 +75,114 @@ kubebuilder init --domain mydomain
cmd.AddCommand(initCmd)
}

func (o *initOptions) runInitRepo() {
type projectOptions struct {
prj *project.Project
bp *project.Boilerplate
gopkg *project.GopkgToml
mgr *manager.Cmd
dkr *manager.Dockerfile
dep bool
depFlag *flag.Flag
}

func (o *projectOptions) RunInit() {
checkGoVersion()

if !depExists() {
log.Fatalf("Dep is not installed. Follow steps at: https://golang.github.io/dep/docs/installation.html")
}

if o.projectVersion == "v1" {
if len(o.domain) != 0 {
o.prj.Domain = o.domain
}
o.RunInit()
if util.ProjectExist() {
fmt.Println("Failed to initialize project bacause project is already initialized")
return
}
// project and boilerplate must come before main so the boilerplate exists
s := &scaffold.Scaffold{
BoilerplateOptional: true,
ProjectOptional: true,
}

if len(o.domain) == 0 {
log.Fatal("Must specify --domain")
p, err := o.prj.GetInput()
if err != nil {
log.Fatal(err)
}
cr := util.GetCopyright(o.copyright)

fmt.Printf("Initializing project structure...\n")
if o.bazel {
createBazelWorkspace()
b, err := o.bp.GetInput()
if err != nil {
log.Fatal(err)
}
createControllerManager(cr)
//createInstaller(cr)
createAPIs(cr, o.domain)
//runCreateApiserver(cr)

pkgs := []string{
filepath.Join("hack"),
filepath.Join("pkg"),
filepath.Join("pkg", "controller"),
filepath.Join("pkg", "inject"),
//filepath.Join("pkg", "openapi"),

err = s.Execute(input.Options{ProjectPath: p.Path, BoilerplatePath: b.Path}, o.prj, o.bp)
if err != nil {
log.Fatal(err)
}

fmt.Printf("\t%s/\n", filepath.Join("pkg", "controller"))
for _, p := range pkgs {
createPackage(cr, p)
// default controller manager image name
imgName := "controller:latest"

s = &scaffold.Scaffold{}
err = s.Execute(input.Options{ProjectPath: p.Path, BoilerplatePath: b.Path},
o.gopkg,
o.mgr,
&project.Makefile{Image: imgName},
o.dkr,
&manager.APIs{},
&manager.Controller{},
&manager.Config{Image: imgName},
&project.GitIgnore{},
&project.Kustomize{},
&project.KustomizeImagePatch{})
if err != nil {
log.Fatal(err)
}

if !o.depFlag.Changed {
reader := bufio.NewReader(os.Stdin)
fmt.Println("Run `dep ensure` to fetch dependencies (Recommended) [y/n]?")
o.dep = util.Yesno(reader)
}
if o.dep {
c := exec.Command("dep", "ensure") // #nosec
c.Stderr = os.Stderr
c.Stdout = os.Stdout
fmt.Println(strings.Join(c.Args, " "))
if err := c.Run(); err != nil {
log.Fatal(err)
}

fmt.Println("Running make...")
c = exec.Command("make") // #nosec
c.Stderr = os.Stderr
c.Stdout = os.Stdout
fmt.Println(strings.Join(c.Args, " "))
if err := c.Run(); err != nil {
log.Fatal(err)
}
} else {
fmt.Println("Skipping `dep ensure`. Dependencies will not be fetched.")
}
doDockerfile()
doInject(cr)
doArgs(cr, o.controllerOnly)
RunVendorInstall(nil, []string{o.copyright})
createBoilerplate()
fmt.Printf("Next: Define a resource with:\n" +
"$ kubebuilder create resource\n")
"$ kubebuilder create api\n")
}

// projectForFlags registers flags for Project fields and returns the Project
func projectForFlags(f *flag.FlagSet) *project.Project {
p := &project.Project{}
f.StringVar(&p.Repo, "repo", "", "name of the github repo. "+
"defaults to the go package of the current working directory.")
f.StringVar(&p.Domain, "domain", "k8s.io", "domain for groups")
f.StringVar(&p.Version, "project-version", "1", "project version")
return p
}

// boilerplateForFlags registers flags for Boilerplate fields and returns the Boilerplate
func boilerplateForFlags(f *flag.FlagSet) *project.Boilerplate {
b := &project.Boilerplate{}
f.StringVar(&b.Path, "path", "", "path for boilerplate")
f.StringVar(&b.License, "license", "apache2", "license to use to boilerplate. Maybe one of apache2,none")
f.StringVar(&b.Owner, "owner", "", "Owner to add to the copyright")
return b
}
func checkGoVersion() {
cmd := exec.Command("go", "version")
out, err := cmd.Output()
Expand Down Expand Up @@ -165,29 +222,3 @@ type templateArgs struct {
Repo string
ControllerOnly bool
}

func versionCmp(v1 string, v2 string) int {
v1s := strings.Split(strings.Replace(v1, "go", "", 1), ".")
v2s := strings.Split(strings.Replace(v2, "go", "", 1), ".")
for i := 0; i < len(v1s) && i < len(v2s); i++ {
mv1, err1 := strconv.Atoi(v1s[i])
mv2, err2 := strconv.Atoi(v2s[i])
if err1 == nil && err2 == nil {
cmp := mv1 - mv2
if cmp > 0 {
return 1
} else if cmp < 0 {
return -1
}
} else {
log.Fatalf("Unexpected error comparing %v with %v", v1, v2)
}
}
if len(v1s) == len(v2s) {
return 0
} else if len(v1s) > len(v2s) {
return 1
} else {
return -1
}
}
Loading

0 comments on commit 883ca64

Please sign in to comment.