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

Add support for configuration-as-code plugin (#265)

* Add support with configuration-as-code

* Fix the comment issues

* Add i18n items
上级 fc455a7c
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(cascCmd)
}
var cascCmd = &cobra.Command{
Use: "casc",
Short: i18n.T("Configuration as Code"),
Long: i18n.T("Configuration as Code"),
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"net/http"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
// CASCApplyOption as the options of apply configuration as code
type CASCApplyOption struct {
RoundTripper http.RoundTripper
}
var cascApplyOption CASCApplyOption
func init() {
cascCmd.AddCommand(cascApplyCmd)
}
var cascApplyCmd = &cobra.Command{
Use: "apply",
Short: i18n.T("Apply config through configuration-as-code"),
Long: i18n.T("Apply config through configuration-as-code"),
RunE: func(cmd *cobra.Command, _ []string) error {
jClient := &client.CASCManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: cascApplyOption.RoundTripper,
},
}
getCurrentJenkinsAndClient(&(jClient.JenkinsCore))
return jClient.Apply()
},
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"io/ioutil"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("casc apply command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
rootURL string
user string
password string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
cascApplyOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
rootURL = "http://localhost:8080/jenkins"
user = "admin"
password = "111e3a2f0231198855dceaff96f20540a9"
})
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())
client.PrepareForSASCApply(roundTripper, rootURL, user, password)
rootCmd.SetArgs([]string{"casc", "apply"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"net/http"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
// CASCExportOption as the options of reload configuration as code
type CASCExportOption struct {
RoundTripper http.RoundTripper
}
var cascExportOption CASCExportOption
func init() {
cascCmd.AddCommand(cascExportCmd)
}
var cascExportCmd = &cobra.Command{
Use: "export",
Short: i18n.T("Export the config from configuration-as-code"),
Long: i18n.T("Export the config from configuration-as-code"),
RunE: func(cmd *cobra.Command, _ []string) (err error) {
jClient := &client.CASCManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: cascExportOption.RoundTripper,
},
}
getCurrentJenkinsAndClient(&(jClient.JenkinsCore))
var config string
if config, err = jClient.Export(); err == nil {
cmd.Print(config)
}
return
},
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"io/ioutil"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("casc apply command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
rootURL string
user string
password string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
cascExportOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
rootURL = "http://localhost:8080/jenkins"
user = "admin"
password = "111e3a2f0231198855dceaff96f20540a9"
})
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())
client.PrepareForSASCExport(roundTripper, rootURL, user, password)
rootCmd.SetArgs([]string{"casc", "export"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
package cmd
import (
"fmt"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
func init() {
cascCmd.AddCommand(cascOpenCmd)
}
var cascOpenCmd = &cobra.Command{
Use: "open",
Short: i18n.T("Open Configuration as Code page in browser"),
Long: i18n.T("Open Configuration as Code page in browser"),
RunE: func(_ *cobra.Command, _ []string) error {
jenkins := getCurrentJenkinsFromOptionsOrDie()
return open(fmt.Sprintf("%s/configuration-as-code", jenkins.URL))
},
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"net/http"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
// CASCReloadOption as the options of reload configuration as code
type CASCReloadOption struct {
RoundTripper http.RoundTripper
}
var cascReloadOption CASCReloadOption
func init() {
cascCmd.AddCommand(cascReloadCmd)
}
var cascReloadCmd = &cobra.Command{
Use: "reload",
Short: i18n.T("Reload config through configuration-as-code"),
Long: i18n.T("Reload config through configuration-as-code"),
RunE: func(cmd *cobra.Command, _ []string) error {
jClient := &client.CASCManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: cascReloadOption.RoundTripper,
},
}
getCurrentJenkinsAndClient(&(jClient.JenkinsCore))
return jClient.Reload()
},
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"io/ioutil"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("casc reload command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
rootURL string
user string
password string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
cascReloadOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
rootURL = "http://localhost:8080/jenkins"
user = "admin"
password = "111e3a2f0231198855dceaff96f20540a9"
})
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())
client.PrepareForSASCReload(roundTripper, rootURL, user, password)
rootCmd.SetArgs([]string{"casc", "reload"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"net/http"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)
// CASCSchemaOption as the options of reload configuration as code
type CASCSchemaOption struct {
RoundTripper http.RoundTripper
}
var cascSchemaOption CASCSchemaOption
func init() {
cascCmd.AddCommand(cascSchemaCmd)
}
var cascSchemaCmd = &cobra.Command{
Use: "schema",
Short: i18n.T("Get the schema of configuration-as-code"),
Long: i18n.T("Get the schema of configuration-as-code"),
RunE: func(cmd *cobra.Command, _ []string) (err error) {
jClient := &client.CASCManager{
JenkinsCore: client.JenkinsCore{
RoundTripper: cascSchemaOption.RoundTripper,
},
}
getCurrentJenkinsAndClient(&(jClient.JenkinsCore))
var config string
if config, err = jClient.Schema(); err == nil {
cmd.Print(config)
}
return
},
}
package cmd
import (
"github.com/jenkins-zh/jenkins-cli/client"
"io/ioutil"
"os"
"github.com/golang/mock/gomock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
)
var _ = Describe("casc apply command", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
rootURL string
user string
password string
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
cascSchemaOption.RoundTripper = roundTripper
rootCmd.SetArgs([]string{})
rootOptions.Jenkins = ""
rootOptions.ConfigFile = "test.yaml"
rootURL = "http://localhost:8080/jenkins"
user = "admin"
password = "111e3a2f0231198855dceaff96f20540a9"
})
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())
client.PrepareForSASCSchema(roundTripper, rootURL, user, password)
rootCmd.SetArgs([]string{"casc", "schema"})
_, err = rootCmd.ExecuteC()
Expect(err).To(BeNil())
})
})
})
......@@ -16,8 +16,8 @@ import (
type CenterOption struct {
WatchOption
RoundTripper http.RoundTripper
CeneterStatus string
RoundTripper http.RoundTripper
CenterStatus string
}
var centerOption CenterOption
......@@ -61,8 +61,8 @@ func printUpdateCenter(jenkins *JenkinsServer, cmd *cobra.Command, roundTripper
}
}
if centerOption.CeneterStatus != centerStatus {
centerOption.CeneterStatus = centerStatus
if centerOption.CenterStatus != centerStatus {
centerOption.CenterStatus = centerStatus
cmd.Printf("%s", centerStatus)
}
......
......@@ -13,8 +13,8 @@ func init() {
var pluginOpenCmd = &cobra.Command{
Use: "open",
Short: "Open update center server",
Long: `Open update center server`,
Short: "Open update center server in browser",
Long: `Open update center server in browser`,
Run: func(_ *cobra.Command, _ []string) {
jenkins := getCurrentJenkinsFromOptionsOrDie()
......
......@@ -9,7 +9,7 @@ import (
. "github.com/onsi/gomega"
)
func TestApp(t *testing.T) {
func TestCmd(t *testing.T) {
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("test-app.xml")
RunSpecsWithDefaultAndCustomReporters(t, "app/cmd", []Reporter{junitReporter})
......
......@@ -9,7 +9,7 @@ import (
. "github.com/onsi/gomega"
)
func TestI18n(t *testing.T) {
func TestHealth(t *testing.T) {
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("test-health.xml")
RunSpecsWithDefaultAndCustomReporters(t, "command health check", []Reporter{junitReporter})
......
......@@ -103,6 +103,14 @@ msgstr "管理 jcli 的配置"
msgid "Copy the output into clipboard"
msgstr "拷贝输出到剪贴板"
#: app/cmd/job_build.go:36
msgid "Batch mode, no need to confirm"
msgstr "批处理模式,无需确认"
#: app/cmd/casc_apply.go:25 app/cmd/casc_apply.go:26
msgid "Apply config through configuration-as-code"
msgstr "从应用已有的配置"
#: app/cmd/root.go:77
msgid "An alternative config file"
msgstr "指定另外一个配置文件"
......@@ -141,8 +149,8 @@ msgid "jcli is a tool which could help you with your multiple Jenkins"
msgstr "jcli 是帮助你管理多个 Jenkins 的工具"
#: app/cmd/computer.go:15 app/cmd/computer.go:16
msgid "管理 Jenkins 节点"
msgstr ""
msgid "Manage the computers of your Jenkins"
msgstr "管理 Jenkins 节点"
#: app/cmd/root.go:55
msgid "Jenkins CLI (jcli) manage your Jenkins"
......@@ -172,6 +180,14 @@ msgstr "管理 Jenkins 的插件"
msgid "Print the version of Jenkins CLI"
msgstr "打印 Jenkins CLI 的版本"
#: app/cmd/job_history.go:29 app/cmd/job_history.go:30
msgid "Print the history of job in your Jenkins"
msgstr "输出任务的构建历史"
#: app/cmd/casc_export.go:25 app/cmd/casc_export.go:26
msgid "Export the config from configuration-as-code"
msgstr "导出配置及代码的配置"
#: app/cmd/completion.go:14 app/cmd/completion.go:15
msgid "Genereate bash completion scripts"
msgstr "生成 bash 自动补全的脚本"
......@@ -180,6 +196,10 @@ msgstr "生成 bash 自动补全的脚本"
msgid "If you want to show the progress of download a plugin"
msgstr "你是否希望显示插件下载的进度"
#: app/cmd/casc_open.go:16 app/cmd/casc_open.go:17
msgid "Open Configuration as Code page in browser"
msgstr "在浏览器中打开配置及代码的页面"
#: app/cmd/center_start.go:61
msgid "Certificate file path for https"
msgstr "HTTPS 协议的证书文件路径"
......@@ -212,6 +232,10 @@ msgstr "远程插件 URL"
msgid "Whether skip the post command hook"
msgstr "是否跳过后置命令钩子"
#: app/cmd/casc_reload.go:25 app/cmd/casc_reload.go:26
msgid "Reload config through configuration-as-code"
msgstr "重新加载配置及代码的配置"
#: app/cmd/center_download.go:32
msgid "Version of the Jenkins which you want to download"
msgstr "你希望下载的 Jenkins 版本"
......@@ -316,6 +340,10 @@ msgstr "搜索插件"
msgid "Whether show the upload progress"
msgstr "是否显示上传进度"
#: app/cmd/casc_schema.go:25 app/cmd/casc_schema.go:26
msgid "Get the schema of configuration-as-code"
msgstr "获取配置及代码的结构"
#: app/cmd/plugin_upload.go:47
msgid "Remote Jenkins which will find from config list"
msgstr ""
......
......@@ -9,7 +9,7 @@ import (
. "github.com/onsi/gomega"
)
func TestUtils(t *testing.T) {
func TestApp(t *testing.T) {
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("test-app.xml")
RunSpecsWithDefaultAndCustomReporters(t, "app", []Reporter{junitReporter})
......
package client
// CASCManager is the client of configuration as code
type CASCManager struct {
JenkinsCore
}
// Export exports the config of configuration-as-code
func (c *CASCManager) Export() (config string, err error) {
var (
data []byte
statusCode int
)
if statusCode, data, err = c.Request("POST", "/configuration-as-code/export",
nil, nil); err == nil &&
statusCode != 200 {
err = c.ErrorHandle(statusCode, data)
}
config = string(data)
return
}
// Schema get the schema of configuration-as-code
func (c *CASCManager) Schema() (schema string, err error) {
var (
data []byte
statusCode int
)
if statusCode, data, err = c.Request("POST", "/configuration-as-code/schema",
nil, nil); err == nil &&
statusCode != 200 {
err = c.ErrorHandle(statusCode, data)
}
schema = string(data)
return
}
// Reload reload the config of configuration-as-code
func (c *CASCManager) Reload() (err error) {
_, err = c.RequestWithoutData("POST", "/configuration-as-code/reload",
nil, nil, 200)
return
}
// Apply apply the config of configuration-as-code
func (c *CASCManager) Apply() (err error) {
_, err = c.RequestWithoutData("POST", "/configuration-as-code/apply",
nil, nil, 200)
return
}
package client_test
import (
"github.com/golang/mock/gomock"
"github.com/jenkins-zh/jenkins-cli/client"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("", func() {
var (
ctrl *gomock.Controller
roundTripper *mhttp.MockRoundTripper
cascManager client.CASCManager
)
BeforeEach(func() {
ctrl = gomock.NewController(GinkgoT())
roundTripper = mhttp.NewMockRoundTripper(ctrl)
cascManager = client.CASCManager{}
cascManager.RoundTripper = roundTripper
cascManager.URL = "http://localhost"
})
AfterEach(func() {
ctrl.Finish()
})
It("normal cases", func() {
client.PrepareForSASCReload(roundTripper, cascManager.URL, "", "")
client.PrepareForSASCApply(roundTripper, cascManager.URL, "", "")
client.PrepareForSASCExport(roundTripper, cascManager.URL, "", "")
client.PrepareForSASCSchema(roundTripper, cascManager.URL, "", "")
reloadErr := cascManager.Reload()
applyErr := cascManager.Apply()
config, exportErr := cascManager.Export()
schema, schemaErr := cascManager.Schema()
Expect(reloadErr).NotTo(HaveOccurred())
Expect(applyErr).NotTo(HaveOccurred())
Expect(exportErr).NotTo(HaveOccurred())
Expect(schemaErr).NotTo(HaveOccurred())
Expect(config).To(Equal("sample"))
Expect(schema).To(Equal("sample"))
})
Context("with error code", func() {
BeforeEach(func() {
client.PrepareForSASCExportWithCode(roundTripper, cascManager.URL, "", "", 500)
client.PrepareForSASCSchemaWithCode(roundTripper, cascManager.URL, "", "", 500)
})
It("get error", func() {
_, exportErr := cascManager.Export()
_, schemaErr := cascManager.Schema()
Expect(exportErr).To(HaveOccurred())
Expect(schemaErr).To(HaveOccurred())
})
})
})
package client
import (
"fmt"
"github.com/jenkins-zh/jenkins-cli/mock/mhttp"
"net/http"
)
// PrepareForSASCReload only for test
func PrepareForSASCReload(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string) {
request, _ := http.NewRequest("POST",
fmt.Sprintf("%s/configuration-as-code/reload", rootURL), nil)
PrepareCommonPost(request, "", roundTripper, user, password, rootURL)
}
// PrepareForSASCApply only for test
func PrepareForSASCApply(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string) {
request, _ := http.NewRequest("POST",
fmt.Sprintf("%s/configuration-as-code/apply", rootURL), nil)
PrepareCommonPost(request, "", roundTripper, user, password, rootURL)
}
// PrepareForSASCExport only for test
func PrepareForSASCExport(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string) (
response *http.Response) {
request, _ := http.NewRequest("POST",
fmt.Sprintf("%s/configuration-as-code/export", rootURL), nil)
response = PrepareCommonPost(request, "sample", roundTripper, user, password, rootURL)
return
}
// PrepareForSASCExportWithCode only for test
func PrepareForSASCExportWithCode(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string, code int) {
response := PrepareForSASCExport(roundTripper, rootURL, user, password)
response.StatusCode = code
}
// PrepareForSASCSchema only for test
func PrepareForSASCSchema(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string) (
response *http.Response) {
request, _ := http.NewRequest("POST",
fmt.Sprintf("%s/configuration-as-code/schema", rootURL), nil)
response = PrepareCommonPost(request, "sample", roundTripper, user, password, rootURL)
return
}
// PrepareForSASCSchemaWithCode only for test
func PrepareForSASCSchemaWithCode(roundTripper *mhttp.MockRoundTripper, rootURL, user, password string, code int) {
response := PrepareForSASCSchema(roundTripper, rootURL, user, password)
response.StatusCode = code
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册