未验证 提交 dc23b673 编写于 作者: LinuxSuRen's avatar LinuxSuRen 提交者: GitHub

Add support to upgrade a plugin by command (#144)

* Add support to upgrade a plugin by command

* Try to fix the travis pr id

* Add test cases for plugin upgrade command

* Add more test cases
上级 dd065398
package cmd
import (
"fmt"
"net/http"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/spf13/cobra"
)
// PluginUpgradeOption option for plugin list command
type PluginUpgradeOption struct {
Filter []string
RoundTripper http.RoundTripper
}
var pluginUpgradeOption PluginUpgradeOption
func init() {
pluginCmd.AddCommand(pluginUpgradeCmd)
pluginUpgradeCmd.Flags().StringArrayVarP(&pluginUpgradeOption.Filter, "filter", "", []string{}, "Filter for the list, like: name=foo")
}
var pluginUpgradeCmd = &cobra.Command{
Use: "upgrade [plugin name]",
Short: "Upgrade the specific plugin",
Long: `Upgrade the specific plugin`,
Run: func(cmd *cobra.Command, args []string) {
jclient := &client.PluginManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: pluginUpgradeOption.RoundTripper,
},
}
getCurrentJenkinsAndClient(&(jclient.JenkinsCore))
var err error
targetPlugins := make([]string, 0)
if len(args) == 0 {
var upgradeablePlugins []client.InstalledPlugin
if upgradeablePlugins, err = pluginUpgradeOption.findUpgradeablePlugins(jclient); err == nil {
prompt := &survey.MultiSelect{
Message: fmt.Sprintf("Please select the plugins(%d) which you want to upgrade:", len(upgradeablePlugins)),
Options: pluginUpgradeOption.convertToArray(upgradeablePlugins),
}
err = survey.AskOne(prompt, &targetPlugins)
}
} else {
targetPlugins = args
}
if err != nil {
cmd.PrintErrln(err)
} else {
if err = jclient.InstallPlugin(targetPlugins); err != nil {
cmd.PrintErrln(err)
}
}
},
}
func (p *PluginUpgradeOption) convertToArray(installedPlugins []client.InstalledPlugin) (plugins []string) {
plugins = make([]string, 0)
for _, plugin := range installedPlugins {
plugins = append(plugins, plugin.ShortName)
}
return
}
func (p *PluginUpgradeOption) findUpgradeablePlugins(jclient *client.PluginManager) (
filteredPlugins []client.InstalledPlugin, err error) {
var (
pluginName string
plugins *client.InstalledPluginList
)
if p.Filter != nil {
for _, f := range p.Filter {
if strings.HasPrefix(f, "name=") {
pluginName = strings.TrimPrefix(f, "name=")
break
}
}
}
if plugins, err = jclient.GetPlugins(); err != nil {
return
}
for _, plugin := range plugins.Plugins {
if !plugin.HasUpdate {
continue
}
if pluginName != "" && !strings.Contains(plugin.ShortName, pluginName) {
continue
}
filteredPlugins = append(filteredPlugins, plugin)
}
return
}
package cmd
import (
"bytes"
"io/ioutil"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("plugin upgrade command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
pluginName string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
pluginUpgradeOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
pluginName = "fake"
})
AfterEach(func() {
rootCmd.SetArgs([]string{})
os.Remove(rootOptions.ConfigFile)
rootOptions.ConfigFile = ""
ctrl.Finish()
})
Context("basic cases", func() {
It("given plugin name, should success", func() {
data, err := generateSampleConfig()
Expect(err).To(BeNil())
err = ioutil.WriteFile(rootOptions.ConfigFile, data, 0664)
Expect(err).To(BeNil())
client.PrepareForInstallPlugin(roundTripper, "http://localhost:8080/jenkins", pluginName, "admin", "111e3a2f0231198855dceaff96f20540a9")
rootCmd.SetArgs([]string{"plugin", "upgrade", pluginName})
buf := new(bytes.Buffer)
rootCmd.SetOutput(buf)
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
Expect(buf.String()).To(Equal(""))
})
It("findUpgradeablePlugins", func() {
data, err := generateSampleConfig()
Expect(err).To(BeNil())
err = ioutil.WriteFile(rootOptions.ConfigFile, data, 0664)
Expect(err).To(BeNil())
jclient := &client.PluginManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: roundTripper,
},
}
getCurrentJenkinsAndClient(&(jclient.JenkinsCore))
request, _ := client.PrepareForOneInstalledPlugin(roundTripper, "http://localhost:8080/jenkins")
request.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
pluginUpgradeOption.Filter = []string{"name=a"}
result, err := pluginUpgradeOption.findUpgradeablePlugins(jclient)
Expect(err).To(BeNil())
Expect(result).NotTo(BeNil())
Expect(len(result)).To(Equal(1))
Expect(result[0].ShortName).To(Equal(pluginName))
plugins := pluginUpgradeOption.convertToArray(result)
Expect(len(plugins)).To(Equal(1))
Expect(plugins[0]).To(Equal(pluginName))
})
})
})
......@@ -111,6 +111,23 @@ var _ = Describe("PluginManager test", func() {
})
})
Context("InstallPlugin", func() {
var (
pluginName string
)
BeforeEach(func() {
pluginName = "fake"
})
It("normal case, should success", func() {
PrepareForInstallPlugin(roundTripper, pluginMgr.URL, pluginName, "", "")
err := pluginMgr.InstallPlugin([]string{pluginName})
Expect(err).To(BeNil())
})
})
Context("UninstallPlugin", func() {
var (
pluginName string
......
......@@ -114,48 +114,19 @@ func getPluginsInstallQuery(names []string) string {
// InstallPlugin install a plugin by name
func (p *PluginManager) InstallPlugin(names []string) (err error) {
api := fmt.Sprintf("%s/pluginManager/install?%s", p.URL, getPluginsInstallQuery(names))
var (
req *http.Request
response *http.Response
)
req, err = http.NewRequest("POST", api, nil)
if err == nil {
if err = p.AuthHandle(req); err != nil {
log.Fatal(err)
}
} else {
return
}
client := p.GetClient()
if response, err = client.Do(req); err == nil {
code := response.StatusCode
var data []byte
data, err = ioutil.ReadAll(response.Body)
if code == 200 {
fmt.Println("install succeed.")
} else if code == 400 {
if errMsg, ok := response.Header["X-Error"]; ok {
for _, msg := range errMsg {
fmt.Println(msg)
}
} else {
fmt.Println("Cannot found plugins", names)
}
} else {
fmt.Println(response.Header)
fmt.Println("status code", code)
if err == nil && p.Debug && len(data) > 0 {
ioutil.WriteFile("debug.html", data, 0664)
} else if err != nil {
log.Fatal(err)
}
}
} else {
log.Fatal(err)
}
api := fmt.Sprintf("/pluginManager/install?%s", getPluginsInstallQuery(names))
_, err = p.RequestWithoutData("POST", api, nil, nil, 200)
// TODO needs to consider the following cases
// code == 400 {
// if errMsg, ok := response.Header["X-Error"]; ok {
// for _, msg := range errMsg {
// fmt.Println(msg)
// }
// } else {
// fmt.Println("Cannot found plugins", names)
// }
// }
return
}
......
......@@ -225,6 +225,28 @@ func RequestCrumb(roundTripper *mhttp.MockRoundTripper, rootURL string) (
return
}
// PrepareForInstallPlugin only for test
func PrepareForInstallPlugin(roundTripper *mhttp.MockRoundTripper, rootURL, pluginName, user, passwd string) {
request, _ := http.NewRequest("POST", fmt.Sprintf("%s/pluginManager/install?plugin.%s=", rootURL, pluginName), nil)
request.Header.Add("CrumbRequestField", "Crumb")
response := &http.Response{
StatusCode: 200,
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString("")),
}
roundTripper.EXPECT().
RoundTrip(NewRequestMatcher(request)).Return(response, nil)
// common crumb request
requestCrumb, _ := RequestCrumb(roundTripper, rootURL)
if user != "" && passwd != "" {
request.SetBasicAuth(user, passwd)
requestCrumb.SetBasicAuth(user, passwd)
}
return
}
// PrepareForPipelineJob only for test
func PrepareForPipelineJob(roundTripper *mhttp.MockRoundTripper, rootURL, user, passwd string) (
request *http.Request, response *http.Response) {
......@@ -233,7 +255,7 @@ func PrepareForPipelineJob(roundTripper *mhttp.MockRoundTripper, rootURL, user,
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(`{"type":null,"displayName":null,"script":"script","sandbox":true}`)),
Body: ioutil.NopCloser(bytes.NewBufferString(`{"type":null,"displayName":null,"script":"script","sandbox":true}`)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
......@@ -264,4 +286,5 @@ func PrepareForUpdatePipelineJob(roundTripper *mhttp.MockRoundTripper, rootURL,
request.SetBasicAuth(user, passwd)
requestCrumb.SetBasicAuth(user, passwd)
}
return
}
......@@ -3,7 +3,7 @@ module github.com/jenkins-zh/jenkins-cli
go 1.12
require (
github.com/AlecAivazis/survey/v2 v2.0.1
github.com/AlecAivazis/survey/v2 v2.0.4
github.com/Pallinder/go-randomdata v1.2.0
github.com/atotto/clipboard v0.1.2
github.com/golang/mock v1.3.1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册