func TestSettingsContextMiddleware(t *testing.T) { Convey("Given a server with settings context middleware", t, func() { // Reset settings on each test configuration.ResetSettings() // Set the negroni server with our middleware response := httptest.NewRecorder() n := negroni.New() n.Use(NewSettingsContext()) req, _ := http.NewRequest("GET", "http://localhost:3000/", nil) // Check no context before running the middleware Convey("The starting context should be empty", func() { So(len(context.GetAll(req)), ShouldEqual, 0) }) Convey("When making a request", func() { n.ServeHTTP(response, req) requestContextAfter := context.GetAll(req) settings := viper.AllSettings() Convey("The context should be the same as the app settings", func() { So(len(requestContextAfter), ShouldEqual, len(requestContextAfter)) for k := range settings { So(requestContextAfter[k], ShouldEqual, settings[k]) } }) }) Reset(func() { }) }) }
func config(cmd *cobra.Command, args []string) error { if err := InitializeConfig(configCmd); err != nil { return err } allSettings := viper.AllSettings() var separator string if allSettings["metadataformat"] == "toml" { separator = " = " } else { separator = ": " } var keys []string for k := range allSettings { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { kv := reflect.ValueOf(allSettings[k]) if kv.Kind() == reflect.String { fmt.Printf("%s%s\"%+v\"\n", k, separator, allSettings[k]) } else { fmt.Printf("%s%s%+v\n", k, separator, allSettings[k]) } } return nil }
func PrintConfig(ctx log.Interface, debug bool) { prt := ctx.Infof if debug { prt = ctx.Debugf } prt("Using config:") fmt.Println() printKV("config file", viper.ConfigFileUsed()) printKV("data dir", viper.GetString("data")) fmt.Println() for key, val := range viper.AllSettings() { switch key { case "builddate": fallthrough case "gitcommit": fallthrough case "gitbranch": fallthrough case "version": continue default: printKV(key, val) } } fmt.Println() }
func SaveViperConfig() error { cfg := viper.ConfigFileUsed() if cfg == "" { usr, err := user.Current() if err != nil { return err } cfg = filepath.Join(usr.HomeDir, "."+NAME+".yaml") } f, err := os.Create(cfg) if err != nil { return err } defer f.Close() all := viper.AllSettings() b, err := yaml.Marshal(all) if err != nil { return fmt.Errorf("Panic while encoding into YAML format.") } if _, err := f.WriteString(string(b)); err != nil { return err } return nil }
func LoadSettingsFromFile() { viper.SetConfigType(ConfigType) setConfigLocation() // Set defaults viper.SetDefault("Port", Port) viper.SetDefault("EnableAutomerge", EnableAutomerge) viper.SetDefault("Debug", Debug) viper.SetDefault("DefaultEnvironment", DefaultEnvironment) viper.SetDefault("DefaultTask", DefaultTask) viper.SetDefault("BoltdbName", BoltdbName) // Load configuration err := viper.ReadInConfig() if err != nil { log.Warning("Configuration not found, loading defaults") } // set log level if viper.GetBool("Debug") { log.SetLevel(log.DebugLevel) } else { log.SetLevel(log.InfoLevel) } log.Debugf("Loaded setting values: %v", viper.AllSettings()) log.Info("Settings loaded") }
// LoadSettings Load all the app settings // If specific path then don't look at the env var, nor default places func LoadSettings(path string) { // 1 - Default settings LoadAppDefaultSettings() // 2 - Specific file settings if path != "" { LoadFromFileSettings(path) SpecificConfigPath = path } else { // 3 - Env var settings file envSettingsFile := viper.GetString(SettingsPath) if envSettingsFile != "" { LoadFromFileSettings(envSettingsFile) } else { // 4 finally load from one of the default places LoadDefaultFilePathSettings() } } // the first thing after loading the settings is to set the log level ConfigureLogs() log.Info("Loaded Settings: ") for k, v := range viper.AllSettings() { log.Infof(" - %s: %v", k, v) } }
func generate(path, name string) { seedDir := viper.GetString("SeedDir") target := viper.GetString("WorkingDir") path = filepath.Join(target, path) tfile := filepath.Join(seedDir, fmt.Sprintf("%s%s", name, ".tmpl")) if _, err := os.Stat(tfile); os.IsNotExist(err) { log.Fatalln("Given seed directory does not contain template:", name) return } data, err := ioutil.ReadFile(tfile) if err != nil { log.Fatalln(tfile, "could not be loaded.") return } tmpl, _ := template.New(name).Parse(string(data)) ffile := filepath.Join(path, fmt.Sprintf("%s%s", name, ".go")) var file *os.File file, err = os.Create(ffile) if err != nil { log.Fatal(ffile, "could not be created.") return } log.Printf("Generating file: %s\n", ffile) tmpl.Execute(file, viper.AllSettings()) }
func dumpConfigToLog() { l := log.NewEntry(log.StandardLogger()) for k, v := range config.AllSettings() { l = l.WithField(k, v) } l.Debug("running with configuration") }
func tomlConfig() string { var buffer bytes.Buffer if err := toml.NewEncoder(&buffer).Encode(viper.AllSettings()); err != nil { // handle error panic(err) } return buffer.String() }
// Loads the given yaml file as a Value. func LoadYaml(file string) *Source { y, err := ioutil.ReadFile(file) maybePanic(err) viper.SetConfigType("yaml") viper.ReadConfig(bytes.NewBuffer(y)) conf := viper.AllSettings() return NewSource(vals.New(conf)) }
// String returns the current configuration as a string func String() string { allSettings := viper.AllSettings() y, err := yaml.Marshal(&allSettings) if err != nil { log.WithFields(map[string]interface{}{ "settings": allSettings, "err": err, }).Panicln("Failed to marshall config to string") } return fmt.Sprintf("%s\n", y) }
func saveConfig() { cmd := exec.Command("mount", "LABEL=BOOT", "/boot") err := cmd.Run() if err != nil { return } b, _ := json.MarshalIndent(viper.AllSettings(), "", " ") err = ioutil.WriteFile(viper.GetString("file"), b, 0644) if err != nil { panic(fmt.Sprint("Error opening file:", err.Error())) } fmt.Println("Config saved.") cmd = exec.Command("umount", "/boot") cmd.Run() }
func unmarshal(rawVal interface{}) error { config := &mapstructure.DecoderConfig{ DecodeHook: mapstructure.StringToTimeDurationHookFunc(), Metadata: nil, Result: rawVal, WeaklyTypedInput: true, } decoder, err := mapstructure.NewDecoder(config) if err != nil { return err } err = decoder.Decode(viper.AllSettings()) if err != nil { return err } return nil }
func (h *RequestHandler) HandleStatusRequest(w http.ResponseWriter, r *http.Request) error { counters, guages := metrics.Snapshot() return writeJsonResponse(w, Status{true, counters, guages, viper.AllSettings()}, nil) }
// Main runs Centrifugo as a service. func Main() { var port string var address string var debug bool var name string var web string var engn string var logLevel string var logFile string var insecure bool var useSSL bool var sslCert string var sslKey string var redisHost string var redisPort string var redisPassword string var redisDB string var redisURL string var redisAPI bool var redisPool int var rootCmd = &cobra.Command{ Use: "", Short: "Centrifugo", Long: "Centrifuge + GO = Centrifugo – harder, better, faster, stronger", Run: func(cmd *cobra.Command, args []string) { viper.SetDefault("gomaxprocs", 0) viper.SetDefault("prefix", "") viper.SetDefault("web_password", "") viper.SetDefault("web_secret", "") viper.RegisterAlias("cookie_secret", "web_secret") viper.SetDefault("max_channel_length", 255) viper.SetDefault("channel_prefix", "centrifugo") viper.SetDefault("node_ping_interval", 5) viper.SetDefault("message_send_timeout", 60) viper.SetDefault("expired_connection_close_delay", 10) viper.SetDefault("presence_ping_interval", 25) viper.SetDefault("presence_expire_interval", 60) viper.SetDefault("private_channel_prefix", "$") viper.SetDefault("namespace_channel_boundary", ":") viper.SetDefault("user_channel_boundary", "#") viper.SetDefault("user_channel_separator", ",") viper.SetDefault("client_channel_boundary", "&") viper.SetDefault("sockjs_url", "https://cdn.jsdelivr.net/sockjs/1.0/sockjs.min.js") viper.SetDefault("project_name", "") viper.SetDefault("project_secret", "") viper.SetDefault("project_connection_lifetime", false) viper.SetDefault("project_watch", false) viper.SetDefault("project_publish", false) viper.SetDefault("project_anonymous", false) viper.SetDefault("project_presence", false) viper.SetDefault("project_history_size", 0) viper.SetDefault("project_history_lifetime", 0) viper.SetDefault("project_namespaces", "") viper.SetEnvPrefix("centrifugo") viper.BindEnv("engine") viper.BindEnv("insecure") viper.BindEnv("web_password") viper.BindEnv("web_secret") viper.BindEnv("project_name") viper.BindEnv("project_secret") viper.BindEnv("project_connection_lifetime") viper.BindEnv("project_watch") viper.BindEnv("project_publish") viper.BindEnv("project_anonymous") viper.BindEnv("project_join_leave") viper.BindEnv("project_presence") viper.BindEnv("project_history_size") viper.BindEnv("project_history_lifetime") viper.BindPFlag("port", cmd.Flags().Lookup("port")) viper.BindPFlag("address", cmd.Flags().Lookup("address")) viper.BindPFlag("debug", cmd.Flags().Lookup("debug")) viper.BindPFlag("name", cmd.Flags().Lookup("name")) viper.BindPFlag("web", cmd.Flags().Lookup("web")) viper.BindPFlag("engine", cmd.Flags().Lookup("engine")) viper.BindPFlag("insecure", cmd.Flags().Lookup("insecure")) viper.BindPFlag("ssl", cmd.Flags().Lookup("ssl")) viper.BindPFlag("ssl_cert", cmd.Flags().Lookup("ssl_cert")) viper.BindPFlag("ssl_key", cmd.Flags().Lookup("ssl_key")) viper.BindPFlag("log_level", cmd.Flags().Lookup("log_level")) viper.BindPFlag("log_file", cmd.Flags().Lookup("log_file")) viper.BindPFlag("redis_host", cmd.Flags().Lookup("redis_host")) viper.BindPFlag("redis_port", cmd.Flags().Lookup("redis_port")) viper.BindPFlag("redis_password", cmd.Flags().Lookup("redis_password")) viper.BindPFlag("redis_db", cmd.Flags().Lookup("redis_db")) viper.BindPFlag("redis_url", cmd.Flags().Lookup("redis_url")) viper.BindPFlag("redis_api", cmd.Flags().Lookup("redis_api")) viper.BindPFlag("redis_pool", cmd.Flags().Lookup("redis_pool")) err := validateConfig(configFile) if err != nil { logger.FATAL.Fatalln(err) } viper.SetConfigFile(configFile) err = viper.ReadInConfig() if err != nil { logger.FATAL.Fatalln("unable to locate config file") } setupLogging() if os.Getenv("GOMAXPROCS") == "" { if viper.IsSet("gomaxprocs") && viper.GetInt("gomaxprocs") > 0 { runtime.GOMAXPROCS(viper.GetInt("gomaxprocs")) } else { runtime.GOMAXPROCS(runtime.NumCPU()) } } logger.INFO.Println("GOMAXPROCS set to", runtime.GOMAXPROCS(0)) logger.INFO.Println("using config file:", viper.ConfigFileUsed()) c := newConfig() s := structureFromConfig(nil) app, err := libcentrifugo.NewApplication(c) if err != nil { logger.FATAL.Fatalln(err) } app.SetStructure(s) var e libcentrifugo.Engine switch viper.GetString("engine") { case "memory": e = libcentrifugo.NewMemoryEngine(app) case "redis": e = libcentrifugo.NewRedisEngine( app, viper.GetString("redis_host"), viper.GetString("redis_port"), viper.GetString("redis_password"), viper.GetString("redis_db"), viper.GetString("redis_url"), viper.GetBool("redis_api"), viper.GetInt("redis_pool"), ) default: logger.FATAL.Fatalln("unknown engine: " + viper.GetString("engine")) } logger.INFO.Println("engine:", viper.GetString("engine")) logger.DEBUG.Printf("%v\n", viper.AllSettings()) logger.INFO.Println("Use SSL:", viper.GetBool("ssl")) if viper.GetBool("ssl") { if viper.GetString("ssl_cert") == "" { logger.FATAL.Println("No SSL certificate provided") os.Exit(1) } if viper.GetString("ssl_key") == "" { logger.FATAL.Println("No SSL certificate key provided") os.Exit(1) } } app.SetEngine(e) app.Run() go handleSignals(app) mux := libcentrifugo.DefaultMux(app, viper.GetString("prefix"), viper.GetString("web"), viper.GetString("sockjs_url")) addr := viper.GetString("address") + ":" + viper.GetString("port") logger.INFO.Printf("start serving on %s\n", addr) if useSSL { if err := http.ListenAndServeTLS(addr, sslCert, sslKey, mux); err != nil { logger.FATAL.Fatalln("ListenAndServe:", err) } } else { if err := http.ListenAndServe(addr, mux); err != nil { logger.FATAL.Fatalln("ListenAndServe:", err) } } }, } rootCmd.Flags().StringVarP(&port, "port", "p", "8000", "port to bind to") rootCmd.Flags().StringVarP(&address, "address", "a", "", "address to listen on") rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "debug mode - please, do not use it in production") rootCmd.Flags().StringVarP(&configFile, "config", "c", "config.json", "path to config file") rootCmd.Flags().StringVarP(&name, "name", "n", "", "unique node name") rootCmd.Flags().StringVarP(&web, "web", "w", "", "optional path to web interface application") rootCmd.Flags().StringVarP(&engn, "engine", "e", "memory", "engine to use: memory or redis") rootCmd.Flags().BoolVarP(&insecure, "insecure", "", false, "start in insecure mode") rootCmd.Flags().BoolVarP(&useSSL, "ssl", "", false, "accept SSL connections. This requires an X509 certificate and a key file") rootCmd.Flags().StringVarP(&sslCert, "ssl_cert", "", "", "path to an X509 certificate file") rootCmd.Flags().StringVarP(&sslKey, "ssl_key", "", "", "path to an X509 certificate key") rootCmd.Flags().StringVarP(&logLevel, "log_level", "", "info", "set the log level: debug, info, error, critical, fatal or none") rootCmd.Flags().StringVarP(&logFile, "log_file", "", "", "optional log file - if not specified all logs go to STDOUT") rootCmd.Flags().StringVarP(&redisHost, "redis_host", "", "127.0.0.1", "redis host (Redis engine)") rootCmd.Flags().StringVarP(&redisPort, "redis_port", "", "6379", "redis port (Redis engine)") rootCmd.Flags().StringVarP(&redisPassword, "redis_password", "", "", "redis auth password (Redis engine)") rootCmd.Flags().StringVarP(&redisDB, "redis_db", "", "0", "redis database (Redis engine)") rootCmd.Flags().StringVarP(&redisURL, "redis_url", "", "", "redis connection URL (Redis engine)") rootCmd.Flags().BoolVarP(&redisAPI, "redis_api", "", false, "enable Redis API listener (Redis engine)") rootCmd.Flags().IntVarP(&redisPool, "redis_pool", "", 256, "Redis pool size (Redis engine)") var versionCmd = &cobra.Command{ Use: "version", Short: "Centrifugo version number", Long: `Print the version number of Centrifugo`, Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Centrifugo v%s\n", VERSION) }, } var checkConfigFile string var checkConfigCmd = &cobra.Command{ Use: "checkconfig", Short: "Check configuration file", Long: `Check Centrifugo configuration file`, Run: func(cmd *cobra.Command, args []string) { err := validateConfig(checkConfigFile) if err != nil { logger.FATAL.Fatalln(err) } }, } checkConfigCmd.Flags().StringVarP(&checkConfigFile, "config", "c", "config.json", "path to config file to check") var outputConfigFile string var generateConfigCmd = &cobra.Command{ Use: "genconfig", Short: "Generate simple configuration file to start with", Long: `Generate simple configuration file to start with`, Run: func(cmd *cobra.Command, args []string) { err := generateConfig(outputConfigFile) if err != nil { logger.FATAL.Fatalln(err) } }, } generateConfigCmd.Flags().StringVarP(&outputConfigFile, "config", "c", "config.json", "path to output config file") rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(checkConfigCmd) rootCmd.AddCommand(generateConfigCmd) rootCmd.Execute() }
func main() { viper.AddConfigPath("./") viper.SetConfigFile("config.toml") viper.ReadInConfig() logFile, logLevel := loggerInit() mwriter := io.MultiWriter(os.Stdout, logFile) logger.SetOutput(mwriter) logger.SetLevel(logLevel) logger.SetFormatter(&logger.TextFormatter{ FullTimestamp: true, TimestampFormat: "01/02/2006 15:04:05", }) logger.Info("Cardinal starting") logger.Info("Log file: " + logFile.Name()) logger.Info("=========Settings===========") for k, v := range viper.AllSettings() { if reflect.TypeOf(v).Kind() == reflect.Map { logger.Infof("%s", k) for sk, sv := range viper.GetStringMapString(k) { logger.Infof("\t%s = %s", sk, sv) } } else { logger.Infof("%s = %s", k, v) } } logger.Info("============================") logger.Info("connecting to mongodb") initDB() defer session.Close() logger.Info("mongodb connection successful") router := mux.NewRouter() router.HandleFunc("/userAuth/login", func(w http.ResponseWriter, r *http.Request) { handlers.LoginHandler(w, r, userCollection) }).Methods("POST") router.HandleFunc("/userAuth/signup", func(w http.ResponseWriter, r *http.Request) { handlers.SignupHandler(w, r, userCollection) }).Methods("POST") router.HandleFunc("/api/v1/createCollection", func(w http.ResponseWriter, r *http.Request) { handlers.CreateCollection(w, r, userCollection) }).Methods("POST") router.HandleFunc("/api/v1/cardSearch", func(w http.ResponseWriter, r *http.Request) { handlers.CardSearch(w, r, db) }).Methods("GET") if viper.GetBool("server.serveClientFiles") { logger.Info("Serving client files, I recommend using NGINX instead.") router.HandleFunc("/", indexHandler) router.PathPrefix("/").Handler(http.FileServer(http.Dir(viper.GetString("server.clientFileLocation")))) } logger.Info("Server ready on port " + viper.GetString("server.port")) http.ListenAndServe(viper.GetString("server.ip")+":"+viper.GetString("server.port"), router) }
func init() { settings = viper.AllSettings() }
func TestConfigurationUtils(t *testing.T) { Convey("Given a not configured app", t, func() { viper.Reset() viper.SetConfigType(configType) Convey("And loading default settings", func() { // Load as normal LoadSettings("") //--------------------------------------------------- Test ResetSettings Convey("And adding new settings", func() { // Add some settings settingsLengthBefore := len(viper.AllSettings()) for i := 0; i < 20; i++ { viper.Set(fmt.Sprintf("%d", i), i) } Convey("There should be new settings", func() { for i := 0; i < 20; i++ { So(viper.GetInt(fmt.Sprintf("%d", i)), ShouldEqual, i) } }) Convey("When using the settings reset util", func() { // Reset and check ResetSettings() settingsLengthAfter := len(viper.AllSettings()) Convey("Then the context should be the same as the begging settings", func() { So(settingsLengthAfter, ShouldEqual, settingsLengthBefore) }) }) }) //------------------------------------------------ Test OverrideSettings Convey("And setting some specific setting", func() { viper.Set("special", true) settingsLengthBefore := len(viper.AllSettings()) Convey("the setted settings should be available", func() { So(viper.GetBool("special"), ShouldBeTrue) }) Convey("When using the settings override util", func() { // Override and check OverrideSettings(map[string]interface{}{ "special": false, "special1": 1, "special2": "test", }) settingsLengthAfter := len(viper.AllSettings()) Convey("Then the override values should override or add the old settings", func() { So(settingsLengthAfter, ShouldEqual, settingsLengthBefore+2) So(viper.GetBool("special"), ShouldBeFalse) So(viper.GetInt("special1"), ShouldEqual, 1) So(viper.GetString("special2"), ShouldEqual, "test") }) }) }) }) Convey("And loading file settings", func() { testFilePath := "/tmp/monf_test.yml" testData := []byte(`test_setting1: 1 test_setting2: batman test_setting3: true`) err := ioutil.WriteFile(testFilePath, testData, 0644) So(err, ShouldBeNil) LoadSettings(testFilePath) So(viper.GetInt("test_setting1"), ShouldEqual, 1) So(viper.GetString("test_setting2"), ShouldEqual, "batman") So(viper.GetBool("test_setting3"), ShouldBeTrue) Convey("And adding new settings", func() { // Add some settings settingsLengthBefore := len(viper.AllSettings()) for i := 0; i < 20; i++ { viper.Set(fmt.Sprintf("%d", i), i) } Convey("There should be new settings", func() { for i := 0; i < 20; i++ { So(viper.GetInt(fmt.Sprintf("%d", i)), ShouldEqual, i) } }) Convey("When using the settings reset util", func() { // Reset and check ResetSettings() settingsLengthAfter := len(viper.AllSettings()) Convey("Then the context should be the same as the beggining settings including the ones loaded from the config file", func() { So(settingsLengthAfter, ShouldEqual, settingsLengthBefore) So(viper.GetInt("test_setting1"), ShouldEqual, 1) So(viper.GetString("test_setting2"), ShouldEqual, "batman") So(viper.GetBool("test_setting3"), ShouldBeTrue) }) }) }) }) }) }
import ( "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" "reflect" "sort" ) var config = &cobra.Command{ Use: "config", Short: "Print the site configuration", Long: `Print the site configuration, both default and custom settings.`, Run: func(cmd *cobra.Command, args []string) { InitializeConfig() allSettings := viper.AllSettings() var separator string if allSettings["metadataformat"] == "toml" { separator = " = " } else { separator = ": " } var keys []string for k := range allSettings { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { kv := reflect.ValueOf(allSettings[k])
//Run main entry func Run() error { app := cli.NewApp() app.Name = "chaos" app.Version = "v20160606" app.Usage = "it-package web application." app.EnableBashCompletion = true app.Commands = []cli.Command{ { Name: "init", Aliases: []string{"i"}, Usage: "init config file", Flags: []cli.Flag{ cli.StringFlag{ Name: "environment, e", Value: "development", Usage: "environment, like: development, production, test...", }, }, Action: func(c *cli.Context) error { const fn = "config.toml" if _, err := os.Stat(fn); err == nil { return fmt.Errorf("file %s already exists", fn) } fmt.Printf("generate file %s\n", fn) viper.Set("env", c.String("environment")) args := viper.AllSettings() fd, err := os.Create(fn) if err != nil { log.Println(err) return err } defer fd.Close() end := toml.NewEncoder(fd) err = end.Encode(args) return err }, }, { Name: "server", Aliases: []string{"s"}, Usage: "start the app server", Action: IocAction(func(*cli.Context, *inject.Graph) error { if IsProduction() { gin.SetMode(gin.ReleaseMode) } rt := gin.Default() rt.Use(i18n.LocaleHandler) Loop(func(en Engine) error { en.Mount(rt) return nil }) adr := fmt.Sprintf(":%d", viper.GetInt("http.port")) hnd := cors.New(cors.Options{ AllowCredentials: true, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH"}, AllowedHeaders: []string{"*"}, //Debug: true, }).Handler(rt) if IsProduction() { return endless.ListenAndServe(adr, hnd) } return http.ListenAndServe(adr, hnd) }), }, { Name: "worker", Aliases: []string{"w"}, Usage: "start the worker progress", Action: IocAction(func(*cli.Context, *inject.Graph) error { Loop(func(en Engine) error { en.Worker() return nil }) workers.Run() return nil }), }, { Name: "openssl", Aliases: []string{"ssl"}, Usage: "generate ssl certificates", Flags: []cli.Flag{ cli.StringFlag{ Name: "name, n", Usage: "name", }, cli.StringFlag{ Name: "country, c", Value: "Earth", Usage: "country", }, cli.StringFlag{ Name: "organization, o", Value: "Mother Nature", Usage: "organization", }, cli.IntFlag{ Name: "years, y", Value: 1, Usage: "years", }, }, Action: Action(func(c *cli.Context) error { name := c.String("name") if len(name) == 0 { cli.ShowCommandHelp(c, "openssl") return nil } root := path.Join("etc", "ssl", name) key, crt, err := CreateCertificate( true, pkix.Name{ Country: []string{c.String("country")}, Organization: []string{c.String("organization")}, }, c.Int("years"), ) if err != nil { return err } fnk := path.Join(root, "key.pem") fnc := path.Join(root, "crt.pem") fmt.Printf("generate pem file %s\n", fnk) err = WritePemFile(fnk, "RSA PRIVATE KEY", key) fmt.Printf("test: openssl rsa -noout -text -in %s\n", fnk) if err == nil { fmt.Printf("generate pem file %s\n", fnc) err = WritePemFile(fnc, "CERTIFICATE", crt) fmt.Printf("test: openssl x509 -noout -text -in %s\n", fnc) } if err == nil { fmt.Printf( "verify: diff <(openssl rsa -noout -modulus -in %s) <(openssl x509 -noout -modulus -in %s)", fnk, fnc, ) } return err }), }, } for _, en := range engines { cmd := en.Shell() app.Commands = append(app.Commands, cmd...) } return app.Run(os.Args) }