diff --git a/app/cmd/config.go b/app/cmd/config.go new file mode 100644 index 0000000000000000000000000000000000000000..66219a1cbcc1dbb9cdb4d1e17e12fa920e1cad85 --- /dev/null +++ b/app/cmd/config.go @@ -0,0 +1,167 @@ +package cmd + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "runtime" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" +) + +type ConfigOptions struct { + Current string + Show bool + Generate bool + List bool + + ConfigFileLocation string +} + +var configOptions ConfigOptions + +func init() { + rootCmd.AddCommand(configCmd) + configCmd.PersistentFlags().StringVarP(&configOptions.Current, "current", "c", "", "Set the current Jenkins") + configCmd.PersistentFlags().BoolVarP(&configOptions.Show, "show", "s", false, "Show the current Jenkins") + configCmd.PersistentFlags().BoolVarP(&configOptions.Generate, "generate", "g", false, "Generate a sample config file for you") + configCmd.PersistentFlags().BoolVarP(&configOptions.List, "list", "l", false, "Display all your Jenkins configs") +} + +var configCmd = &cobra.Command{ + Use: "config", + Short: "Manage the config of jcli", + Long: `Manage the config of jcli`, + Run: func(cmd *cobra.Command, args []string) { + if configOptions.Show { + current := getCurrentJenkins() + fmt.Printf("Current Jenkins's name is %s, url is %s\n", current.Name, current.URL) + } + + if configOptions.List { + fmt.Println("number-name\turl") + for i, jenkins := range getConfig().JenkinsServers { + fmt.Printf("%d-%s\t%s\n", i, jenkins.Name, jenkins.URL) + } + } + + if configOptions.Generate { + if data, err := generateSampleConfig(); err == nil { + fmt.Print(string(data)) + } else { + log.Fatal(err) + } + } + + if configOptions.Current != "" { + found := false + for _, jenkins := range getConfig().JenkinsServers { + if jenkins.Name == configOptions.Current { + found = true + break + } + } + + if found { + config.Current = configOptions.Current + if err := saveConfig(); err != nil { + log.Fatal(err) + } + } else { + log.Fatalf("Cannot found Jenkins by name %s", configOptions.Current) + } + } + }, +} + +// JenkinsServer holds the configuration of your Jenkins +type JenkinsServer struct { + Name string `yaml:"name"` + URL string `yaml:"url"` + UserName string `yaml:"username"` + Token string `yaml:"token"` + Proxy string `yaml:"proxy"` +} + +type Config struct { + Current string `yaml:"current"` + JenkinsServers []JenkinsServer `yaml:"jenkins_servers"` +} + +func generateSampleConfig() ([]byte, error) { + sampleConfig := Config{ + Current: "yourServer", + JenkinsServers: []JenkinsServer{ + { + Name: "yourServer", + URL: "http://localhost:8080/jenkins", + UserName: "admin", + Token: "111e3a2f0231198855dceaff96f20540a9", + }, + }, + } + return yaml.Marshal(&sampleConfig) +} + +var config Config + +func getConfig() Config { + return config +} + +func getCurrentJenkins() (jenkinsServer JenkinsServer) { + config := getConfig() + current := config.Current + for _, cfg := range config.JenkinsServers { + if cfg.Name == current { + jenkinsServer = cfg + break + } + } + return +} + +func loadDefaultConfig() { + userHome := userHomeDir() + if err := loadConfig(fmt.Sprintf("%s/.jenkins-cli.yaml", userHome)); err != nil { + log.Fatalf("error: %v", err) + } +} + +func loadConfig(path string) (err error) { + configOptions.ConfigFileLocation = path + + var content []byte + if content, err = ioutil.ReadFile(path); err == nil { + err = yaml.Unmarshal([]byte(content), &config) + } + return +} + +func saveConfig() (err error) { + var data []byte + config := getConfig() + + if data, err = yaml.Marshal(&config); err == nil { + err = ioutil.WriteFile(configOptions.ConfigFileLocation, data, 0644) + } + return +} + +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } else if runtime.GOOS == "linux" { + home := os.Getenv("XDG_CONFIG_HOME") + if home != "" { + return home + } + } + return os.Getenv("HOME") +} diff --git a/app/cmd/crumbIssuer.go b/app/cmd/crumbIssuer.go index baadcc09543b0e77360a2e0ec97b7b61bc35e8f5..7512265c352728b769f0c843db59ef25ab4baf3d 100644 --- a/app/cmd/crumbIssuer.go +++ b/app/cmd/crumbIssuer.go @@ -10,6 +10,8 @@ import ( "github.com/spf13/cobra" ) +//curl -k -u $JENKINS_USER:$JENKINS_TOKEN $JENKINS_URL/crumbIssuer/api/json -s + // Start contains the command line options type CrumbIssuerOptions struct { Upload bool @@ -21,10 +23,9 @@ func init() { var versionCmd = &cobra.Command{ Use: "crumb", - Short: "Print the version number of Hugo", - Long: `Manage the plugin of Jenkins`, + Short: "Print crumbIssuer of Jenkins", + Long: `Print crumbIssuer of Jenkins`, Run: func(cmd *cobra.Command, args []string) { - //curl -k -u $JENKINS_USER:$JENKINS_TOKEN $JENKINS_URL/crumbIssuer/api/json -s }, } @@ -33,24 +34,22 @@ type CrumbIssuer struct { CrumbRequestField string `json:"crumbRequestField"` } -func getCrumb() (CrumbIssuer, Config) { - config := getConfig() - fmt.Println(config) +func getCrumb() (CrumbIssuer, JenkinsServer) { + config := getCurrentJenkins() - jenkinsRoot := config.JenkinsServers[0].URL + jenkinsRoot := config.URL api := fmt.Sprintf("%s/crumbIssuer/api/json", jenkinsRoot) req, err := http.NewRequest("GET", api, nil) if err != nil { log.Fatal(err) } - req.SetBasicAuth(config.JenkinsServers[0].UserName, config.JenkinsServers[0].Token) + req.SetBasicAuth(config.UserName, config.Token) var crumbIssuer CrumbIssuer client := &http.Client{} if response, err := client.Do(req); err == nil { if data, err := ioutil.ReadAll(response.Body); err == nil { - fmt.Println("crumbe success") fmt.Println(string(data)) json.Unmarshal(data, &crumbIssuer) } else { diff --git a/app/cmd/open.go b/app/cmd/open.go new file mode 100644 index 0000000000000000000000000000000000000000..6e1f4dcc40b557bbe7cfa8b5c2e271f89e4b6618 --- /dev/null +++ b/app/cmd/open.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "log" + "os/exec" + "runtime" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(openCmd) +} + +var openCmd = &cobra.Command{ + Use: "open", + Short: "Open your Jenkins in the browse", + Long: `Open your Jenkins in the browse`, + Run: func(cmd *cobra.Command, args []string) { + jenkins := getCurrentJenkins() + if jenkins.URL != "" { + open(jenkins.URL) + } else { + log.Fatalf("No URL found with Jenkins %s", jenkins.Name) + } + }, +} + +func open(url string) error { + var cmd string + var args []string + + switch runtime.GOOS { + case "windows": + cmd = "cmd" + args = []string{"/c", "start"} + case "darwin": + cmd = "open" + default: // "linux", "freebsd", "openbsd", "netbsd" + cmd = "xdg-open" + } + args = append(args, url) + return exec.Command(cmd, args...).Start() +} diff --git a/app/cmd/plugin.go b/app/cmd/plugin.go index 5d1a6eaf555b4fde37a53f2fc938d7846b8c27ae..dd99b2c6729c1d6d9b7a02523ea593e76a7f8dfa 100644 --- a/app/cmd/plugin.go +++ b/app/cmd/plugin.go @@ -16,32 +16,28 @@ import ( "github.com/spf13/viper" ) -// Start contains the command line options +// PluginOptions contains the command line options type PluginOptions struct { Upload bool } func init() { rootCmd.AddCommand(pluginCmd) + pluginCmd.PersistentFlags().BoolVarP(&author.Upload, "upload", "u", false, "Upload plugin to your Jenkins server") + viper.BindPFlag("upload", pluginCmd.PersistentFlags().Lookup("upload")) } var author PluginOptions var pluginCmd = &cobra.Command{ Use: "plugin", - Short: "Print the version number of Hugo", - Long: `Manage the plugin of Jenkins`, + Short: "Manage the plugins of Jenkins", + Long: `Manage the plugins of Jenkins`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - - fmt.Printf("upload: %v\n", author.Upload) if author.Upload { crumb, config := getCrumb() - fmt.Println("crumb", crumb) - - jenkinsRoot := getConfig().JenkinsServers[0].URL - api := fmt.Sprintf("%s/pluginManager/uploadPlugin", jenkinsRoot) + api := fmt.Sprintf("%s/pluginManager/uploadPlugin", config.URL) path, _ := os.Getwd() dirName := filepath.Base(path) @@ -53,7 +49,7 @@ var pluginCmd = &cobra.Command{ if err != nil { log.Fatal(err) } - request.SetBasicAuth(config.JenkinsServers[0].UserName, config.JenkinsServers[0].Token) + request.SetBasicAuth(config.UserName, config.Token) request.Header.Add("Accept", "*/*") request.Header.Add(crumb.CrumbRequestField, crumb.Crumb) fmt.Println(request.Header) @@ -105,8 +101,3 @@ func newfileUploadRequest(uri string, params map[string]string, paramName, path req.Header.Set("Content-Type", writer.FormDataContentType()) return req, err } - -func init() { - rootCmd.PersistentFlags().BoolVar(&author.Upload, "upload", false, "Upload plugin to your Jenkins server") - viper.BindPFlag("upload", rootCmd.PersistentFlags().Lookup("upload")) -} diff --git a/app/cmd/root.go b/app/cmd/root.go index 12a8c8d170b29284b9092003a30835fa5897dacb..a92500703a328d45785731cfbbe2adb4ed251795 100644 --- a/app/cmd/root.go +++ b/app/cmd/root.go @@ -2,24 +2,30 @@ package cmd import ( "fmt" - "io/ioutil" - "log" "os" + "github.com/linuxsuren/jenkins-cli/app" "github.com/spf13/cobra" - "github.com/spf13/viper" - "gopkg.in/yaml.v2" ) +type RootOptions struct { + Version bool +} + var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, + Use: "jcli", + Short: "jcli is a tool which could help you with your multiple Jenkins", + Long: `jcli is Jenkins CLI which could help with your multiple Jenkins, + Manage your Jenkins and your pipelines + More information could found at https://jenkins-zh.cn`, Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - fmt.Println("hello") + fmt.Println("Jenkins CLI (jcli) manage your Jenkins") + + if rootOptions.Version { + fmt.Printf("Version: v%.2f.%d%s", app.CurrentVersion.Number, + app.CurrentVersion.PatchLevel, + app.CurrentVersion.Suffix) + } }, } @@ -30,40 +36,13 @@ func Execute() { } } -type JenkinsServer struct { - URL string `yaml:"url"` - UserName string `yaml:"username"` - Token string `yaml:"token"` -} - -type Config struct { - JenkinsServers []JenkinsServer `yaml:"jenkins_servers"` -} +var rootOptions RootOptions func init() { cobra.OnInitialize(initConfig) - rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") -} - -var config Config - -func getConfig() Config { - return config + rootCmd.PersistentFlags().BoolVarP(&rootOptions.Version, "version", "v", false, "Print the version of Jenkins CLI") } func initConfig() { - content, err := ioutil.ReadFile("/Users/mac/.jenkins-cli.yaml") - if err != nil { - log.Fatal(err) - } - - err = yaml.Unmarshal([]byte(content), &config) - if err != nil { - log.Fatalf("error: %v", err) - } + loadDefaultConfig() } diff --git a/app/version.go b/app/version.go new file mode 100644 index 0000000000000000000000000000000000000000..83ea23b32934b3e5c57773708e33c655406067d3 --- /dev/null +++ b/app/version.go @@ -0,0 +1,14 @@ +package app + +// Version represents the Jenkins CLI build version. +type Version struct { + // Major and minor version. + Number float32 + + // Increment this for bug releases + PatchLevel int + + // JCLI Suffix is the suffix used in the Jenkins CLI version string. + // It will be blank for release versions. + Suffix string +} diff --git a/app/version_current.go b/app/version_current.go new file mode 100644 index 0000000000000000000000000000000000000000..aacda66e383f33847d8226eb975387cb62a4186f --- /dev/null +++ b/app/version_current.go @@ -0,0 +1,9 @@ +package app + +// CurrentVersion represents the current build version. +// This should be the only one. +var CurrentVersion = Version{ + Number: 0.0, + PatchLevel: 9, + Suffix: "-DEV", +}