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

Add support to download Jenkins (#129)

* Add support to download Jenkins

* Add test cases for http downloader

* Exclued mock files

* Exclued mock files

* Add test cases for center download

* Remove mock files

* Fix gen-mock

* Add init stage for building

* Add test case for jenkins upgrade cmd

* Add test casee for center watch cmd

* Add test case for center cmd
上级 92ab7a6c
......@@ -15,3 +15,5 @@ bin/
release/
*.xml
mock
......@@ -17,7 +17,7 @@ addons:
script:
- make clean
# Execute some tests
- make test
- make init test
# And finally run the SonarQube analysis - read the "sonar-project.properties"
# file to see the specific configuration
- curl -LsS https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.0.0.1744-linux.zip > sonar-scanner-cli-4.0.0.1744-linux.zip
......
......@@ -6,6 +6,15 @@ pipeline {
}
stages {
stage('Init') {
steps {
script {
entry.container_x('golang', 'go version'){
sh label: 'make init', script: 'make init'
}
}
}
}
stage('Build') {
parallel {
stage('MacOS') {
......
......@@ -7,6 +7,13 @@ VERSION := dev-$(shell git describe --tags $(shell git rev-list --tags --max-cou
BUILDFLAGS = -ldflags "-X github.com/jenkins-zh/jenkins-cli/app.version=$(VERSION) -X github.com/jenkins-zh/jenkins-cli/app.commit=$(COMMIT)"
COVERED_MAIN_SRC_FILE=./main
gen-mock:
go get github.com/golang/mock/gomock
go install github.com/golang/mock/mockgen
mockgen -destination ./mock/mhttp/roundtripper.go -package mhttp net/http RoundTripper
init: gen-mock
darwin: ## Build for OSX
GO111MODULE=on CGO_ENABLED=$(CGO_ENABLED) GOOS=darwin GOARCH=amd64 $(GO) $(BUILD_TARGET) $(BUILDFLAGS) -o bin/darwin/$(NAME) $(MAIN_SRC_FILE)
chmod +x bin/darwin/$(NAME)
......
......@@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"log"
"net/http"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/spf13/cobra"
......@@ -11,6 +12,7 @@ import (
type CenterOption struct {
WatchOption
RoundTripper http.RoundTripper
CeneterStatus string
}
......@@ -26,14 +28,18 @@ var centerCmd = &cobra.Command{
Long: `Manage your update center`,
Run: func(_ *cobra.Command, _ []string) {
jenkins := getCurrentJenkinsFromOptionsOrDie()
printJenkinsStatus(jenkins)
printJenkinsStatus(jenkins, centerOption.RoundTripper)
printUpdateCenter(jenkins)
printUpdateCenter(jenkins, centerOption.RoundTripper)
},
}
func printUpdateCenter(jenkins *JenkinsServer) {
jclient := &client.UpdateCenterManager{}
func printUpdateCenter(jenkins *JenkinsServer, roundTripper http.RoundTripper) {
jclient := &client.UpdateCenterManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: roundTripper,
},
}
jclient.URL = jenkins.URL
jclient.UserName = jenkins.UserName
jclient.Token = jenkins.Token
......@@ -63,8 +69,12 @@ func printUpdateCenter(jenkins *JenkinsServer) {
}
}
func printJenkinsStatus(jenkins *JenkinsServer) {
jclient := &client.JenkinsStatusClient{}
func printJenkinsStatus(jenkins *JenkinsServer, roundTripper http.RoundTripper) {
jclient := &client.JenkinsStatusClient{
JenkinsCore: client.JenkinsCore{
RoundTripper: roundTripper,
},
}
jclient.URL = jenkins.URL
jclient.UserName = jenkins.UserName
jclient.Token = jenkins.Token
......
package cmd
import (
"log"
"net/http"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/spf13/cobra"
)
// CenterDownloadOption as the options of download command
type CenterDownloadOption struct {
LTS bool
Output string
RoundTripper http.RoundTripper
}
var centerDownloadOption CenterDownloadOption
func init() {
centerCmd.AddCommand(centerDownloadCmd)
centerDownloadCmd.Flags().BoolVarP(&centerDownloadOption.LTS, "lts", "", true, "If you want to download Jenkins as LTS")
centerDownloadCmd.Flags().StringVarP(&centerDownloadOption.Output, "output", "o", "jenkins.war", "The file of output")
}
var centerDownloadCmd = &cobra.Command{
Use: "download",
Short: "Download Jenkins",
Long: `Download Jenkins`,
Run: func(_ *cobra.Command, _ []string) {
jclient := &client.UpdateCenterManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: centerDownloadOption.RoundTripper,
},
}
if err := jclient.DownloadJenkins(centerDownloadOption.LTS, centerDownloadOption.Output); err != nil {
log.Fatal(err)
}
},
}
package cmd
import (
"bytes"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("center download command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
targetFilePath string
responseBody string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
targetFilePath = "jenkins.war"
responseBody = "fake response"
})
AfterEach(func() {
rootCmd.SetArgs([]string{})
os.Remove(targetFilePath)
ctrl.Finish()
})
Context("basic cases", func() {
It("should success", func() {
centerDownloadOption.RoundTripper = roundTripper
centerDownloadOption.LTS = false
request, _ := http.NewRequest("GET", "http://mirrors.jenkins.io/war/latest/jenkins.war", nil)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Header: http.Header{},
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
rootCmd.SetArgs([]string{"center", "download"})
_, err := rootCmd.ExecuteC()
Expect(err).To(BeNil())
_, err = os.Stat(targetFilePath)
Expect(err).To(BeNil())
content, readErr := ioutil.ReadFile(targetFilePath)
Expect(readErr).To(BeNil())
Expect(string(content)).To(Equal(responseBody))
})
})
})
package cmd
import (
"bytes"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("center command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
centerOption.RoundTripper = roundTripper
})
AfterEach(func() {
rootCmd.SetArgs([]string{})
os.Remove(rootOptions.ConfigFile)
rootOptions.ConfigFile = ""
ctrl.Finish()
})
Context("basic cases", func() {
It("should success", func() {
data, err := generateSampleConfig()
Expect(err).To(BeNil())
err = ioutil.WriteFile(rootOptions.ConfigFile, data, 0664)
Expect(err).To(BeNil())
requestCrumb, _ := http.NewRequest("GET", "http://localhost:8080/jenkins/api/json", nil)
requestCrumb.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
responseCrumb := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: requestCrumb,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"version":"0"}
`)),
}
roundTripper.EXPECT().
RoundTrip(requestCrumb).Return(responseCrumb, nil)
request, _ := http.NewRequest("GET", "http://localhost:8080/jenkins/updateCenter/api/json?pretty=false&depth=1", nil)
request.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"RestartRequiredForCompletion":true}
`)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
rootCmd.SetArgs([]string{"center"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
......@@ -2,11 +2,19 @@ package cmd
import (
"log"
"net/http"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/spf13/cobra"
)
// CenterUpgradeOption option for upgrade Jenkins
type CenterUpgradeOption struct {
RoundTripper http.RoundTripper
}
var centerUpgradeOption CenterUpgradeOption
func init() {
centerCmd.AddCommand(centerUpgradeCmd)
}
......@@ -18,7 +26,11 @@ var centerUpgradeCmd = &cobra.Command{
Run: func(_ *cobra.Command, _ []string) {
jenkins := getCurrentJenkinsFromOptionsOrDie()
jclient := &client.UpdateCenterManager{}
jclient := &client.UpdateCenterManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: centerUpgradeOption.RoundTripper,
},
}
jclient.URL = jenkins.URL
jclient.UserName = jenkins.UserName
jclient.Token = jenkins.Token
......
package cmd
import (
"bytes"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("center upgrade command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
centerUpgradeOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
})
AfterEach(func() {
rootCmd.SetArgs([]string{})
os.Remove(rootOptions.ConfigFile)
rootOptions.ConfigFile = ""
ctrl.Finish()
})
Context("basic cases", func() {
It("should success", func() {
data, err := generateSampleConfig()
Expect(err).To(BeNil())
err = ioutil.WriteFile(rootOptions.ConfigFile, data, 0664)
Expect(err).To(BeNil())
requestCrumb, _ := http.NewRequest("GET", "http://localhost:8080/jenkins/crumbIssuer/api/json", nil)
requestCrumb.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
responseCrumb := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: requestCrumb,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"crumbRequestField":"CrumbRequestField","crumb":"Crumb"}
`)),
}
roundTripper.EXPECT().
RoundTrip(requestCrumb).Return(responseCrumb, nil)
request, _ := http.NewRequest("POST", "http://localhost:8080/jenkins/updateCenter/upgrade", nil)
request.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
request.Header.Add("CrumbRequestField", "Crumb")
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString("")),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
rootCmd.SetArgs([]string{"center", "upgrade"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
package cmd
import (
"net/http"
"time"
"github.com/spf13/cobra"
......@@ -10,6 +11,7 @@ import (
type CenterWatchOption struct {
WatchOption
RoundTripper http.RoundTripper
CeneterStatus string
}
......@@ -17,7 +19,7 @@ var centerWatchOption CenterWatchOption
func init() {
centerCmd.AddCommand(centerWatchCmd)
centerWatchCmd.Flags().IntVarP(&centerWatchOption.Interval, "interval", "i", 1, "Interval of watch")
centerWatchOption.SetFlag(centerWatchCmd)
}
var centerWatchCmd = &cobra.Command{
......@@ -26,10 +28,10 @@ var centerWatchCmd = &cobra.Command{
Long: `Watch your update center status`,
Run: func(_ *cobra.Command, _ []string) {
jenkins := getCurrentJenkinsFromOptionsOrDie()
printJenkinsStatus(jenkins)
printJenkinsStatus(jenkins, centerWatchOption.RoundTripper)
for {
printUpdateCenter(jenkins)
for ; centerWatchOption.Count >= 0; centerWatchOption.Count-- {
printUpdateCenter(jenkins, centerOption.RoundTripper)
time.Sleep(time.Duration(centerOption.Interval) * time.Second)
}
......
package cmd
import (
"bytes"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("center watch command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
centerWatchOption.WatchOption.Count = -1
centerWatchOption.RoundTripper = roundTripper
centerOption.RoundTripper = roundTripper
})
AfterEach(func() {
rootCmd.SetArgs([]string{})
os.Remove(rootOptions.ConfigFile)
rootOptions.ConfigFile = ""
ctrl.Finish()
})
Context("basic cases", func() {
It("should success", func() {
data, err := generateSampleConfig()
Expect(err).To(BeNil())
err = ioutil.WriteFile(rootOptions.ConfigFile, data, 0664)
Expect(err).To(BeNil())
requestCrumb, _ := http.NewRequest("GET", "http://localhost:8080/jenkins/api/json", nil)
requestCrumb.SetBasicAuth("admin", "111e3a2f0231198855dceaff96f20540a9")
responseCrumb := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: requestCrumb,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"version":"0"}
`)),
}
roundTripper.EXPECT().
RoundTrip(requestCrumb).Return(responseCrumb, nil)
rootCmd.SetArgs([]string{"center", "watch"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
......@@ -78,6 +78,13 @@ func (b *BatchOption) SetFlag(cmd *cobra.Command) {
type WatchOption struct {
Watch bool
Interval int
Count int
}
// SetFlag for WatchOption
func (o *WatchOption) SetFlag(cmd *cobra.Command) {
cmd.Flags().IntVarP(&o.Interval, "interval", "i", 1, "Interval of watch")
cmd.Flags().IntVarP(&o.Interval, "count", "", 9999, "Count of watch")
}
// InteractiveOption allow user to choose whether the mode is interactive
......
......@@ -105,8 +105,11 @@ func getJenkinsNames() []string {
func getCurrentJenkins() (jenkinsServer *JenkinsServer) {
config := getConfig()
current := config.Current
jenkinsServer = findJenkinsByName(current)
if config != nil {
current := config.Current
jenkinsServer = findJenkinsByName(current)
}
return
}
......
......@@ -14,9 +14,10 @@ import (
// RootOptions is a global option for whole cli
type RootOptions struct {
Jenkins string
Version bool
Debug bool
ConfigFile string
Jenkins string
Version bool
Debug bool
}
var rootCmd = &cobra.Command{
......@@ -53,20 +54,31 @@ var rootOptions RootOptions
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVarP(&rootOptions.ConfigFile, "configFile", "", "", "An alternative config file")
rootCmd.PersistentFlags().StringVarP(&rootOptions.Jenkins, "jenkins", "j", "", "Select a Jenkins server for this time")
rootCmd.PersistentFlags().BoolVarP(&rootOptions.Version, "version", "v", false, "Print the version of Jenkins CLI")
rootCmd.PersistentFlags().BoolVarP(&rootOptions.Debug, "debug", "", false, "Print the output into debug.html")
}
func initConfig() {
if err := loadDefaultConfig(); err != nil {
if os.IsNotExist(err) {
log.Printf("No config file found.")
return
if rootOptions.ConfigFile == "" {
if err := loadDefaultConfig(); err != nil {
configLoadErrorHandle(err)
}
} else {
if err := loadConfig(rootOptions.ConfigFile); err != nil {
configLoadErrorHandle(err)
}
}
}
log.Fatalf("Config file is invalid: %v", err)
func configLoadErrorHandle(err error) {
if os.IsNotExist(err) {
log.Printf("No config file found.")
return
}
log.Fatalf("Config file is invalid: %v", err)
}
func getCurrentJenkinsFromOptions() (jenkinsServer *JenkinsServer) {
......
......@@ -19,7 +19,8 @@ type JenkinsCore struct {
Proxy string
ProxyAuth string
Debug bool
Debug bool
RoundTripper http.RoundTripper
}
type JenkinsCrumb struct {
......@@ -28,23 +29,29 @@ type JenkinsCrumb struct {
}
func (j *JenkinsCore) GetClient() (client *http.Client) {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
if j.Proxy != "" {
if proxyURL, err := url.Parse(j.Proxy); err == nil {
tr.Proxy = http.ProxyURL(proxyURL)
} else {
log.Fatal(err)
var roundTripper http.RoundTripper
if j.RoundTripper != nil {
roundTripper = j.RoundTripper
} else {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
if j.Proxy != "" {
if proxyURL, err := url.Parse(j.Proxy); err == nil {
tr.Proxy = http.ProxyURL(proxyURL)
} else {
log.Fatal(err)
}
if j.ProxyAuth != "" {
basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(j.ProxyAuth))
tr.ProxyConnectHeader = http.Header{}
tr.ProxyConnectHeader.Add("Proxy-Authorization", basicAuth)
if j.ProxyAuth != "" {
basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(j.ProxyAuth))
tr.ProxyConnectHeader = http.Header{}
tr.ProxyConnectHeader.Add("Proxy-Authorization", basicAuth)
}
}
roundTripper = tr
}
client = &http.Client{Transport: tr}
client = &http.Client{Transport: roundTripper}
return
}
......@@ -56,7 +63,10 @@ func (j *JenkinsCore) ProxyHandle(request *http.Request) {
}
func (j *JenkinsCore) AuthHandle(request *http.Request) (err error) {
request.SetBasicAuth(j.UserName, j.Token)
if j.UserName != "" && j.Token != "" {
request.SetBasicAuth(j.UserName, j.Token)
}
j.ProxyHandle(request)
if request.Method == "POST" {
......
......@@ -6,6 +6,8 @@ import (
"io/ioutil"
"log"
"net/http"
"github.com/jenkins-zh/jenkins-cli/util"
)
// UpdateCenterManager manages the UpdateCenter
......@@ -132,3 +134,22 @@ func (u *UpdateCenterManager) Upgrade() (err error) {
}
return
}
// DownloadJenkins download Jenkins
func (u *UpdateCenterManager) DownloadJenkins(lts bool, output string) (err error) {
var url string
if lts {
url = "http://mirrors.jenkins.io/war-stable/latest/jenkins.war"
} else {
url = "http://mirrors.jenkins.io/war/latest/jenkins.war"
}
downloader := util.HTTPDownloader{
RoundTripper: u.RoundTripper,
TargetFilePath: output,
URL: url,
ShowProgress: true,
}
err = downloader.DownloadFile()
return
}
package client
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("update center test", func() {
var (
ctrl *gomock.Controller
manager *UpdateCenterManager
roundTripper *mhttp.MockRoundTripper
responseBody string
donwloadFile string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
manager = &UpdateCenterManager{}
roundTripper = mhttp.NewMockRoundTripper(ctrl)
responseBody = "fake response"
donwloadFile = "downloadfile.log"
})
AfterEach(func() {
os.Remove(donwloadFile)
ctrl.Finish()
})
Context("DownloadJenkins", func() {
It("should success with basic cases", func() {
manager.RoundTripper = roundTripper
request, _ := http.NewRequest("GET", "http://mirrors.jenkins.io/war/latest/jenkins.war", nil)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Header: http.Header{},
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := manager.DownloadJenkins(false, donwloadFile)
Expect(err).To(BeNil())
_, err = os.Stat(donwloadFile)
Expect(err).To(BeNil())
content, readErr := ioutil.ReadFile(donwloadFile)
Expect(readErr).To(BeNil())
Expect(string(content)).To(Equal(responseBody))
})
})
Context("Upgrade", func() {
It("basic cases", func() {
manager.RoundTripper = roundTripper
manager.URL = ""
requestCrumb, _ := http.NewRequest("GET", fmt.Sprintf("%s/crumbIssuer/api/json", ""), nil)
responseCrumb := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: requestCrumb,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"crumbRequestField":"CrumbRequestField","crumb":"Crumb"}
`)),
}
roundTripper.EXPECT().
RoundTrip(requestCrumb).Return(responseCrumb, nil)
request, _ := http.NewRequest("POST", "/updateCenter/upgrade", nil)
request.Header.Add("CrumbRequestField", "Crumb")
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString("")),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := manager.Upgrade()
Expect(err).To(BeNil())
})
})
Context("Status", func() {
It("should success", func() {
manager.RoundTripper = roundTripper
manager.URL = ""
request, _ := http.NewRequest("GET", "/updateCenter/api/json?pretty=false&depth=1", nil)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(`
{"RestartRequiredForCompletion": true}
`)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
status, err := manager.Status()
Expect(err).To(BeNil())
Expect(status).NotTo(BeNil())
Expect(status.RestartRequiredForCompletion).Should(BeTrue())
})
})
})
// Code generated by MockGen. DO NOT EDIT.
// Source: net/http (interfaces: RoundTripper)
// Package mhttp is a generated GoMock package.
package mhttp
import (
gomock "github.com/golang/mock/gomock"
http "net/http"
reflect "reflect"
)
// MockRoundTripper is a mock of RoundTripper interface
type MockRoundTripper struct {
ctrl *gomock.Controller
recorder *MockRoundTripperMockRecorder
}
// MockRoundTripperMockRecorder is the mock recorder for MockRoundTripper
type MockRoundTripperMockRecorder struct {
mock *MockRoundTripper
}
// NewMockRoundTripper creates a new mock instance
func NewMockRoundTripper(ctrl *gomock.Controller) *MockRoundTripper {
mock := &MockRoundTripper{ctrl: ctrl}
mock.recorder = &MockRoundTripperMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockRoundTripper) EXPECT() *MockRoundTripperMockRecorder {
return m.recorder
}
// RoundTrip mocks base method
func (m *MockRoundTripper) RoundTrip(arg0 *http.Request) (*http.Response, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RoundTrip", arg0)
ret0, _ := ret[0].(*http.Response)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RoundTrip indicates an expected call of RoundTrip
func (mr *MockRoundTripperMockRecorder) RoundTrip(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RoundTrip", reflect.TypeOf((*MockRoundTripper)(nil).RoundTrip), arg0)
}
......@@ -10,4 +10,4 @@ sonar.sources=.
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
sonar.go.exclusions=**/vendor/**,**/**/*_test.go
sonar.go.exclusions=**/vendor/**,**/**/*_test.go,mock/**/**
......@@ -25,7 +25,8 @@ type HTTPDownloader struct {
UserName string
Password string
Debug bool
Debug bool
RoundTripper http.RoundTripper
}
// DownloadFile download a file with the progress
......@@ -40,8 +41,13 @@ func (h *HTTPDownloader) DownloadFile() error {
if h.UserName != "" && h.Password != "" {
req.SetBasicAuth(h.UserName, h.Password)
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
var tr http.RoundTripper
if h.RoundTripper != nil {
tr = h.RoundTripper
} else {
tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}
client := &http.Client{Transport: tr}
resp, err := client.Do(req)
......
package util
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("http test", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
downloader HTTPDownloader
targetFilePath string
responseBody string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
targetFilePath = "test.log"
downloader = HTTPDownloader{
TargetFilePath: targetFilePath,
RoundTripper: roundTripper,
}
responseBody = "fake body"
})
AfterEach(func() {
os.Remove(targetFilePath)
ctrl.Finish()
})
Context("DownloadFile", func() {
It("no progress indication", func() {
request, _ := http.NewRequest("GET", "", nil)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Header: http.Header{},
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := downloader.DownloadFile()
Expect(err).To(BeNil())
_, err = os.Stat(targetFilePath)
Expect(err).To(BeNil())
content, readErr := ioutil.ReadFile(targetFilePath)
Expect(readErr).To(BeNil())
Expect(string(content)).To(Equal(responseBody))
return
})
It("with BasicAuth", func() {
downloader = HTTPDownloader{
TargetFilePath: targetFilePath,
RoundTripper: roundTripper,
UserName: "UserName",
Password: "Password",
}
request, _ := http.NewRequest("GET", "", nil)
request.SetBasicAuth(downloader.UserName, downloader.Password)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Header: http.Header{},
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := downloader.DownloadFile()
Expect(err).To(BeNil())
_, err = os.Stat(targetFilePath)
Expect(err).To(BeNil())
content, readErr := ioutil.ReadFile(targetFilePath)
Expect(readErr).To(BeNil())
Expect(string(content)).To(Equal(responseBody))
return
})
It("with error request", func() {
downloader = HTTPDownloader{
URL: "fake url",
}
err := downloader.DownloadFile()
Expect(err).To(HaveOccurred())
})
It("with error response", func() {
downloader = HTTPDownloader{
RoundTripper: roundTripper,
}
request, _ := http.NewRequest("GET", "", nil)
response := &http.Response{}
roundTripper.EXPECT().
RoundTrip(request).Return(response, fmt.Errorf("fake error"))
err := downloader.DownloadFile()
Expect(err).To(HaveOccurred())
})
It("status code isn't 200", func() {
downloader = HTTPDownloader{
RoundTripper: roundTripper,
Debug: true,
}
request, _ := http.NewRequest("GET", "", nil)
response := &http.Response{
StatusCode: 400,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := downloader.DownloadFile()
Expect(err).To(HaveOccurred())
const debugFile = "debug-download.html"
_, err = os.Stat(debugFile)
Expect(err).To(BeNil())
content, readErr := ioutil.ReadFile(debugFile)
Expect(readErr).To(BeNil())
Expect(string(content)).To(Equal(responseBody))
defer os.Remove(debugFile)
})
It("showProgress", func() {
downloader = HTTPDownloader{
RoundTripper: roundTripper,
ShowProgress: true,
TargetFilePath: targetFilePath,
}
request, _ := http.NewRequest("GET", "", nil)
response := &http.Response{
StatusCode: 200,
Proto: "HTTP/1.1",
Request: request,
Body: ioutil.NopCloser(bytes.NewBufferString(responseBody)),
}
roundTripper.EXPECT().
RoundTrip(request).Return(response, nil)
err := downloader.DownloadFile()
Expect(err).To(BeNil())
})
})
})
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册