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

Support mod feature #43

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ vendor/

.idea
*.iml
.vscode/
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ GoKit Cli needs to be installed using `go get` and `go install` so `Go` is a req
- [Generate the service](#generate-the-service)
- [Generate the client library](#generate-the-client-library)
- [Generate new middlewares](#generate-new-middleware)
- [Mod feature support](#mod-feature-support)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- [Mod feature support](#mod-feature-support)
- [Module support](#mod-feature-support)

- [Enable docker integration](#enable-docker-integration)

# Installation
Expand Down Expand Up @@ -109,6 +110,15 @@ kit g m hi -s hello
kit g m hi -s hello -e # if you want to add endpoint middleware
```
The only thing left to do is add your middleware logic and wire the middleware with your service/endpoint.
# Mod feature support
If you want to create project outside the gopath, you could use --mod_module flag to set your module name when you are creating a new service. And if you want to use it under your gopath, please make sure your go version >= 1.3, or
GO111MODULE is set on.
For example:
```bash
kit n s hello --mod_mudole hello
kit g s hello --dmw
```
The command could create the go.mod file with the module name. And when you are generating the service and the client library, the module name in the go.mod file could be autodetected.
# Enable docker integration

```bash
Expand Down
23 changes: 23 additions & 0 deletions cmd/g_service.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package cmd

import (
"os"
"path/filepath"
"strings"

"github.com/kujtimiihoxha/kit/generator"
"github.com/kujtimiihoxha/kit/utils"
GrantZheng marked this conversation as resolved.
Show resolved Hide resolved
"github.com/sirupsen/logrus"
"github.com/spf13/afero"
GrantZheng marked this conversation as resolved.
Show resolved Hide resolved
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand All @@ -13,6 +19,23 @@ var initserviceCmd = &cobra.Command{
Short: "Initiate a service",
Aliases: []string{"s"},
Run: func(cmd *cobra.Command, args []string) {
gosrc := strings.TrimSuffix(utils.GetGOPATH(), afero.FilePathSeparator) + afero.FilePathSeparator + "src" + afero.FilePathSeparator
pwd, err := os.Getwd()
if err != nil {
logrus.Error(err)
return
}
gosrc, err = filepath.EvalSymlinks(gosrc)
if err != nil {
logrus.Error(err)
return
}
pwd, err = filepath.EvalSymlinks(pwd)
if err != nil {
logrus.Error(err)
return
}

if len(args) == 0 {
logrus.Error("You must provide a name for the service")
return
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func init() {
RootCmd.PersistentFlags().BoolP("debug", "d", false, "If you want to se the debug logs.")
RootCmd.PersistentFlags().BoolP("force", "f", false, "Force overide existing files without asking.")
RootCmd.PersistentFlags().StringP("folder", "b", "", "If you want to specify the base folder of the project.")

viper.BindPFlag("gk_folder", RootCmd.PersistentFlags().Lookup("folder"))
viper.BindPFlag("gk_force", RootCmd.PersistentFlags().Lookup("force"))
viper.BindPFlag("gk_debug", RootCmd.PersistentFlags().Lookup("debug"))
Expand Down
34 changes: 34 additions & 0 deletions cmd/service.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,48 @@
package cmd

import (
"os"
"path/filepath"
"strings"

"github.com/kujtimiihoxha/kit/generator"
"github.com/kujtimiihoxha/kit/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var serviceCmd = &cobra.Command{
Use: "service",
Short: "Generate new service",
Aliases: []string{"s"},
Run: func(cmd *cobra.Command, args []string) {
gosrc := strings.TrimSuffix(utils.GetGOPATH(), afero.FilePathSeparator) + afero.FilePathSeparator + "src" + afero.FilePathSeparator
pwd, err := os.Getwd()
if err != nil {
logrus.Error(err)
return
}
gosrc, err = filepath.EvalSymlinks(gosrc)
if err != nil {
logrus.Error(err)
return
}
pwd, err = filepath.EvalSymlinks(pwd)
if err != nil {
logrus.Error(err)
return
}

var modPath string
modPath = viper.GetString("n_s_mod_module")

if modPath == "" && !strings.HasPrefix(pwd, gosrc) {
logrus.Error("The project must be in the $GOPATH/src folder for the generator to work, or generate project with --mod_module flag")
return
}

if len(args) == 0 {
logrus.Error("You must provide a name for the service")
return
Expand All @@ -24,4 +56,6 @@ var serviceCmd = &cobra.Command{

func init() {
newCmd.AddCommand(serviceCmd)
serviceCmd.Flags().StringP("mod_module", "m", "", "The mod module name that you plan to set in the project")
viper.BindPFlag("n_s_mod_module", serviceCmd.Flags().Lookup("mod_module"))
}
32 changes: 18 additions & 14 deletions generator/generate_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -1683,35 +1683,39 @@ func (g *generateCmd) generateRun() (*PartialGenerator, error) {
jen.Lit("URL"),
jen.Id("*zipkinURL"),
),
jen.List(jen.Id("collector"), jen.Err()).Op(":=").Qual(
"github.com/openzipkin/zipkin-go-opentracing", "NewHTTPCollector",
jen.Id("reporter").Op(":=").Qual(
"github.com/openzipkin/zipkin-go/reporter/http", "NewReporter",
).Call(jen.Id("*zipkinURL")),
jen.Defer().Id("reporter").Dot("Close").Call(),
jen.List(jen.Id("endpoint"), jen.Id("err")).Op(":=").Qual(
"github.com/openzipkin/zipkin-go", "NewEndpoint",
).Call(
jen.Lit(g.name),
jen.Lit("localhost:80"),
),
jen.If(jen.Err().Op("!=").Nil()).Block(
jen.Id("logger").Dot("Log").Call(
jen.Lit("err"),
jen.Id("err"),
),
jen.Qual("os", "Exit").Call(jen.Lit(1)),
),
jen.Defer().Id("collector").Dot("Close").Call(),
jen.Id("recorder").Op(":=").Qual(
"github.com/openzipkin/zipkin-go-opentracing", "NewRecorder",
).Call(
jen.Id("collector"),
jen.Lit(false),
jen.Lit("localhost:80"),
jen.Lit(g.name),
),
jen.List(jen.Id("tracer"), jen.Id("err")).Op("=").Qual(
"github.com/openzipkin/zipkin-go-opentracing", "NewTracer",
).Call(jen.Id("recorder")),
jen.Id("localEndpoint").Op(":=").Qual("github.com/openzipkin/zipkin-go", "WithLocalEndpoint").Call(jen.Id("endpoint")),
jen.List(jen.Id("nativeTracer"), jen.Id("err")).Op(":=").Qual(
"github.com/openzipkin/zipkin-go", "NewTracer",
).Call(jen.Id("reporter"), jen.Id("localEndpoint")),
jen.If(jen.Err().Op("!=").Nil()).Block(
jen.Id("logger").Dot("Log").Call(
jen.Lit("err"),
jen.Id("err"),
),
jen.Qual("os", "Exit").Call(jen.Lit(1)),
),
jen.Id("tracer").Op("=").Qual(
"github.com/openzipkin-contrib/zipkin-go-opentracing", "Wrap",
).Call(
jen.Id("nativeTracer"),
),
).Else().If(jen.Id("*lightstepToken").Op("!=").Lit("")).Block(
jen.Id("logger").Dot("Log").Call(
jen.Lit("tracer"),
GrantZheng marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
20 changes: 20 additions & 0 deletions generator/new_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package generator

import (
"fmt"
"os/exec"
"path"
"strings"

Expand Down Expand Up @@ -40,6 +41,14 @@ func NewNewService(name string) Gen {
// Generate will run the generator.
func (g *NewService) Generate() error {
g.CreateFolderStructure(g.destPath)
if viper.GetString("n_s_mod_module") != "" {
err := g.genModule()
if err != nil {
println(err.Error())
return err
}
}

comments := []string{
"Add your methods here",
"e.x: Foo(ctx context.Context,s string)(rs string, err error)",
Expand All @@ -53,3 +62,14 @@ func (g *NewService) Generate() error {
)
return g.fs.WriteFile(g.filePath, g.srcFile.GoString(), false)
}

func (g *NewService) genModule() error {
exist, _ := g.fs.Exists(g.name + "/go.mod")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we want to add the dependencies manually, at least the once we depend on after running kit g s

Copy link
Author

@GrantZheng GrantZheng Jan 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @kujtimiihoxha :)

Why we need to maintain multiple services under the same package?
I think it has two scenes:
The one scene is that we just maintain multiple services and convenient to manage the project. There have no relation between services and services are started by there own main.go file ({service}/cmd/main.go).

The other scene is that we want to construct a monolithic project that contains multiple services under the same package. There have some dependency between services and the monolithic project is started only by one main.go file which needs to be create manually at the service's parent level. In addition, we should also delete the go.mod file at the service level and create a go.mod file manually at the parent level.

About the one scene, I think it is of small significance and rarely used in this way. We only need to cover most of the usage scenarios. There's no need to support.

About the other scene, I think it is significant. But I do not recommend realizing the function at the kit tool. The responsibility of kit tool is just construct our services. If we want to construct a monolithic project, we should do manually as follows:

  1. delete the go.mod file at the service level and create a go.mod file manually at the parent level
  2. create a main.go file at the service's parent level
    But, when we need to add functions to a service , the kit g s {service} will not work well, because we delete the go.mod file under the service level, the module name in the go.mod file can not be autodetected. To solve this problem, the kit tool should add a function that if the go.mod file can not be found in the service level, it will use the go.mod file in parent level to generate service and client library.

What do you think?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right.

One other thing that came to my mind now is that with how it is implemented now we are not maintaining backwards compatibility with already existing projects that use kit.

Is there a way to only use modules when the user wants to do that ?

Basically only use mod if --module is provided OR the go.mod file is detected in the service folder.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About compatible with the already existing projects,we may have two ways, I think.

The one is that we should use tag vesion to manage our feature, such as checkout two new branches named release/v0.1.0 and release/v0.2.0 from the master and tag the release/v0.1.0 branch code v0.1.0 which should run kit commands under the GOPATH, and then switch to release/v0.2.0 branch, merge code from feature/mod_support branch, tag v0.2.0 under the release/v0.2.0 branch. If the user want to use the GOPATH ,he can use the v0.1.0 version; if the user want to use the module feature, he can use the v0.2.0 version.

The other is that continue to support GOPATH in our new version, if user run kit n s {service} without module flag, it will use the old way to new and generate service and client library.

I think the first way is better than the second. I want to quote some word from https://blog.golang.org/modules2019.

Our aim is for Go 1.13, scheduled for August 2019, to enable module mode by default (that is, to change the default from auto to on) and deprecate GOPATH mode. In order to do that, we’ve been working on better tooling support along with better support for the open-source module ecosystem.

So, I think there is no need to compatible with GOPATH in our new version. We should guide the user to use the new module feature. If the user have to use the GOPATH, he could switch to the old version v0.1.0.

What do you think about this? :)

if exist {
return nil
}
cmdStr := "cd " + g.name + " && go mod init " + viper.GetString("n_s_mod_module")
cmd := exec.Command("sh", "-c", cmdStr)
_, err := cmd.Output()
return err
}
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@ go 1.12

require (
github.com/Songmu/prompter v0.0.0-20181014095714-d227c68538bd
github.com/VividCortex/gohistogram v1.0.0 // indirect
GrantZheng marked this conversation as resolved.
Show resolved Hide resolved
github.com/alioygur/godash v0.0.0-20160919141744-af6b3da41c5a
github.com/dave/jennifer v1.3.0
github.com/emicklei/proto v1.6.10
github.com/emicklei/proto-contrib v0.0.0-20190206213850-73879796f936
github.com/go-kit/kit v0.9.0 // indirect
GrantZheng marked this conversation as resolved.
Show resolved Hide resolved
github.com/lightstep/lightstep-tracer-go v0.17.0 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/oklog/oklog v0.3.2 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/opentracing/basictracer-go v1.0.0 // indirect
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.3 // indirect
github.com/prometheus/client_golang v1.1.0 // indirect
github.com/sirupsen/logrus v1.4.0
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a
github.com/spf13/afero v1.2.2
github.com/spf13/cobra v0.0.3
github.com/spf13/viper v1.3.2
golang.org/x/tools v0.0.0-20190401163957-4fc9f0bfa59a
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135
google.golang.org/grpc v1.24.0 // indirect
gopkg.in/yaml.v2 v2.2.2
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 // indirect
)
Loading