Skip to content

Commit cef5f4c

Browse files
authored
✨re-scaffold the project with a new command (#3431)
1 parent 60ac4a7 commit cef5f4c

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

pkg/cli/alpha.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"strings"
2222

2323
"github.com/spf13/cobra"
24+
"sigs.k8s.io/kubebuilder/v3/pkg/cli/alpha"
2425
)
2526

2627
const (
@@ -29,6 +30,7 @@ const (
2930

3031
var alphaCommands = []*cobra.Command{
3132
newAlphaCommand(),
33+
alpha.NewScaffoldCommand(),
3234
}
3335

3436
func newAlphaCommand() *cobra.Command {

pkg/cli/alpha/generate.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
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+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package alpha
15+
16+
import (
17+
"log"
18+
19+
"github.com/spf13/cobra"
20+
"sigs.k8s.io/kubebuilder/v3/pkg/rescaffold"
21+
)
22+
23+
// NewScaffoldCommand return a new scaffold command
24+
func NewScaffoldCommand() *cobra.Command {
25+
opts := rescaffold.MigrateOptions{}
26+
scaffoldCmd := &cobra.Command{
27+
Use: "generate",
28+
Short: "Re-scaffold an existing Kuberbuilder project",
29+
Long: `It's an experimental feature that has the purpose of re-scaffolding the whole project from the scratch
30+
using the current version of KubeBuilder binary available.
31+
# make sure the PROJECT file is in the 'input-dir' argument, the default is the current directory.
32+
$ kubebuilder alpha generate --input-dir="./test" --output-dir="./my-output"
33+
Then we will re-scaffold the project by Kubebuilder in the directory specified by 'output-dir'.
34+
`,
35+
PreRunE: func(cmd *cobra.Command, _ []string) error {
36+
return opts.Validate()
37+
},
38+
Run: func(cmd *cobra.Command, args []string) {
39+
if err := opts.Rescaffold(); err != nil {
40+
log.Fatalf("Failed to rescaffold %s", err)
41+
}
42+
},
43+
}
44+
scaffoldCmd.Flags().StringVar(&opts.InputDir, "input-dir", "",
45+
"path to a Kubebuilder project file if not in the current working directory")
46+
scaffoldCmd.Flags().StringVar(&opts.OutputDir, "output-dir", "",
47+
"path to output the scaffolding. defaults a directory in the current working directory")
48+
49+
return scaffoldCmd
50+
}

pkg/rescaffold/migrate.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
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+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package rescaffold
15+
16+
import (
17+
"fmt"
18+
"log"
19+
"os"
20+
"os/exec"
21+
22+
"github.com/spf13/afero"
23+
"sigs.k8s.io/kubebuilder/v3/pkg/config/store"
24+
"sigs.k8s.io/kubebuilder/v3/pkg/config/store/yaml"
25+
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
26+
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
27+
)
28+
29+
type MigrateOptions struct {
30+
InputDir string
31+
OutputDir string
32+
}
33+
34+
const DefaultOutputDir = "output-dir"
35+
36+
func (opts *MigrateOptions) Rescaffold() error {
37+
config := yaml.New(machinery.Filesystem{FS: afero.NewOsFs()})
38+
if err := config.LoadFrom(opts.InputDir); err != nil {
39+
log.Fatal(err)
40+
}
41+
// create output directory
42+
// nolint: gosec
43+
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
44+
log.Fatal(err)
45+
}
46+
// use the new directory to set up the new project
47+
if err := os.Chdir(opts.OutputDir); err != nil {
48+
log.Fatal(err)
49+
}
50+
// init project with plugins
51+
if err := kubebuilderInit(config); err != nil {
52+
log.Fatal(err)
53+
}
54+
return nil
55+
}
56+
57+
func (opts *MigrateOptions) Validate() error {
58+
cwd, err := os.Getwd()
59+
if err != nil {
60+
log.Fatal(err)
61+
}
62+
// get PROJECT path from command args
63+
inputPath, err := getInputPath(cwd, opts.InputDir)
64+
if err != nil {
65+
log.Fatal(err)
66+
}
67+
opts.InputDir = inputPath
68+
// get output path from command args
69+
opts.OutputDir, err = getOutputPath(cwd, opts.OutputDir)
70+
if err != nil {
71+
log.Fatal(err)
72+
}
73+
// check whether the kubebuilder binary is accessible
74+
_, err = exec.LookPath("kubebuilder")
75+
return err
76+
}
77+
78+
func getInputPath(currentWorkingDirectory string, inputPath string) (string, error) {
79+
if inputPath == "" {
80+
inputPath = currentWorkingDirectory
81+
}
82+
projectPath := fmt.Sprintf("%s/%s", inputPath, yaml.DefaultPath)
83+
if _, err := os.Stat(projectPath); os.IsNotExist(err) {
84+
return "", fmt.Errorf("PROJECT path: %s does not exist. %v", projectPath, err)
85+
}
86+
return projectPath, nil
87+
}
88+
89+
func getOutputPath(currentWorkingDirectory, outputPath string) (string, error) {
90+
if outputPath == "" {
91+
outputPath = fmt.Sprintf("%s/%s", currentWorkingDirectory, DefaultOutputDir)
92+
}
93+
_, err := os.Stat(outputPath)
94+
if err == nil {
95+
return "", fmt.Errorf("Output path: %s already exists. %v", outputPath, err)
96+
}
97+
if os.IsNotExist(err) {
98+
return outputPath, nil
99+
}
100+
return "", err
101+
}
102+
103+
func kubebuilderInit(_ store.Store) error {
104+
var args []string
105+
args = append(args, "init")
106+
return util.RunCmd("kubebuilder init", "kubebuilder", args...)
107+
}

0 commit comments

Comments
 (0)