Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins-cli
提交
087021d8
J
jenkins-cli
项目概览
LinuxSuRen
/
jenkins-cli
与 Fork 源项目一致
Fork自
Jenkins 中文社区 / jenkins-cli
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins-cli
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
087021d8
编写于
7月 27, 2019
作者:
LinuxSuRen
提交者:
GitHub
7月 27, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support to upload plugins from local or remote (#79)
上级
d55bde46
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
239 addition
and
62 deletion
+239
-62
app/cmd/config.go
app/cmd/config.go
+7
-4
app/cmd/config_generate.go
app/cmd/config_generate.go
+4
-3
app/cmd/plugin.go
app/cmd/plugin.go
+3
-0
app/cmd/plugin_list.go
app/cmd/plugin_list.go
+2
-0
app/cmd/plugin_upload.go
app/cmd/plugin_upload.go
+77
-5
app/cmd/root.go
app/cmd/root.go
+2
-0
client/common.go
client/common.go
+2
-0
client/pluginManger.go
client/pluginManger.go
+16
-44
util/http.go
util/http.go
+126
-0
util/table.go
util/table.go
+0
-6
未找到文件。
app/cmd/config.go
浏览文件 @
087021d8
...
...
@@ -22,14 +22,17 @@ func init() {
}
var
configCmd
=
&
cobra
.
Command
{
Use
:
"config"
,
Short
:
"Manage the config of jcli"
,
Long
:
`Manage the config of jcli`
,
Use
:
"config"
,
Aliases
:
[]
string
{
"cfg"
},
Short
:
"Manage the config of jcli"
,
Long
:
`Manage the config of jcli`
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
current
:=
getCurrentJenkins
()
fmt
.
Printf
(
"Current Jenkins's name is %s, url is %s
\n
"
,
current
.
Name
,
current
.
URL
)
},
Example
:
"jcli config -l"
,
Example
:
` jcli config generate
jcli config list
jcli config edit`
,
}
// JenkinsServer holds the configuration of your Jenkins
...
...
app/cmd/config_generate.go
浏览文件 @
087021d8
...
...
@@ -24,9 +24,10 @@ func init() {
}
var
configGenerateCmd
=
&
cobra
.
Command
{
Use
:
"generate"
,
Short
:
"Generate a sample config file for you"
,
Long
:
`Generate a sample config file for you`
,
Use
:
"generate"
,
Aliases
:
[]
string
{
"gen"
},
Short
:
"Generate a sample config file for you"
,
Long
:
`Generate a sample config file for you`
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
if
data
,
err
:=
generateSampleConfig
();
err
==
nil
{
configPath
:=
configOptions
.
ConfigFileLocation
...
...
app/cmd/plugin.go
浏览文件 @
087021d8
...
...
@@ -18,6 +18,9 @@ var pluginCmd = &cobra.Command{
Use
:
"plugin"
,
Short
:
"Manage the plugins of Jenkins"
,
Long
:
`Manage the plugins of Jenkins`
,
Example
:
` jcli plugin list
jcli plugin search github
jcli plugin check`
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
cmd
.
Help
()
},
...
...
app/cmd/plugin_list.go
浏览文件 @
087021d8
...
...
@@ -28,6 +28,8 @@ var pluginListCmd = &cobra.Command{
Use
:
"list"
,
Short
:
"Print all the plugins which are installed"
,
Long
:
`Print all the plugins which are installed`
,
Example
:
` jcli plugin list --filter name=github
jcli plugin list --filter hasUpdate`
,
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
jenkins
:=
getCurrentJenkins
()
jclient
:=
&
client
.
PluginManager
{}
...
...
app/cmd/plugin_upload.go
浏览文件 @
087021d8
package
cmd
import
(
"github.com/jenkins-zh/jenkins-cli/client"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"github.com/jenkins-zh/jenkins-cli/util"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/spf13/cobra"
)
// PluginUploadOption will hold the options of plugin cmd
type
PluginUploadOption
struct
{
Remote
string
RemoteUser
string
RemotePassword
string
RemoteJenkins
string
pluginFilePath
string
}
var
pluginUploadOption
PluginUploadOption
func
init
()
{
pluginCmd
.
AddCommand
(
pluginUploadCmd
)
pluginUploadCmd
.
Flags
()
.
StringVarP
(
&
pluginUploadOption
.
Remote
,
"remote"
,
"r"
,
""
,
"Remote plugin URL"
)
pluginUploadCmd
.
Flags
()
.
StringVarP
(
&
pluginUploadOption
.
RemoteUser
,
"remote-user"
,
""
,
""
,
"User of remote plugin URL"
)
pluginUploadCmd
.
Flags
()
.
StringVarP
(
&
pluginUploadOption
.
RemotePassword
,
"remote-password"
,
""
,
""
,
"Password of remote plugin URL"
)
pluginUploadCmd
.
Flags
()
.
StringVarP
(
&
pluginUploadOption
.
RemoteJenkins
,
"remote-jenkins"
,
""
,
""
,
"Remote Jenkins which will find from config list"
)
}
var
pluginUploadCmd
=
&
cobra
.
Command
{
Use
:
"upload"
,
Short
:
"Upload the plugin from local to your Jenkins"
,
Long
:
`Upload the plugin from local to your Jenkins`
,
Use
:
"upload"
,
Aliases
:
[]
string
{
"up"
},
Short
:
"Upload a plugin to your Jenkins"
,
Long
:
`Upload a plugin from local filesystem or remote URL to your Jenkins`
,
Example
:
` jcli plugin upload --remote https://server/sample.hpi
jcli plugin upload sample.hpi`
,
PreRun
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
if
pluginUploadOption
.
Remote
!=
""
{
file
,
err
:=
ioutil
.
TempFile
(
"."
,
"jcli-plugin"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
defer
os
.
Remove
(
file
.
Name
())
if
pluginUploadOption
.
RemoteJenkins
!=
""
{
if
jenkins
:=
findJenkinsByName
(
pluginUploadOption
.
RemoteJenkins
);
jenkins
!=
nil
{
pluginUploadOption
.
RemoteUser
=
jenkins
.
UserName
pluginUploadOption
.
RemotePassword
=
jenkins
.
Token
}
}
pluginUploadOption
.
pluginFilePath
=
fmt
.
Sprintf
(
"%s.hpi"
,
file
.
Name
())
downloader
:=
util
.
HTTPDownloader
{
TargetFilePath
:
pluginUploadOption
.
pluginFilePath
,
URL
:
pluginUploadOption
.
Remote
,
UserName
:
pluginUploadOption
.
RemoteUser
,
Password
:
pluginUploadOption
.
RemotePassword
,
ShowProgress
:
true
,
Debug
:
rootOptions
.
Debug
,
}
if
err
:=
downloader
.
DownloadFile
();
err
!=
nil
{
log
.
Fatal
(
err
)
}
}
else
if
len
(
args
)
==
0
{
path
,
_
:=
os
.
Getwd
()
dirName
:=
filepath
.
Base
(
path
)
dirName
=
strings
.
Replace
(
dirName
,
"-plugin"
,
""
,
-
1
)
path
+=
fmt
.
Sprintf
(
"/target/%s.hpi"
,
dirName
)
pluginUploadOption
.
pluginFilePath
=
path
}
else
{
pluginUploadOption
.
pluginFilePath
=
args
[
0
]
}
},
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
jenkins
:=
getCurrentJenkins
()
jclient
:=
&
client
.
PluginManager
{}
...
...
@@ -21,7 +88,12 @@ var pluginUploadCmd = &cobra.Command{
jclient
.
Token
=
jenkins
.
Token
jclient
.
Proxy
=
jenkins
.
Proxy
jclient
.
ProxyAuth
=
jenkins
.
ProxyAuth
jclient
.
Debug
=
rootOptions
.
Debug
if
pluginUploadOption
.
Remote
!=
""
{
defer
os
.
Remove
(
pluginUploadOption
.
pluginFilePath
)
}
jclient
.
Upload
()
jclient
.
Upload
(
pluginUploadOption
.
pluginFilePath
)
},
}
app/cmd/root.go
浏览文件 @
087021d8
...
...
@@ -11,6 +11,7 @@ import (
type
RootOptions
struct
{
Version
bool
Debug
bool
}
var
rootCmd
=
&
cobra
.
Command
{
...
...
@@ -48,6 +49,7 @@ var rootOptions RootOptions
func
init
()
{
cobra
.
OnInitialize
(
initConfig
)
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
()
{
...
...
client/common.go
浏览文件 @
087021d8
...
...
@@ -18,6 +18,8 @@ type JenkinsCore struct {
Token
string
Proxy
string
ProxyAuth
string
Debug
bool
}
type
JenkinsCrumb
struct
{
...
...
client/pluginManger.go
浏览文件 @
087021d8
...
...
@@ -13,7 +13,7 @@ import (
"path/filepath"
"strings"
"github.com/
gosuri/uiprogress
"
"github.com/
linuxsuren/jenkins-cli/util
"
)
type
PluginManager
struct
{
...
...
@@ -220,15 +220,11 @@ func (p *PluginManager) UninstallPlugin(name string) (err error) {
return
}
func
(
p
*
PluginManager
)
Upload
()
{
// Upload will upload a file from local filesystem into Jenkins
func
(
p
*
PluginManager
)
Upload
(
pluginFile
string
)
{
api
:=
fmt
.
Sprintf
(
"%s/pluginManager/uploadPlugin"
,
p
.
URL
)
path
,
_
:=
os
.
Getwd
()
dirName
:=
filepath
.
Base
(
path
)
dirName
=
strings
.
Replace
(
dirName
,
"-plugin"
,
""
,
-
1
)
path
+=
fmt
.
Sprintf
(
"/target/%s.hpi"
,
dirName
)
extraParams
:=
map
[
string
]
string
{}
request
,
err
:=
newfileUploadRequest
(
api
,
extraParams
,
"@name"
,
p
ath
)
request
,
err
:=
newfileUploadRequest
(
api
,
extraParams
,
"@name"
,
p
luginFile
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
...
...
@@ -245,9 +241,10 @@ func (p *PluginManager) Upload() {
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
else
if
response
.
StatusCode
!=
200
{
fmt
.
Println
(
"StatusCode"
,
response
.
StatusCode
)
var
data
[]
byte
if
data
,
err
=
ioutil
.
ReadAll
(
response
.
Body
);
err
==
nil
{
fmt
.
Println
(
string
(
data
)
)
if
data
,
err
=
ioutil
.
ReadAll
(
response
.
Body
);
err
==
nil
&&
p
.
Debug
{
ioutil
.
WriteFile
(
"debug.html"
,
data
,
0664
)
}
else
{
log
.
Fatal
(
err
)
}
...
...
@@ -261,34 +258,6 @@ func (p *PluginManager) handleCheck(handle func(*http.Response)) func(*http.Resp
return
handle
}
type
ProgressIndicator
struct
{
bytes
.
Buffer
Total
float64
count
float64
bar
*
uiprogress
.
Bar
}
func
(
i
*
ProgressIndicator
)
Init
()
{
uiprogress
.
Start
()
// start rendering
i
.
bar
=
uiprogress
.
AddBar
(
100
)
// Add a new bar
// optionally, append and prepend completion and elapsed time
i
.
bar
.
AppendCompleted
()
// i.bar.PrependElapsed()
}
func
(
i
*
ProgressIndicator
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
n
,
err
=
i
.
Buffer
.
Write
(
p
)
return
}
func
(
i
*
ProgressIndicator
)
Read
(
p
[]
byte
)
(
n
int
,
err
error
)
{
n
,
err
=
i
.
Buffer
.
Read
(
p
)
i
.
count
+=
float64
(
n
)
i
.
bar
.
Set
((
int
)(
i
.
count
*
100
/
i
.
Total
))
return
}
func
newfileUploadRequest
(
uri
string
,
params
map
[
string
]
string
,
paramName
,
path
string
)
(
*
http
.
Request
,
error
)
{
file
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
...
...
@@ -303,12 +272,15 @@ func newfileUploadRequest(uri string, params map[string]string, paramName, path
}
defer
file
.
Close
()
// body := &bytes.Buffer{}
body
:=
&
ProgressIndicator
{
Total
:
total
,
bytesBuffer
:=
&
bytes
.
Buffer
{}
progressWriter
:=
&
util
.
ProgressIndicator
{
Total
:
total
,
Writer
:
bytesBuffer
,
Reader
:
bytesBuffer
,
Title
:
"Uploading"
,
}
body
.
Init
()
writer
:=
multipart
.
NewWriter
(
b
ody
)
progressWriter
.
Init
()
writer
:=
multipart
.
NewWriter
(
b
ytesBuffer
)
part
,
err
:=
writer
.
CreateFormFile
(
paramName
,
filepath
.
Base
(
path
))
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -324,7 +296,7 @@ func newfileUploadRequest(uri string, params map[string]string, paramName, path
return
nil
,
err
}
req
,
err
:=
http
.
NewRequest
(
"POST"
,
uri
,
body
)
req
,
err
:=
http
.
NewRequest
(
"POST"
,
uri
,
progressWriter
)
req
.
Header
.
Set
(
"Content-Type"
,
writer
.
FormDataContentType
())
return
req
,
err
}
util/http.go
0 → 100644
浏览文件 @
087021d8
package
util
import
(
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strconv"
"github.com/gosuri/uiprogress"
)
type
HTTPDownloader
struct
{
TargetFilePath
string
URL
string
ShowProgress
bool
UserName
string
Password
string
Debug
bool
}
// DownloadFile download a file with the progress
func
(
h
*
HTTPDownloader
)
DownloadFile
()
error
{
filepath
,
url
,
showProgress
:=
h
.
TargetFilePath
,
h
.
URL
,
h
.
ShowProgress
// Get the data
req
,
err
:=
http
.
NewRequest
(
"GET"
,
url
,
nil
)
if
err
!=
nil
{
return
err
}
if
h
.
UserName
!=
""
&&
h
.
Password
!=
""
{
req
.
SetBasicAuth
(
h
.
UserName
,
h
.
Password
)
}
tr
:=
&
http
.
Transport
{
TLSClientConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
}
client
:=
&
http
.
Client
{
Transport
:
tr
}
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
return
err
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
200
{
if
h
.
Debug
{
if
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
);
err
==
nil
{
ioutil
.
WriteFile
(
"debug-download.html"
,
data
,
0664
)
}
}
return
fmt
.
Errorf
(
"Invalidate status code: %d"
,
resp
.
StatusCode
)
}
writer
:=
&
ProgressIndicator
{
Title
:
"Downloading"
,
}
if
showProgress
{
if
total
,
ok
:=
resp
.
Header
[
"Content-Length"
];
ok
&&
len
(
total
)
>
0
{
fileLength
,
err
:=
strconv
.
ParseInt
(
total
[
0
],
10
,
64
)
if
err
==
nil
{
writer
.
Total
=
float64
(
fileLength
)
}
}
}
// Create the file
out
,
err
:=
os
.
Create
(
filepath
)
if
err
!=
nil
{
return
err
}
defer
out
.
Close
()
writer
.
Writer
=
out
writer
.
Init
()
// Write the body to file
_
,
err
=
io
.
Copy
(
writer
,
resp
.
Body
)
return
err
}
// ProgressIndicator hold the progress of io operation
type
ProgressIndicator
struct
{
Writer
io
.
Writer
Reader
io
.
Reader
Title
string
// bytes.Buffer
Total
float64
count
float64
bar
*
uiprogress
.
Bar
}
// Init set the default value for progress indicator
func
(
i
*
ProgressIndicator
)
Init
()
{
uiprogress
.
Start
()
// start rendering
i
.
bar
=
uiprogress
.
AddBar
(
100
)
// Add a new bar
// optionally, append and prepend completion and elapsed time
i
.
bar
.
AppendCompleted
()
// i.bar.PrependElapsed()
if
i
.
Title
!=
""
{
i
.
bar
.
PrependFunc
(
func
(
b
*
uiprogress
.
Bar
)
string
{
return
fmt
.
Sprintf
(
"%s: "
,
i
.
Title
)
})
}
}
func
(
i
*
ProgressIndicator
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
n
,
err
=
i
.
Writer
.
Write
(
p
)
i
.
setBar
(
n
)
return
}
func
(
i
*
ProgressIndicator
)
Read
(
p
[]
byte
)
(
n
int
,
err
error
)
{
n
,
err
=
i
.
Reader
.
Read
(
p
)
i
.
setBar
(
n
)
return
}
func
(
i
*
ProgressIndicator
)
setBar
(
n
int
)
{
i
.
count
+=
float64
(
n
)
i
.
bar
.
Set
((
int
)(
i
.
count
*
100
/
i
.
Total
))
}
util/table.go
浏览文件 @
087021d8
...
...
@@ -6,12 +6,6 @@ import (
"unicode/utf8"
)
// const (
// ALIGN_LEFT = 0
// ALIGN_CENTER = 1
// ALIGN_RIGHT = 2
// )
type
Table
struct
{
Out
io
.
Writer
Rows
[][]
string
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录