Skip to content

Commit

Permalink
feat: added cli structure and moved server code to start command
Browse files Browse the repository at this point in the history
  • Loading branch information
mahendraintelops committed Nov 6, 2023
1 parent e9e7411 commit 7429646
Show file tree
Hide file tree
Showing 382 changed files with 72,450 additions and 147 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ WORKDIR /app
COPY . .

# Build application
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o core .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o compage .
# Container start command for development
# Allows DevSpace to restart the dev container
# It is also possible to override this in devspace.yaml via images.*.cmd
Expand Down Expand Up @@ -71,4 +71,4 @@ RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
EXPOSE 8080
EXPOSE 50051
# Container start command for production
CMD ["/core"]
CMD ["/compage"]
36 changes: 36 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

// generateCmd represents the generate command
var generateCmd = &cobra.Command{
Use: "generate",
Short: "Generates the code for the given configuration",
Long: `This will generate the code for the given configuration. The configuration file is a yaml file that contains the configuration that guides the compage to generate the code.
Change the file as per your needs and then run the compage generate command to generate the code.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("generate called")
},
}

func init() {
rootCmd.AddCommand(generateCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// generateCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// generateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
33 changes: 33 additions & 0 deletions cmd/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

// initCmd represents the init command
var initCmd = &cobra.Command{
Use: "init",
Short: "Initializes the compage configuration, generates the file and writes it down in the current directory",
Long: `Compage configuration file is a yaml file that contains the configuration that guides the compage to generate the code.
You can change the file as per your needs and then run the compage generate command to generate the code.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("init called")
},
}

func init() {
rootCmd.AddCommand(initCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// initCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// initCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
73 changes: 73 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var cfgFile string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "compage",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
cobra.OnInitialize(initConfig)

// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.compage.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// Search config in home directory with name ".compage" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".compage")
}

viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
}
}
130 changes: 130 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package cmd

import (
"context"
"fmt"
"github.com/intelops/compage/config"
project "github.com/intelops/compage/gen/api/v1"
server "github.com/intelops/compage/grpc"
log "github.com/sirupsen/logrus"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"net"
"os"
"os/signal"
"syscall"

"github.com/spf13/cobra"
"golang.org/x/exp/slices"
)

var (
serviceName = os.Getenv("SERVICE_NAME")
collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
insecure = os.Getenv("INSECURE_MODE")
)

// startCmd represents the start command
var startCmd = &cobra.Command{
Use: "start",
Short: "Starts the gRPC server",
Long: `Compage is a grpc server that generates code for various languages.
This command will start thr gRPC server and allow the gRPC clients to get connected with it. The gRPC server will be listening on port 50051. Make sure that the git submodules are pulled.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("start called")

// grpc server configuration
// Initializes the exporter
var grpcTraceProvider *sdktrace.TracerProvider
if len(serviceName) > 0 && len(collectorURL) > 0 {
// add open telemetry tracing
grpcTraceProvider = config.InitGrpcTracer(serviceName, collectorURL, insecure)
}
defer func() {
if grpcTraceProvider != nil {
if err := grpcTraceProvider.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer provider: %v", err)
}
}
}()

// check if the git submodules have been pulled (mainly need to check this on developer's machine)
if checkIfGitSubmodulesExist() {
log.Println("starting gRPC server...")
startGrpcServer()
} else {
log.Error("starting gRPC server failed as git submodules don't exist")
}
},
}

func init() {
rootCmd.AddCommand(startCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// startCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// startCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func checkIfGitSubmodulesExist() bool {
templatesPath := "templates"
// currently available templates
templates := []string{"compage-templates", "compage-template-go", "compage-template-java", "compage-template-python", "compage-template-javascript", "compage-template-ruby", "compage-template-rust", "compage-template-typescript"}
// read the templates directory and list down files in it.
files, err := os.ReadDir(templatesPath)
if err != nil {
log.Fatal(err)
}
// iterate over files in templates directory
for _, file := range files {
// check if the item in templates directory is directory,
// and it's a valid template (by looking into available templates)
if file.IsDir() && slices.Contains(templates, file.Name()) {
// check in specific template folder.
filesInDir, err0 := os.ReadDir(templatesPath + "/" + file.Name())
if err0 != nil {
log.Fatal(err0)
}
// if there are no directories or files in specific template, this means that the `git submodules update --remote` command wasn't fired before.
if len(filesInDir) <= 0 {
log.Info(file.Name() + " template have not been pulled. Please fire `git submodule init` and then `git submodule update --remote`.")
return false
}
}
}
return true
}

func startGrpcServer() {
listener, err := net.Listen("tcp", "0.0.0.0:50051")
if err != nil {
log.Fatalf("failed to serve: %v", err)
}

grpcServer := grpc.NewServer(grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()))
impl := server.New()
project.RegisterProjectServiceServer(grpcServer, impl)
reflection.Register(grpcServer)

go func() {
if err := grpcServer.Serve(listener); err != nil {
log.Printf("grpcServer.Serve: %v", err)
}
}()

done := make(chan os.Signal, 1)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-done
grpcServer.GracefulStop()
log.Printf("Server stopped")
}
20 changes: 19 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ require (
github.com/gertd/go-pluralize v0.2.1
github.com/iancoleman/strcase v0.3.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.17.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0
Expand All @@ -20,16 +22,32 @@ require (
require (
cloud.google.com/go/compute v1.23.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.14.0 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 7429646

Please sign in to comment.