Skip to content
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

Add egbuilder #1058

Merged
merged 16 commits into from
Aug 15, 2023
Prev Previous commit
Next Next commit
finish 'init', 'add' command for egbuilder
  • Loading branch information
suchen-sci committed Jul 28, 2023
commit 0a14336d403b414c3db609863b21ee3e8e6711ae
144 changes: 144 additions & 0 deletions cmd/builder/command/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2017, MegaEase
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package command

import (
"errors"
"fmt"
"os"

"github.com/megaease/easegress/v2/cmd/builder/generate"
"github.com/megaease/easegress/v2/cmd/builder/utils"
"github.com/spf13/cobra"
)

var addFlags = &generate.ObjectConfig{}

func AddCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Add filter or resources to the project",
Args: addArgs,
Run: addRun,
}

cmd.Flags().StringSliceVar(&addFlags.Filters, "filters", []string{}, "filters to be generated")
cmd.Flags().StringSliceVar(&addFlags.Resources, "resources", []string{}, "resources to be generated")
return cmd
}

func addArgs(cmd *cobra.Command, args []string) error {
if len(args) != 0 {
return errors.New("add takes no arguments")
}
if (len(addFlags.Filters) == 0) && (len(addFlags.Resources) == 0) {
return errors.New("filters or resources is required")
}

for _, filter := range addFlags.Filters {
if !(utils.CapitalVariableName(filter)) {
return fmt.Errorf("filter %s is not a valid golang variable name with first letter upper case", filter)
}
}
for _, resource := range addFlags.Resources {
if !(utils.CapitalVariableName(resource)) {
return fmt.Errorf("resource %s is not a valid golang variable name with first letter upper case", resource)
}
}
return nil
}

func addRun(cmd *cobra.Command, args []string) {
cwd, err := os.Getwd()
if err != nil {
utils.ExitWithErrorf("get current working directory failed: %s", err.Error())
}
config, err := generate.ReadObjectConfigFile(cwd)
if err != nil {
utils.ExitWithError(err)
}
err = addCheckConfig(config)
if err != nil {
utils.ExitWithError(err)
}

// generate filters and resources dir and files.
err = utils.MakeDirs(cwd, addFlags.Filters, addFlags.Resources)
if err != nil {
utils.ExitWithError(err)
}
for _, f := range addFlags.Filters {
file := generate.CreateFilter(f)
err := file.Save(utils.GetFilterFileName(cwd, f))
if err != nil {
utils.ExitWithErrorf("add filter %s failed: %s", f, err.Error())
} else {
fmt.Printf("add filter %s successfully\n", f)
}
}
for _, r := range addFlags.Resources {
file := generate.CreateResource(r)
err := file.Save(utils.GetResourceFileName(cwd, r))
if err != nil {
utils.ExitWithErrorf("add resource %s failed: %s", r, err.Error())
} else {
fmt.Printf("add resource %s successfully\n", r)
}
}

config.Filters = append(config.Filters, addFlags.Filters...)
config.Resources = append(config.Resources, addFlags.Resources...)

// generate registry dir and file.
err = os.MkdirAll(utils.GetRegistryDir(cwd), os.ModePerm)
if err != nil {
utils.ExitWithErrorf("make directory %s failed: %s", utils.GetRegistryDir(cwd), err.Error())
}
file := generate.CreateRegistry(config)
err = file.Save(utils.GetRegistryFileName(cwd))
if err != nil {
utils.ExitWithErrorf("update registry file failed: %s", err.Error())
} else {
fmt.Println("update registry file successfully")
}
}

func addCheckConfig(config *generate.ObjectConfig) error {
arrToSet := func(arr []string) map[string]struct{} {
set := make(map[string]struct{})
for _, a := range arr {
set[a] = struct{}{}
}
return set
}

filters := arrToSet(config.Filters)
for _, f := range addFlags.Filters {
if _, ok := filters[f]; ok {
return fmt.Errorf("filter %s already exists", f)
}
}

resources := arrToSet(config.Resources)
for _, r := range addFlags.Resources {
if _, ok := resources[r]; ok {
return fmt.Errorf("resource %s already exists", r)
}
}
return nil
}
89 changes: 66 additions & 23 deletions cmd/builder/command/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,15 @@ import (
"errors"
"fmt"
"os"
"os/exec"

"github.com/megaease/easegress/cmd/builder/generate"
"github.com/megaease/easegress/cmd/builder/utils"
"github.com/megaease/easegress/v2/cmd/builder/generate"
"github.com/megaease/easegress/v2/cmd/builder/utils"
"github.com/spf13/cobra"
"golang.org/x/mod/module"
)

