Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new feature to backup jenkins relying on thinBackup plugin #638

Merged
merged 10 commits into from
Jun 15, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add -tail to job log
Update job_log.go

Create docker_run.go

Update docker_run.go

Update docker_run.go

Update docker_run.go

Update docker_run.go

Update docker_run.go

Update job_log.go

Update go.mod

Update docker_run.go

Update docker_run.go
jxr98 committed Sep 22, 2021
commit 0af2da7913241f1156646165a43bdc7f1d77148e
193 changes: 193 additions & 0 deletions app/cmd/docker_run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package cmd

import (
"archive/tar"
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(dockerRunCmd)
dockerRunCmd.Flags().StringVarP(&dockerRunOptions.ImageName, "image-name", "", "",
i18n.T("Name of the image in docker hub which contains upgraded jenkins and plugins"))
dockerRunCmd.Flags().StringVarP(&dockerRunOptions.IP, "ip", "", "127.0.0.1",
i18n.T("The ip address of the computer you want to use"))
dockerRunCmd.Flags().StringVarP(&dockerRunOptions.Tag, "tag", "", "latest",
i18n.T("The tag of the images"))
dockerRunCmd.Flags().IntVarP(&dockerRunOptions.DockerPort, "docker-port", "", 2375,
i18n.T("The port to connect to docker"))
dockerRunCmd.Flags().StringVarP(&dockerRunOptions.DockerfilePath, "dockerfile-path", "", "./tmp/output/Dockerfile",
i18n.T("where you want the dockerfile to be placed"))
dockerRunCmd.Flags().IntVarP(&dockerRunOptions.JenkinsPort, "Jenkins-port", "", 8081,
i18n.T("The port to connect to jenkins"))
dockerRunCmd.Flags().StringVarP(&dockerRunOptions.WarPath, "war-path", "", "",
i18n.T("where you want the dockerfile to be placed"))
}

//DockerRunOptions contains some of the options used to create a docker image and run a container
type DockerRunOptions struct {
ImageName string
Tag string
IP string
DockerPort int
DockerfilePath string
JenkinsPort int
WarPath string
}

var dockerRunOptions DockerRunOptions

var dockerRunCmd = &cobra.Command{
Use: "docker run",
Short: i18n.T("Start a container in docker where all upgraded plugins and jenkins run in order to test their eligibility"),
Long: i18n.T("Start a container, where all upgraded plugins and jenkins run, using a image built by Jenkins WAR packager in order to test their eligibility"),
RunE: dockerRunOptions.pullImageAndRunContainer,
Example: `jcli docker run`,
}

//GetDockerIPAndPort returns a string contains IP and port of a local or remote host
func (o *DockerRunOptions) GetDockerIPAndPort() string {
ip := o.IP
port := o.DockerPort
return fmt.Sprintf("tcp://%s:%d", ip, port)
}

//ConnectToDocker returns a client which is used to connect to a local or remote docker host
func (o *DockerRunOptions) ConnectToDocker() (cli *client.Client, err error) {
tcp := fmt.Sprintf("tcp://%s:%d", o.IP, o.DockerPort)
cli, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(), client.WithHost(tcp))
return cli, err
}

func (o *DockerRunOptions) pullImageAndRunContainer(cmd *cobra.Command, args []string) (err error) {
ctx := context.Background()
cli, err := o.ConnectToDocker()
if err != nil {
cmd.Println(err)
return err
}
imageName := o.ImageName + ":" + o.Tag
if o.checkImageExistsInDockerHub(cmd) {
reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
if err != nil {
cmd.Println(err)
}
cmd.Print(reader)
} else {
err := o.buildImage(cmd)
if err != nil {
cmd.Println(err)
}
}
jenkinsPort, err := nat.NewPort("tcp", "8080")
if err != nil {
cmd.Println(err)
}
hostConfig := &container.HostConfig{
PortBindings: nat.PortMap{
jenkinsPort: []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: strconv.Itoa(o.JenkinsPort),
},
},
},
}
exposedPorts := map[nat.Port]struct{}{
jenkinsPort: struct{}{},
}
config := &container.Config{
Image: imageName,
ExposedPorts: exposedPorts,
}