var initFlags = struct {
filters []string
resources []string
repo string
}{
filters: []string{},
resources: []string{},
repo: "",
}
var initFlags = &generate.ObjectConfig{}

func InitCmd() *cobra.Command {
cmd := &cobra.Command{
Expand All @@ -47,33 +40,33 @@ func InitCmd() *cobra.Command {
Run: initRun,
}

cmd.Flags().StringSliceVar(&initFlags.filters, "filters", []string{}, "filters to be generated")
cmd.Flags().StringSliceVar(&initFlags.resources, "resources", []string{}, "resources to be generated")
cmd.Flags().StringVar(&initFlags.repo, "repo", "", "pkg name of the repo")
cmd.Flags().StringSliceVar(&initFlags.Filters, "filters", []string{}, "filters to be generated")
cmd.Flags().StringSliceVar(&initFlags.Resources, "resources", []string{}, "resources to be generated")
cmd.Flags().StringVar(&initFlags.Repo, "repo", "", "pkg name of the repo")
return cmd
}

func initArgs(cmd *cobra.Command, args []string) error {
if len(args) != 0 {
return errors.New("init takes no arguments")
}
if len(initFlags.repo) == 0 {
if len(initFlags.Repo) == 0 {
return errors.New("repo is required")
}
if (len(initFlags.filters) == 0) && (len(initFlags.resources) == 0) {
if (len(initFlags.Filters) == 0) && (len(initFlags.Resources) == 0) {
return errors.New("filters or resources is required")
}

err := module.CheckPath(initFlags.repo)
err := module.CheckPath(initFlags.Repo)
if err != nil {
return fmt.Errorf("repo %s is not a valid path, %s", initFlags.repo, err.Error())
return fmt.Errorf("repo %s is not a valid path, %s", initFlags.Repo, err.Error())
}
for _, filter := range initFlags.filters {
for _, filter := range initFlags.Filters {
if !(utils.CapitalVariableName(filter)) {
return fmt.Errorf("filter %s is not a valid golang variable name with first letter upper case", filter)
}
}
for _, resource := range initFlags.resources {
for _, resource := range initFlags.Resources {
if !(utils.CapitalVariableName(resource)) {
return fmt.Errorf("resource %s is not a valid golang variable name with first letter upper case", resource)
}
Expand All @@ -94,23 +87,73 @@ func initRun(cmd *cobra.Command, args []string) {
utils.ExitWithErrorf("directory %s is not empty, please call init in an empty directory", cwd)
}

err = utils.MakeDirs(cwd, initFlags.filters, initFlags.resources)
initGenerateFiles(cmd, cwd)
initGenerateMod(cmd)
generate.WriteObjectConfigFile(cwd, initFlags)
}

func initGenerateFiles(_ *cobra.Command, cwd string) {
// generate filters and resources dir and files.
err := utils.MakeDirs(cwd, initFlags.Filters, initFlags.Resources)
if err != nil {
utils.ExitWithError(err)
}

for _, f := range initFlags.filters {
for _, f := range initFlags.Filters {
file := generate.CreateFilter(f)
err := file.Save(utils.GetFilterFileName(cwd, f))
if err != nil {
utils.ExitWithErrorf("generate filter %s failed: %s", f, err.Error())
} else {
fmt.Printf("generate filter %s success\n", f)
}
}
for _, r := range initFlags.resources {
for _, r := range initFlags.Resources {
file := generate.CreateResource(r)
err := file.Save(utils.GetResourceFileName(cwd, r))
if err != nil {
utils.ExitWithErrorf("generate resource %s failed: %s", r, err.Error())
} else {
fmt.Printf("generate resource %s success\n", r)
}
}

// generate registry dir and file.
err = os.MkdirAll(utils.GetRegistryDir(cwd), os.ModePerm)
if err != nil {
utils.ExitWithErrorf("make directory %s failed: %s", utils.GetRegistryDir(cwd), err.Error())
}
file := generate.CreateRegistry(initFlags)
err = file.Save(utils.GetRegistryFileName(cwd))
if err != nil {
utils.ExitWithErrorf("generate registry file failed: %s", err.Error())
} else {
fmt.Printf("generate registry file success\n")
}
}

func initGenerateMod(cmd *cobra.Command) {
// go mod init
modInitCmd := exec.Command(utils.GetGo(), "mod", "init", initFlags.Repo)
modInitCmd.Stderr = os.Stderr
out, err := modInitCmd.Output()
if err != nil {
utils.ExitWithErrorf("exec %v: %v: %s", cmd.Args, err, string(out))
}

// go get easegress
modGetCmd := exec.Command(utils.GetGo(), "get", utils.EG)
modGetCmd.Stderr = os.Stderr
out, err = modGetCmd.Output()
if err != nil {
utils.ExitWithErrorf("exec %v: %v: %s", cmd.Args, err, string(out))
}

// go mod tidy
modTidyCmd := exec.Command(utils.GetGo(), "mod", "tidy")
modTidyCmd.Stderr = os.Stderr
out, err = modTidyCmd.Output()
if err != nil {
utils.ExitWithErrorf("exec %v: %v: %s", cmd.Args, err, string(out))
}
}
57 changes: 47 additions & 10 deletions cmd/builder/generate/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,35 @@

package generate

import j "github.com/dave/jennifer/jen"
import (
"fmt"
"os"
"path"

j "github.com/dave/jennifer/jen"
"github.com/megaease/easegress/v2/pkg/util/codectool"
)

const (
KindName = "Kind"
SpecName = "Spec"
egFilters = "github.com/megaease/easegress/pkg/filters"
egContext = "github.com/megaease/easegress/pkg/context"
apiName = "API"
egSupervisor = "github.com/megaease/easegress/pkg/supervisor"
egAPI = "github.com/megaease/easegress/pkg/api"
egLogger = "github.com/megaease/easegress/pkg/logger"
yourCodeHere = "your code here\n"
objectConfigFileName = "egbuilder-config.yaml"
KindName = "Kind"
SpecName = "Spec"
apiName = "API"
yourCodeHere = "your code here\n"

egFilters = "github.com/megaease/easegress/v2/pkg/filters"
egContext = "github.com/megaease/easegress/v2/pkg/context"
egSupervisor = "github.com/megaease/easegress/v2/pkg/supervisor"
egAPI = "github.com/megaease/easegress/v2/pkg/api"
egLogger = "github.com/megaease/easegress/v2/pkg/logger"
)

type ObjectConfig struct {
Repo string `json:"repo"`
Resources []string `json:"resources"`
Filters []string `json:"filters"`
}

// Const is a const definition.
type Const struct {
Name string
Expand Down Expand Up @@ -90,3 +105,25 @@ func DefFunc(fn *Func) *j.Statement {
}
return res
}

func WriteObjectConfigFile(dir string, config *ObjectConfig) error {
fileName := path.Join(dir, objectConfigFileName)
yamlData, err := codectool.MarshalYAML(config)
if err != nil {
return fmt.Errorf("write object config file failed, %s", err.Error())
}
return os.WriteFile(fileName, yamlData, os.ModePerm)
}

func ReadObjectConfigFile(dir string) (*ObjectConfig, error) {
yamlData, err := os.ReadFile(path.Join(dir, objectConfigFileName))
if err != nil {
return nil, fmt.Errorf("read object config file %s failed, %s", objectConfigFileName, err.Error())
}
config := &ObjectConfig{}
err = codectool.UnmarshalYAML(yamlData, config)
if err != nil {
return nil, fmt.Errorf("unmarshal object config file %s failed, %s", objectConfigFileName, err.Error())
}
return config, nil
}
Loading