resp, err := cli.ContainerCreate(ctx, config, hostConfig, nil, nil, "jenkinstest2")
if err != nil {
fmt.Println(err)
}
cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
fmt.Println(resp.ID)
return nil
}
func (o *DockerRunOptions) checkImageExistsInDockerHub(cmd *cobra.Command) bool {
ip := fmt.Sprintf("https://index.docker.io/v1/repositories/%s/tags/%s", o.ImageName, o.Tag)
resp, err := http.Get(ip)
if err != nil {
cmd.Println(err)
return false
}
bytes, err := ioutil.ReadAll(resp.Body)
if string(bytes) != "" {
cmd.Println(err)
return false
}
return true
}
func (o *DockerRunOptions) buildImage(cmd *cobra.Command) error {
ctx := context.Background()
cli, _ := o.ConnectToDocker()
dockerFileTarReader, _ := o.getTarReader(cmd)
buildOptions := types.ImageBuildOptions{
Context: dockerFileTarReader,
Dockerfile: o.DockerfilePath,
Remove: true,
Tags: []string{o.ImageName},
}
imageBuildResponse, err := cli.ImageBuild(
ctx,
dockerFileTarReader,
buildOptions,
)

if err != nil {
return err
}
defer imageBuildResponse.Body.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(imageBuildResponse.Body)
cmd.Println(buf.String())
return nil
}
func (o *DockerRunOptions) getTarReader(cmd *cobra.Command) (*bytes.Reader, error) {
src := []string{o.DockerfilePath, o.WarPath}
buf := new(bytes.Buffer)
tw := tar.NewWriter(buf)
defer tw.Close()

for _, fileName := range src {
dockerFileReader, err := os.Open(fileName)
if err != nil {
return nil, err
}
readDockerFile, err := ioutil.ReadAll(dockerFileReader)
if err != nil {
return nil, err
}
tarHeader := &tar.Header{
Name: fileName,
Size: int64(len(readDockerFile)),
}
err = tw.WriteHeader(tarHeader)
if err != nil {
return nil, err
}
_, err = tw.Write(readDockerFile)
if err != nil {
return nil, err
}
}
dockerFileTarReader := bytes.NewReader(buf.Bytes())
return dockerFileTarReader, nil
}
42 changes: 13 additions & 29 deletions app/cmd/job_log.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"time"

"github.com/jenkins-zh/jenkins-cli/app/cmd/common"
@@ -16,11 +15,11 @@ import (
// JobLogOption is the job log option
type JobLogOption struct {
common.WatchOption
History int
LogText string
LastBuildID int
LastBuildURL string
NumberOfLines int
History int

LogText string
LastBuildID int
LastBuildURL string

RoundTripper http.RoundTripper
}
@@ -35,8 +34,6 @@ func init() {
i18n.T("Watch the job logs"))
jobLogCmd.Flags().IntVarP(&jobLogOption.Interval, "interval", "i", 1,
i18n.T("Interval of watch"))
jobLogCmd.Flags().IntVarP(&jobLogOption.NumberOfLines, "tail", "t", -1,
i18n.T("The last number of lines of the log"))
}

var jobLogCmd = &cobra.Command{
@@ -47,10 +44,9 @@ It'll print the log text of the last build if you don't give the build id.`),
Args: cobra.MinimumNArgs(1),
Example: `jcli job log <jobName> [buildID]
jcli job log <jobName> --history 1
jcli job log <jobName> --watch
jcli job log <jobName> --tail <numberOfLines>`,
jcli job log <jobName> --watch`,
PreRunE: func(_ *cobra.Command, args []string) (err error) {
if len(args) >= 3 && jobLogOption.History == -1 {
if len(args) >= 2 && jobLogOption.History == -1 {
var history int
historyStr := args[1]
if history, err = strconv.Atoi(historyStr); err == nil {
@@ -87,7 +83,7 @@ jcli job log <jobName> --tail <numberOfLines>`,
cmd.Println("Current build number:", jobLogOption.LastBuildID)
cmd.Println("Current build url:", jobLogOption.LastBuildURL)

err = printLog(jclient, cmd, name, jobLogOption.History, 0, jobLogOption.NumberOfLines)
err = printLog(jclient, cmd, name, jobLogOption.History, 0)
}

if err != nil || !jobLogOption.Watch {
@@ -99,7 +95,7 @@ jcli job log <jobName> --tail <numberOfLines>`,
},
}

func printLog(jclient *client.JobClient, cmd *cobra.Command, jobName string, history int, start int64, numberOfLines int) (err error) {
func printLog(jclient *client.JobClient, cmd *cobra.Command, jobName string, history int, start int64) (err error) {
var jobLog client.JobLog
if jobLog, err = jclient.Log(jobName, history, start); err == nil {
isNew := false
@@ -114,25 +110,13 @@ func printLog(jclient *client.JobClient, cmd *cobra.Command, jobName string, his
isNew = true
}
}
numberOfLinesOfJobLogText := strings.Count(jobLog.Text, "\n") - 1
if isNew && (numberOfLines > 0 || numberOfLines == -1) {
if numberOfLines >= numberOfLinesOfJobLogText || numberOfLines == -1 {
cmd.Print(jobLog.Text)
numberOfLines -= numberOfLinesOfJobLogText

} else if numberOfLines < numberOfLinesOfJobLogText {
text := jobLog.Text
for i := 0; i <= numberOfLinesOfJobLogText-numberOfLines; i++ {
temp := strings.Index(text, "\n")
text = text[temp+1:]
}
cmd.Print(text)
numberOfLines = 0
}

if isNew {
cmd.Print(jobLog.Text)
}

if jobLog.HasMore {
err = printLog(jclient, cmd, jobName, history, jobLog.NextStart, numberOfLines)
err = printLog(jclient, cmd, jobName, history, jobLog.NextStart)
}
}
return
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ require (
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1
github.com/golang/mock v1.6.0
github.com/google/go-github/v29 v29.0.3
github.com/gorilla/mux v1.8.0 // indirect
github.com/hashicorp/go-version v1.2.1
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/jedib0t/go-pretty/v6 v6.2.4