Moves common code out of Jenkins plugin test to utility package.
Adds tests to build pipeline to validate new pipeline examples.
| ... | ... |
@@ -34,9 +34,9 @@ objects: |
| 34 | 34 |
node {
|
| 35 | 35 |
project = env.PROJECT_NAME |
| 36 | 36 |
stage("Initialize") {
|
| 37 |
- sh "oc get route ${appName} -n ${project} -o jsonpath='{ .spec.to.weight }' > blueweight"
|
|
| 38 |
- blueWeight = readFile('blueweight').trim()
|
|
| 39 |
- if (blueWeight == "100") {
|
|
| 37 |
+ sh "oc get route ${appName} -n ${project} -o jsonpath='{ .spec.to.name }' > activeservice"
|
|
| 38 |
+ activeService = readFile('activeservice').trim()
|
|
| 39 |
+ if (activeService == "${appName}-blue") {
|
|
| 40 | 40 |
tag = "green" |
| 41 | 41 |
altTag = "blue" |
| 42 | 42 |
} |
| ... | ... |
@@ -55,7 +55,7 @@ objects: |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
stage("Test") {
|
| 58 |
- input "Test deployment: http://${routeHost}. Approve?"
|
|
| 58 |
+ input message: "Test deployment: http://${routeHost}. Approve?", id: "approval"
|
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
stage("Go Live") {
|
| ... | ... |
@@ -4894,9 +4894,9 @@ objects: |
| 4894 | 4894 |
node {
|
| 4895 | 4895 |
project = env.PROJECT_NAME |
| 4896 | 4896 |
stage("Initialize") {
|
| 4897 |
- sh "oc get route ${appName} -n ${project} -o jsonpath='{ .spec.to.weight }' > blueweight"
|
|
| 4898 |
- blueWeight = readFile('blueweight').trim()
|
|
| 4899 |
- if (blueWeight == "100") {
|
|
| 4897 |
+ sh "oc get route ${appName} -n ${project} -o jsonpath='{ .spec.to.name }' > activeservice"
|
|
| 4898 |
+ activeService = readFile('activeservice').trim()
|
|
| 4899 |
+ if (activeService == "${appName}-blue") {
|
|
| 4900 | 4900 |
tag = "green" |
| 4901 | 4901 |
altTag = "blue" |
| 4902 | 4902 |
} |
| ... | ... |
@@ -4915,7 +4915,7 @@ objects: |
| 4915 | 4915 |
} |
| 4916 | 4916 |
|
| 4917 | 4917 |
stage("Test") {
|
| 4918 |
- input "Test deployment: http://${routeHost}. Approve?"
|
|
| 4918 |
+ input message: "Test deployment: http://${routeHost}. Approve?", id: "approval"
|
|
| 4919 | 4919 |
} |
| 4920 | 4920 |
|
| 4921 | 4921 |
stage("Go Live") {
|
| ... | ... |
@@ -2,52 +2,164 @@ package builds |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
+ "strings" |
|
| 6 |
+ "sync" |
|
| 7 |
+ "time" |
|
| 5 | 8 |
|
| 6 | 9 |
g "github.com/onsi/ginkgo" |
| 7 | 10 |
o "github.com/onsi/gomega" |
| 8 | 11 |
|
| 9 | 12 |
exutil "github.com/openshift/origin/test/extended/util" |
| 13 |
+ "github.com/openshift/origin/test/extended/util/jenkins" |
|
| 10 | 14 |
) |
| 11 | 15 |
|
| 12 | 16 |
var _ = g.Describe("[builds][Slow] openshift pipeline build", func() {
|
| 13 | 17 |
defer g.GinkgoRecover() |
| 14 | 18 |
var ( |
| 15 |
- pipelineTemplatePath = exutil.FixturePath("testdata", "test-pipeline.json")
|
|
| 16 |
- jenkinsTemplatePath = exutil.FixturePath("..", "..", "examples", "jenkins", "jenkins-ephemeral-template.json")
|
|
| 17 |
- oc = exutil.NewCLI("jenkins-pipeline", exutil.KubeConfigPath())
|
|
| 19 |
+ jenkinsTemplatePath = exutil.FixturePath("..", "..", "examples", "jenkins", "jenkins-ephemeral-template.json")
|
|
| 20 |
+ mavenSlavePipelinePath = exutil.FixturePath("..", "..", "examples", "jenkins", "pipeline", "maven-pipeline.yaml")
|
|
| 21 |
+ orchestrationPipelinePath = exutil.FixturePath("..", "..", "examples", "jenkins", "pipeline", "mapsapp-pipeline.yaml")
|
|
| 22 |
+ blueGreenPipelinePath = exutil.FixturePath("..", "..", "examples", "jenkins", "pipeline", "bluegreen-pipeline.yaml")
|
|
| 23 |
+ |
|
| 24 |
+ oc = exutil.NewCLI("jenkins-pipeline", exutil.KubeConfigPath())
|
|
| 18 | 25 |
) |
| 19 | 26 |
g.JustBeforeEach(func() {
|
| 20 | 27 |
g.By("waiting for builder service account")
|
| 21 | 28 |
err := exutil.WaitForBuilderAccount(oc.KubeClient().Core().ServiceAccounts(oc.Namespace())) |
| 22 | 29 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 23 | 30 |
}) |
| 24 |
- g.Context("Manual deploy the jenkins and trigger a jenkins pipeline build", func() {
|
|
| 25 |
- g.It("JenkinsPipeline build should succeed when manual deploy the jenkins service", func() {
|
|
| 26 |
- oc.SetOutputDir(exutil.TestContext.OutputDir) |
|
| 27 |
- |
|
| 31 |
+ g.Context("Pipeline with maven slave", func() {
|
|
| 32 |
+ g.It("Should build and complete successfully", func() {
|
|
| 33 |
+ // Deploy Jenkins |
|
| 28 | 34 |
g.By(fmt.Sprintf("calling oc new-app -f %q", jenkinsTemplatePath))
|
| 29 | 35 |
err := oc.Run("new-app").Args("-f", jenkinsTemplatePath).Execute()
|
| 30 | 36 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 31 | 37 |
|
| 32 |
- //wait for the jenkins deployment complete |
|
| 33 |
- g.By("waiting the jenkins service deployed")
|
|
| 34 |
- err = exutil.WaitForADeploymentToComplete(oc.KubeClient().Core().ReplicationControllers(oc.Namespace()), "jenkins", oc) |
|
| 35 |
- if err != nil {
|
|
| 36 |
- exutil.DumpDeploymentLogs("jenkins", oc)
|
|
| 37 |
- } |
|
| 38 |
+ // instantiate the template |
|
| 39 |
+ g.By(fmt.Sprintf("calling oc new-app -f %q", mavenSlavePipelinePath))
|
|
| 40 |
+ err = oc.Run("new-app").Args("-f", mavenSlavePipelinePath).Execute()
|
|
| 41 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 42 |
+ |
|
| 43 |
+ // start the build |
|
| 44 |
+ g.By("starting the pipeline build and waiting for it to complete")
|
|
| 45 |
+ br, _ := exutil.StartBuildAndWait(oc, "openshift-jee-sample") |
|
| 46 |
+ br.AssertSuccess() |
|
| 47 |
+ |
|
| 48 |
+ // wait for the service to be running |
|
| 49 |
+ g.By("expecting the openshift-jee-sample service to be deployed and running")
|
|
| 50 |
+ _, err = exutil.GetEndpointAddress(oc, "openshift-jee-sample") |
|
| 38 | 51 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 39 |
- // create the pipeline build example |
|
| 40 |
- g.By(fmt.Sprintf("calling oc new-app -f %q", pipelineTemplatePath))
|
|
| 41 |
- err = oc.Run("new-app").Args("-f", pipelineTemplatePath).Execute()
|
|
| 52 |
+ }) |
|
| 53 |
+ }) |
|
| 54 |
+ |
|
| 55 |
+ g.Context("Orchestration pipeline", func() {
|
|
| 56 |
+ g.It("Should build and complete successfully", func() {
|
|
| 57 |
+ // Deploy Jenkins |
|
| 58 |
+ g.By(fmt.Sprintf("calling oc new-app -f %q", jenkinsTemplatePath))
|
|
| 59 |
+ err := oc.Run("new-app").Args("-f", jenkinsTemplatePath).Execute()
|
|
| 42 | 60 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 43 | 61 |
|
| 44 |
- g.By("starting a pipeline build")
|
|
| 45 |
- br, _ := exutil.StartBuildAndWait(oc, "sample-pipeline") |
|
| 46 |
- if !br.BuildSuccess {
|
|
| 47 |
- exutil.DumpDeploymentLogs("jenkins", oc)
|
|
| 48 |
- } |
|
| 62 |
+ // instantiate the template |
|
| 63 |
+ g.By(fmt.Sprintf("calling oc new-app -f %q", orchestrationPipelinePath))
|
|
| 64 |
+ err = oc.Run("new-app").Args("-f", orchestrationPipelinePath).Execute()
|
|
| 65 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 66 |
+ |
|
| 67 |
+ // start the build |
|
| 68 |
+ g.By("starting the pipeline build and waiting for it to complete")
|
|
| 69 |
+ br, _ := exutil.StartBuildAndWait(oc, "mapsapp-pipeline") |
|
| 49 | 70 |
br.AssertSuccess() |
| 71 |
+ |
|
| 72 |
+ // wait for the service to be running |
|
| 73 |
+ g.By("expecting the parksmap-web service to be deployed and running")
|
|
| 74 |
+ _, err = exutil.GetEndpointAddress(oc, "parksmap") |
|
| 75 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 50 | 76 |
}) |
| 51 | 77 |
}) |
| 52 | 78 |
|
| 79 |
+ g.Context("Blue-green pipeline", func() {
|
|
| 80 |
+ g.It("Should build and complete successfully", func() {
|
|
| 81 |
+ // Deploy Jenkins without oauth |
|
| 82 |
+ g.By(fmt.Sprintf("calling oc new-app -f %q -p ENABLE_OAUTH=false", jenkinsTemplatePath))
|
|
| 83 |
+ err := oc.Run("new-app").Args("-f", jenkinsTemplatePath, "-p", "ENABLE_OAUTH=false").Execute()
|
|
| 84 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 85 |
+ |
|
| 86 |
+ j := jenkins.NewRef(oc) |
|
| 87 |
+ |
|
| 88 |
+ // instantiate the template |
|
| 89 |
+ g.By(fmt.Sprintf("calling oc new-app -f %q", blueGreenPipelinePath))
|
|
| 90 |
+ err = oc.Run("new-app").Args("-f", blueGreenPipelinePath).Execute()
|
|
| 91 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 92 |
+ |
|
| 93 |
+ wg := &sync.WaitGroup{}
|
|
| 94 |
+ wg.Add(1) |
|
| 95 |
+ |
|
| 96 |
+ // start the build |
|
| 97 |
+ go func() {
|
|
| 98 |
+ g.By("starting the bluegreen pipeline build and waiting for it to complete")
|
|
| 99 |
+ br, _ := exutil.StartBuildAndWait(oc, "bluegreen-pipeline") |
|
| 100 |
+ br.AssertSuccess() |
|
| 101 |
+ |
|
| 102 |
+ g.By("verifying that the main route has been switched to green")
|
|
| 103 |
+ value, err := oc.Run("get").Args("route", "nodejs-mongodb-example", "-o", "jsonpath={ .spec.to.name }").Output()
|
|
| 104 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 105 |
+ activeRoute := strings.TrimSpace(value) |
|
| 106 |
+ g.By("verifying that the active route is 'nodejs-mongodb-example-green'")
|
|
| 107 |
+ o.Expect(activeRoute).To(o.Equal("nodejs-mongodb-example-green"))
|
|
| 108 |
+ wg.Done() |
|
| 109 |
+ }() |
|
| 110 |
+ |
|
| 111 |
+ // wait for the green service to be available |
|
| 112 |
+ g.By("waiting for the nodejs-mongodb-example-green service to be available")
|
|
| 113 |
+ _, err = exutil.GetEndpointAddress(oc, "nodejs-mongodb-example-green") |
|
| 114 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 115 |
+ |
|
| 116 |
+ // approve the Jenkins pipeline |
|
| 117 |
+ g.By("Waiting for the approval prompt")
|
|
| 118 |
+ jobName := oc.Namespace() + "-bluegreen-pipeline" |
|
| 119 |
+ _, err = j.WaitForContent("Approve?", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 120 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 121 |
+ |
|
| 122 |
+ g.By("Approving the current build")
|
|
| 123 |
+ _, _, err = j.Post(nil, fmt.Sprintf("job/%s/lastBuild/input/Approval/proceedEmpty", jobName), "")
|
|
| 124 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 125 |
+ |
|
| 126 |
+ // wait for first build completion and verification |
|
| 127 |
+ g.By("Waiting for the build to complete successfully")
|
|
| 128 |
+ wg.Wait() |
|
| 129 |
+ |
|
| 130 |
+ wg = &sync.WaitGroup{}
|
|
| 131 |
+ wg.Add(1) |
|
| 132 |
+ |
|
| 133 |
+ // start the build again |
|
| 134 |
+ go func() {
|
|
| 135 |
+ g.By("starting the bluegreen pipeline build and waiting for it to complete")
|
|
| 136 |
+ br, _ := exutil.StartBuildAndWait(oc, "bluegreen-pipeline") |
|
| 137 |
+ br.AssertSuccess() |
|
| 138 |
+ |
|
| 139 |
+ g.By("verifying that the main route has been switched to blue")
|
|
| 140 |
+ value, err := oc.Run("get").Args("route", "nodejs-mongodb-example", "-o", "jsonpath={ .spec.to.name }").Output()
|
|
| 141 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 142 |
+ activeRoute := strings.TrimSpace(value) |
|
| 143 |
+ g.By("verifying that the active route is 'nodejs-mongodb-example-blue'")
|
|
| 144 |
+ o.Expect(activeRoute).To(o.Equal("nodejs-mongodb-example-blue"))
|
|
| 145 |
+ wg.Done() |
|
| 146 |
+ }() |
|
| 147 |
+ |
|
| 148 |
+ // wait for the blue service to be available |
|
| 149 |
+ g.By("waiting for the nodejs-mongodb-example-blue service to be available")
|
|
| 150 |
+ _, err = exutil.GetEndpointAddress(oc, "nodejs-mongodb-example-blue") |
|
| 151 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 152 |
+ |
|
| 153 |
+ // approve the Jenkins pipeline |
|
| 154 |
+ g.By("Waiting for the approval prompt")
|
|
| 155 |
+ _, err = j.WaitForContent("Approve?", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 156 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 157 |
+ |
|
| 158 |
+ g.By("Approving the current build")
|
|
| 159 |
+ _, _, err = j.Post(nil, fmt.Sprintf("job/%s/lastBuild/input/Approval/proceedEmpty", jobName), "")
|
|
| 160 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 161 |
+ |
|
| 162 |
+ wg.Wait() |
|
| 163 |
+ }) |
|
| 164 |
+ }) |
|
| 53 | 165 |
}) |
| ... | ... |
@@ -2,12 +2,10 @@ package image_ecosystem |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 |
- "encoding/xml" |
|
| 6 | 5 |
"fmt" |
| 7 |
- "io" |
|
| 8 |
- "io/ioutil" |
|
| 9 |
- "net/http" |
|
| 10 | 6 |
"net/url" |
| 7 |
+ "os" |
|
| 8 |
+ "os/exec" |
|
| 11 | 9 |
"regexp" |
| 12 | 10 |
"strings" |
| 13 | 11 |
"time" |
| ... | ... |
@@ -18,333 +16,21 @@ import ( |
| 18 | 18 |
kapi "k8s.io/kubernetes/pkg/api" |
| 19 | 19 |
"k8s.io/kubernetes/pkg/util/wait" |
| 20 | 20 |
|
| 21 |
- "os" |
|
| 22 |
- "os/exec" |
|
| 23 |
- |
|
| 24 | 21 |
exutil "github.com/openshift/origin/test/extended/util" |
| 22 |
+ "github.com/openshift/origin/test/extended/util/jenkins" |
|
| 25 | 23 |
) |
| 26 | 24 |
|
| 27 |
-type JenkinsRef struct {
|
|
| 28 |
- oc *exutil.CLI |
|
| 29 |
- host string |
|
| 30 |
- port string |
|
| 31 |
- // The namespace in which the Jenkins server is running |
|
| 32 |
- namespace string |
|
| 33 |
- password string |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 | 25 |
const ( |
| 37 | 26 |
useLocalPluginSnapshotEnvVarName = "USE_SNAPSHOT_JENKINS_IMAGE" |
| 38 | 27 |
disableJenkinsMemoryStats = "DISABLE_JENKINS_MEMORY_MONITORING" |
| 39 | 28 |
localPluginSnapshotImage = "openshift/jenkins-plugin-snapshot-test:latest" |
| 40 | 29 |
) |
| 41 | 30 |
|
| 42 |
-// Struct can be marshalled into XML to represent a Jenkins workflow job definition. |
|
| 43 |
-type FlowDefinition struct {
|
|
| 44 |
- XMLName xml.Name `xml:"flow-definition"` |
|
| 45 |
- Plugin string `xml:"plugin,attr"` |
|
| 46 |
- KeepDependencies bool `xml:"keepDependencies"` |
|
| 47 |
- Definition Definition |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-type Definition struct {
|
|
| 51 |
- XMLName xml.Name `xml:"definition"` |
|
| 52 |
- Class string `xml:"class,attr"` |
|
| 53 |
- Plugin string `xml:"plugin,attr"` |
|
| 54 |
- Script string `xml:"script"` |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-// Builds a URI for the Jenkins server. |
|
| 58 |
-func (j *JenkinsRef) buildURI(resourcePathFormat string, a ...interface{}) string {
|
|
| 59 |
- resourcePath := fmt.Sprintf(resourcePathFormat, a...) |
|
| 60 |
- return fmt.Sprintf("http://%s:%v/%s", j.host, j.port, resourcePath)
|
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 |
-// Submits a GET request to this Jenkins server. |
|
| 64 |
-// Returns a response body and status code or an error. |
|
| 65 |
-func (j *JenkinsRef) getResource(resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 66 |
- uri := j.buildURI(resourcePathFormat, a...) |
|
| 67 |
- ginkgolog("Retrieving Jenkins resource: %q", uri)
|
|
| 68 |
- req, err := http.NewRequest("GET", uri, nil)
|
|
| 69 |
- if err != nil {
|
|
| 70 |
- return "", 0, fmt.Errorf("Unable to build request for uri %q: %v", uri, err)
|
|
| 71 |
- } |
|
| 72 |
- |
|
| 73 |
- // http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi |
|
| 74 |
- req.Close = true |
|
| 75 |
- |
|
| 76 |
- req.SetBasicAuth("admin", j.password)
|
|
| 77 |
- client := &http.Client{}
|
|
| 78 |
- resp, err := client.Do(req) |
|
| 79 |
- |
|
| 80 |
- if err != nil {
|
|
| 81 |
- return "", 0, fmt.Errorf("Unable to GET uri %q: %v", uri, err)
|
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- defer resp.Body.Close() |
|
| 85 |
- status := resp.StatusCode |
|
| 86 |
- |
|
| 87 |
- body, err := ioutil.ReadAll(resp.Body) |
|
| 88 |
- if err != nil {
|
|
| 89 |
- return "", 0, fmt.Errorf("Error reading GET response %q: %v", uri, err)
|
|
| 90 |
- } |
|
| 91 |
- |
|
| 92 |
- return string(body), status, nil |
|
| 93 |
-} |
|
| 94 |
- |
|
| 95 |
-// Sends a POST to the Jenkins server. If a body is specified, it should be XML. |
|
| 96 |
-// Returns response body and status code or an error. |
|
| 97 |
-func (j *JenkinsRef) postXML(reqBody io.Reader, resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 98 |
- return j.post(reqBody, resourcePathFormat, "application/xml", a...) |
|
| 99 |
-} |
|
| 100 |
- |
|
| 101 |
-// Sends a POST to the Jenkins server. Returns response body and status code or an error. |
|
| 102 |
-func (j *JenkinsRef) post(reqBody io.Reader, resourcePathFormat, contentType string, a ...interface{}) (string, int, error) {
|
|
| 103 |
- uri := j.buildURI(resourcePathFormat, a...) |
|
| 104 |
- |
|
| 105 |
- req, err := http.NewRequest("POST", uri, reqBody)
|
|
| 106 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 107 |
- |
|
| 108 |
- // http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi |
|
| 109 |
- req.Close = true |
|
| 110 |
- |
|
| 111 |
- if reqBody != nil {
|
|
| 112 |
- req.Header.Set("Content-Type", contentType)
|
|
| 113 |
- req.Header.Del("Expect") // jenkins will return 417 if we have an expect hdr
|
|
| 114 |
- } |
|
| 115 |
- req.SetBasicAuth("admin", j.password)
|
|
| 116 |
- |
|
| 117 |
- client := &http.Client{}
|
|
| 118 |
- resp, err := client.Do(req) |
|
| 119 |
- if err != nil {
|
|
| 120 |
- return "", 0, fmt.Errorf("Error posting request to %q: %v", uri, err)
|
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- defer resp.Body.Close() |
|
| 124 |
- status := resp.StatusCode |
|
| 125 |
- |
|
| 126 |
- body, err := ioutil.ReadAll(resp.Body) |
|
| 127 |
- if err != nil {
|
|
| 128 |
- return "", 0, fmt.Errorf("Error reading post response body %q: %v", uri, err)
|
|
| 129 |
- } |
|
| 130 |
- |
|
| 131 |
- return string(body), status, nil |
|
| 132 |
-} |
|
| 133 |
- |
|
| 134 |
-// Creates simple entry in the GinkgoWriter. |
|
| 31 |
+// ginkgolog creates simple entry in the GinkgoWriter. |
|
| 135 | 32 |
func ginkgolog(format string, a ...interface{}) {
|
| 136 | 33 |
fmt.Fprintf(g.GinkgoWriter, format+"\n", a...) |
| 137 | 34 |
} |
| 138 | 35 |
|
| 139 |
-// Repeatedly tries to GET a jenkins resource with an acceptable |
|
| 140 |
-// HTTP status. Retries for the specified duration. |
|
| 141 |
-func (j *JenkinsRef) getResourceWithStatus(validStatusList []int, timeout time.Duration, resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 142 |
- var retBody string |
|
| 143 |
- var retStatus int |
|
| 144 |
- err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 145 |
- body, status, err := j.getResource(resourcePathFormat, a...) |
|
| 146 |
- if err != nil {
|
|
| 147 |
- ginkgolog("Error accessing resource: %v", err)
|
|
| 148 |
- return false, nil |
|
| 149 |
- } |
|
| 150 |
- var found bool |
|
| 151 |
- for _, s := range validStatusList {
|
|
| 152 |
- if status == s {
|
|
| 153 |
- found = true |
|
| 154 |
- break |
|
| 155 |
- } |
|
| 156 |
- } |
|
| 157 |
- if !found {
|
|
| 158 |
- ginkgolog("Expected http status [%v] during GET by recevied [%v]", validStatusList, status)
|
|
| 159 |
- return false, nil |
|
| 160 |
- } |
|
| 161 |
- retBody = body |
|
| 162 |
- retStatus = status |
|
| 163 |
- return true, nil |
|
| 164 |
- }) |
|
| 165 |
- if err != nil {
|
|
| 166 |
- uri := j.buildURI(resourcePathFormat, a...) |
|
| 167 |
- return "", retStatus, fmt.Errorf("Error waiting for status %v from resource path %s: %v", validStatusList, uri, err)
|
|
| 168 |
- } |
|
| 169 |
- return retBody, retStatus, nil |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-// Waits for a particular HTTP status and HTML matching a particular |
|
| 173 |
-// pattern to be returned by this Jenkins server. An error will be returned |
|
| 174 |
-// if the condition is not matched within the timeout period. |
|
| 175 |
-func (j *JenkinsRef) waitForContent(verificationRegEx string, verificationStatus int, timeout time.Duration, resourcePathFormat string, a ...interface{}) (string, error) {
|
|
| 176 |
- var matchingContent = "" |
|
| 177 |
- err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 178 |
- |
|
| 179 |
- content, _, err := j.getResourceWithStatus([]int{verificationStatus}, timeout, resourcePathFormat, a...)
|
|
| 180 |
- if err != nil {
|
|
| 181 |
- return false, nil |
|
| 182 |
- } |
|
| 183 |
- |
|
| 184 |
- if len(verificationRegEx) > 0 {
|
|
| 185 |
- re := regexp.MustCompile(verificationRegEx) |
|
| 186 |
- if re.MatchString(content) {
|
|
| 187 |
- matchingContent = content |
|
| 188 |
- return true, nil |
|
| 189 |
- } else {
|
|
| 190 |
- ginkgolog("Content did not match verification regex %q:\n %v", verificationRegEx, content)
|
|
| 191 |
- return false, nil |
|
| 192 |
- } |
|
| 193 |
- } else {
|
|
| 194 |
- matchingContent = content |
|
| 195 |
- return true, nil |
|
| 196 |
- } |
|
| 197 |
- }) |
|
| 198 |
- |
|
| 199 |
- if err != nil {
|
|
| 200 |
- uri := j.buildURI(resourcePathFormat, a...) |
|
| 201 |
- return "", fmt.Errorf("Error waiting for status %v and verification regex %q from resource path %s: %v", verificationStatus, verificationRegEx, uri, err)
|
|
| 202 |
- } else {
|
|
| 203 |
- return matchingContent, nil |
|
| 204 |
- } |
|
| 205 |
-} |
|
| 206 |
- |
|
| 207 |
-// Submits XML to create a named item on the Jenkins server. |
|
| 208 |
-func (j *JenkinsRef) createItem(name string, itemDefXML string) {
|
|
| 209 |
- g.By(fmt.Sprintf("Creating new jenkins item: %s", name))
|
|
| 210 |
- _, status, err := j.postXML(bytes.NewBufferString(itemDefXML), "createItem?name=%s", name) |
|
| 211 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 212 |
- o.ExpectWithOffset(1, status).To(o.Equal(200)) |
|
| 213 |
-} |
|
| 214 |
- |
|
| 215 |
-type JobMon struct {
|
|
| 216 |
- j *JenkinsRef |
|
| 217 |
- lastBuildNumber string |
|
| 218 |
- buildNumber string |
|
| 219 |
- jobName string |
|
| 220 |
-} |
|
| 221 |
- |
|
| 222 |
-// Returns the current buildNumber on the named project OR "new" if |
|
| 223 |
-// there are no builds against a job yet. |
|
| 224 |
-func (j *JenkinsRef) getJobBuildNumber(name string, timeout time.Duration) (string, error) {
|
|
| 225 |
- body, status, err := j.getResourceWithStatus([]int{200, 404}, timeout, "job/%s/lastBuild/buildNumber", name)
|
|
| 226 |
- if err != nil {
|
|
| 227 |
- return "", err |
|
| 228 |
- } |
|
| 229 |
- if status != 200 {
|
|
| 230 |
- return "new", nil |
|
| 231 |
- } |
|
| 232 |
- return body, nil |
|
| 233 |
-} |
|
| 234 |
- |
|
| 235 |
-// Waits for the timestamp on the Jenkins job to change. Returns |
|
| 236 |
-// and error if the timeout expires. |
|
| 237 |
-func (jmon *JobMon) await(timeout time.Duration) error {
|
|
| 238 |
- err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 239 |
- |
|
| 240 |
- buildNumber, err := jmon.j.getJobBuildNumber(jmon.jobName, time.Minute) |
|
| 241 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 242 |
- |
|
| 243 |
- ginkgolog("Checking build number for job %q current[%v] vs last[%v]", jmon.jobName, buildNumber, jmon.lastBuildNumber)
|
|
| 244 |
- if buildNumber == jmon.lastBuildNumber {
|
|
| 245 |
- return false, nil |
|
| 246 |
- } |
|
| 247 |
- |
|
| 248 |
- if jmon.buildNumber == "" {
|
|
| 249 |
- jmon.buildNumber = buildNumber |
|
| 250 |
- } |
|
| 251 |
- body, status, err := jmon.j.getResource("job/%s/%s/api/json?depth=1", jmon.jobName, jmon.buildNumber)
|
|
| 252 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 253 |
- o.ExpectWithOffset(1, status).To(o.Equal(200)) |
|
| 254 |
- |
|
| 255 |
- body = strings.ToLower(body) |
|
| 256 |
- if strings.Contains(body, "\"building\":true") {
|
|
| 257 |
- ginkgolog("Jenkins job %q still building:\n%s\n\n", jmon.jobName, body)
|
|
| 258 |
- return false, nil |
|
| 259 |
- } |
|
| 260 |
- |
|
| 261 |
- if strings.Contains(body, "\"result\":null") {
|
|
| 262 |
- ginkgolog("Jenkins job %q still building result:\n%s\n\n", jmon.jobName, body)
|
|
| 263 |
- return false, nil |
|
| 264 |
- } |
|
| 265 |
- |
|
| 266 |
- ginkgolog("Jenkins job %q build complete:\n%s\n\n", jmon.jobName, body)
|
|
| 267 |
- return true, nil |
|
| 268 |
- }) |
|
| 269 |
- return err |
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-// Triggers a named Jenkins job. The job can be monitored with the |
|
| 273 |
-// returned object. |
|
| 274 |
-func (j *JenkinsRef) startJob(jobName string) *JobMon {
|
|
| 275 |
- lastBuildNumber, err := j.getJobBuildNumber(jobName, time.Minute) |
|
| 276 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 277 |
- |
|
| 278 |
- jmon := &JobMon{
|
|
| 279 |
- j: j, |
|
| 280 |
- lastBuildNumber: lastBuildNumber, |
|
| 281 |
- buildNumber: "", |
|
| 282 |
- jobName: jobName, |
|
| 283 |
- } |
|
| 284 |
- |
|
| 285 |
- ginkgolog("Current timestamp for [%s]: %q", jobName, jmon.lastBuildNumber)
|
|
| 286 |
- g.By(fmt.Sprintf("Starting jenkins job: %s", jobName))
|
|
| 287 |
- _, status, err := j.postXML(nil, "job/%s/build?delay=0sec", jobName) |
|
| 288 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 289 |
- o.ExpectWithOffset(1, status).To(o.Equal(201)) |
|
| 290 |
- |
|
| 291 |
- return jmon |
|
| 292 |
-} |
|
| 293 |
- |
|
| 294 |
-// Returns the content of a Jenkins job XML file. Instances of the |
|
| 295 |
-// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 296 |
-// Variables named in the vars map will also be replaced with their |
|
| 297 |
-// corresponding value. |
|
| 298 |
-func (j *JenkinsRef) readJenkinsJobUsingVars(filename, namespace string, vars map[string]string) string {
|
|
| 299 |
- pre := exutil.FixturePath("testdata", "jenkins-plugin", filename)
|
|
| 300 |
- post := exutil.ArtifactPath(filename) |
|
| 301 |
- |
|
| 302 |
- if vars == nil {
|
|
| 303 |
- vars = map[string]string{}
|
|
| 304 |
- } |
|
| 305 |
- vars["PROJECT_NAME"] = namespace |
|
| 306 |
- err := exutil.VarSubOnFile(pre, post, vars) |
|
| 307 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 308 |
- |
|
| 309 |
- data, err := ioutil.ReadFile(post) |
|
| 310 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 311 |
- return string(data) |
|
| 312 |
-} |
|
| 313 |
- |
|
| 314 |
-// Returns the content of a Jenkins job XML file. Instances of the |
|
| 315 |
-// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 316 |
-func (j *JenkinsRef) readJenkinsJob(filename, namespace string) string {
|
|
| 317 |
- return j.readJenkinsJobUsingVars(filename, namespace, nil) |
|
| 318 |
-} |
|
| 319 |
- |
|
| 320 |
-// Returns an XML string defining a Jenkins workflow/pipeline DSL job. Instances of the |
|
| 321 |
-// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 322 |
-func (j *JenkinsRef) buildDSLJob(namespace string, scriptLines ...string) (string, error) {
|
|
| 323 |
- script := strings.Join(scriptLines, "\n") |
|
| 324 |
- script = strings.Replace(script, "PROJECT_NAME", namespace, -1) |
|
| 325 |
- fd := FlowDefinition{
|
|
| 326 |
- Plugin: "workflow-job@2.7", |
|
| 327 |
- Definition: Definition{
|
|
| 328 |
- Class: "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition", |
|
| 329 |
- Plugin: "workflow-cps@2.18", |
|
| 330 |
- Script: script, |
|
| 331 |
- }, |
|
| 332 |
- } |
|
| 333 |
- output, err := xml.MarshalIndent(fd, " ", " ") |
|
| 334 |
- ginkgolog("Formulated DSL Project XML:\n%s\n\n", output)
|
|
| 335 |
- return string(output), err |
|
| 336 |
-} |
|
| 337 |
- |
|
| 338 |
-// Returns the console logs of a particular buildNumber. |
|
| 339 |
-func (j *JenkinsRef) getJobConsoleLogs(jobName, buildNumber string) (string, error) {
|
|
| 340 |
- return j.waitForContent("", 200, 10*time.Minute, "job/%s/%s/consoleText", jobName, buildNumber)
|
|
| 341 |
-} |
|
| 342 |
- |
|
| 343 |
-// Returns the last build associated with a Jenkins job. |
|
| 344 |
-func (j *JenkinsRef) getLastJobConsoleLogs(jobName string) (string, error) {
|
|
| 345 |
- return j.getJobConsoleLogs(jobName, "lastBuild") |
|
| 346 |
-} |
|
| 347 |
- |
|
| 348 | 36 |
// Loads a Jenkins related template using new-app. |
| 349 | 37 |
func loadFixture(oc *exutil.CLI, filename string) {
|
| 350 | 38 |
resourcePath := exutil.FixturePath("testdata", "jenkins-plugin", filename)
|
| ... | ... |
@@ -385,33 +71,6 @@ func assertEnvVars(oc *exutil.CLI, buildPrefix string, varsToFind map[string]str |
| 385 | 385 |
} |
| 386 | 386 |
} |
| 387 | 387 |
|
| 388 |
-func getAdminPassword(oc *exutil.CLI) string {
|
|
| 389 |
- envs, err := oc.Run("set").Args("env", "dc/jenkins", "--list").Output()
|
|
| 390 |
- o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 391 |
- kvs := strings.Split(envs, "\n") |
|
| 392 |
- for _, kv := range kvs {
|
|
| 393 |
- if strings.HasPrefix(kv, "JENKINS_PASSWORD=") {
|
|
| 394 |
- s := strings.Split(kv, "=") |
|
| 395 |
- fmt.Fprintf(g.GinkgoWriter, "\nJenkins admin password %s\n", s[1]) |
|
| 396 |
- return s[1] |
|
| 397 |
- } |
|
| 398 |
- } |
|
| 399 |
- return "password" |
|
| 400 |
-} |
|
| 401 |
- |
|
| 402 |
-// Finds the pod running Jenkins |
|
| 403 |
-func findJenkinsPod(oc *exutil.CLI) *kapi.Pod {
|
|
| 404 |
- pods, err := exutil.GetDeploymentConfigPods(oc, "jenkins") |
|
| 405 |
- o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 406 |
- |
|
| 407 |
- if pods == nil || pods.Items == nil {
|
|
| 408 |
- g.Fail("No pods matching jenkins deploymentconfig in namespace " + oc.Namespace())
|
|
| 409 |
- } |
|
| 410 |
- |
|
| 411 |
- o.ExpectWithOffset(1, len(pods.Items)).To(o.Equal(1)) |
|
| 412 |
- return &pods.Items[0] |
|
| 413 |
-} |
|
| 414 |
- |
|
| 415 | 388 |
// Stands up a simple pod which can be used for exec commands |
| 416 | 389 |
func initExecPod(oc *exutil.CLI) *kapi.Pod {
|
| 417 | 390 |
// Create a running pod in which we can execute our commands |
| ... | ... |
@@ -456,7 +115,7 @@ var memoryOverragePattern = regexp.MustCompile(`\s+rss\s+5\d\d\d\d\d\d\d\d`) |
| 456 | 456 |
var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin", func() {
|
| 457 | 457 |
defer g.GinkgoRecover() |
| 458 | 458 |
var oc = exutil.NewCLI("jenkins-plugin", exutil.KubeConfigPath())
|
| 459 |
- var j *JenkinsRef |
|
| 459 |
+ var j *jenkins.JenkinsRef |
|
| 460 | 460 |
var dcLogFollow *exec.Cmd |
| 461 | 461 |
var dcLogStdOut, dcLogStdErr *bytes.Buffer |
| 462 | 462 |
var ticker *time.Ticker |
| ... | ... |
@@ -467,12 +126,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 467 | 467 |
ticker.Stop() |
| 468 | 468 |
} |
| 469 | 469 |
|
| 470 |
- oc.SetNamespace(j.namespace) |
|
| 470 |
+ oc.SetNamespace(j.Namespace()) |
|
| 471 | 471 |
ginkgolog("Jenkins DC description follows. If there were issues, check to see if there were any restarts in the jenkins pod.")
|
| 472 | 472 |
exutil.DumpDeploymentLogs("jenkins", oc)
|
| 473 | 473 |
|
| 474 | 474 |
// Destroy the Jenkins namespace |
| 475 |
- oc.Run("delete").Args("project", j.namespace).Execute()
|
|
| 475 |
+ oc.Run("delete").Args("project", j.Namespace()).Execute()
|
|
| 476 | 476 |
if dcLogFollow != nil && dcLogStdOut != nil && dcLogStdErr != nil {
|
| 477 | 477 |
ginkgolog("Waiting for Jenkins DC log follow to terminate")
|
| 478 | 478 |
dcLogFollow.Process.Wait() |
| ... | ... |
@@ -548,26 +207,10 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 548 | 548 |
err = exutil.WaitForADeploymentToComplete(oc.KubeClient().Core().ReplicationControllers(oc.Namespace()), "jenkins", oc) |
| 549 | 549 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 550 | 550 |
|
| 551 |
- g.By("get ip and port for jenkins service")
|
|
| 552 |
- serviceIP, err := oc.Run("get").Args("svc", "jenkins", "--config", exutil.KubeConfigPath()).Template("{{.spec.clusterIP}}").Output()
|
|
| 553 |
- o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 554 |
- port, err := oc.Run("get").Args("svc", "jenkins", "--config", exutil.KubeConfigPath()).Template("{{ $x := index .spec.ports 0}}{{$x.port}}").Output()
|
|
| 555 |
- o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 556 |
- |
|
| 557 |
- g.By("get admin password")
|
|
| 558 |
- password := getAdminPassword(oc) |
|
| 559 |
- o.Expect(password).ShouldNot(o.BeEmpty()) |
|
| 560 |
- |
|
| 561 |
- j = &JenkinsRef{
|
|
| 562 |
- oc: oc, |
|
| 563 |
- host: serviceIP, |
|
| 564 |
- port: port, |
|
| 565 |
- namespace: jenkinsNamespace, |
|
| 566 |
- password: password, |
|
| 567 |
- } |
|
| 551 |
+ j = jenkins.NewRef(oc) |
|
| 568 | 552 |
|
| 569 | 553 |
g.By("wait for jenkins to come up")
|
| 570 |
- _, err = j.waitForContent("", 200, 10*time.Minute, "")
|
|
| 554 |
+ _, err = j.WaitForContent("", 200, 10*time.Minute, "")
|
|
| 571 | 555 |
|
| 572 | 556 |
if err != nil {
|
| 573 | 557 |
exutil.DumpDeploymentLogs("jenkins", oc)
|
| ... | ... |
@@ -578,11 +221,11 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 578 | 578 |
if useSnapshotImage {
|
| 579 | 579 |
g.By("verifying the test image is being used")
|
| 580 | 580 |
// for the test image, confirm that a snapshot version of the plugin is running in the jenkins image we'll test against |
| 581 |
- _, err = j.waitForContent(`About OpenShift Pipeline Jenkins Plugin ([0-9\.]+)-SNAPSHOT`, 200, 10*time.Minute, "/pluginManager/plugin/openshift-pipeline/thirdPartyLicenses") |
|
| 581 |
+ _, err = j.WaitForContent(`About OpenShift Pipeline Jenkins Plugin ([0-9\.]+)-SNAPSHOT`, 200, 10*time.Minute, "/pluginManager/plugin/openshift-pipeline/thirdPartyLicenses") |
|
| 582 | 582 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 583 | 583 |
} |
| 584 | 584 |
|
| 585 |
- jenkinsPod := findJenkinsPod(oc) |
|
| 585 |
+ jenkinsPod := jenkins.FindJenkinsPod(oc) |
|
| 586 | 586 |
|
| 587 | 587 |
if os.Getenv(disableJenkinsMemoryStats) == "" {
|
| 588 | 588 |
ticker = time.NewTicker(10 * time.Second) |
| ... | ... |
@@ -630,7 +273,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 630 | 630 |
oc.SetNamespace(testNamespace) |
| 631 | 631 |
|
| 632 | 632 |
g.By("set up policy for jenkins jobs in " + oc.Namespace())
|
| 633 |
- err = oc.Run("policy").Args("add-role-to-user", "edit", "system:serviceaccount:"+j.namespace+":jenkins").Execute()
|
|
| 633 |
+ err = oc.Run("policy").Args("add-role-to-user", "edit", "system:serviceaccount:"+j.Namespace()+":jenkins").Execute()
|
|
| 634 | 634 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 635 | 635 |
|
| 636 | 636 |
// Populate shared Jenkins namespace with artifacts that can be used by all tests |
| ... | ... |
@@ -646,10 +289,10 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 646 | 646 |
g.It("jenkins-plugin test trigger build including clone", func() {
|
| 647 | 647 |
|
| 648 | 648 |
jobName := "test-build-job" |
| 649 |
- data := j.readJenkinsJob("build-job.xml", oc.Namespace())
|
|
| 650 |
- j.createItem(jobName, data) |
|
| 651 |
- jmon := j.startJob(jobName) |
|
| 652 |
- jmon.await(10 * time.Minute) |
|
| 649 |
+ data := j.ReadJenkinsJob("build-job.xml", oc.Namespace())
|
|
| 650 |
+ j.CreateItem(jobName, data) |
|
| 651 |
+ jmon := j.StartJob(jobName) |
|
| 652 |
+ jmon.Await(10 * time.Minute) |
|
| 653 | 653 |
|
| 654 | 654 |
// the build and deployment is by far the most time consuming portion of the test jenkins job; |
| 655 | 655 |
// we leverage some of the openshift utilities for waiting for the deployment before we poll |
| ... | ... |
@@ -661,7 +304,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 661 | 661 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 662 | 662 |
|
| 663 | 663 |
g.By("get build console logs and see if succeeded")
|
| 664 |
- logs, err := j.waitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 664 |
+ logs, err := j.WaitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 665 | 665 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 666 | 666 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 667 | 667 |
|
| ... | ... |
@@ -671,12 +314,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 671 | 671 |
o.Expect(strings.Contains(out, "Jenkins job")).To(o.BeTrue()) |
| 672 | 672 |
|
| 673 | 673 |
jobName = "test-build-clone-job" |
| 674 |
- data = j.readJenkinsJob("build-job-clone.xml", oc.Namespace())
|
|
| 675 |
- j.createItem(jobName, data) |
|
| 676 |
- jmon = j.startJob(jobName) |
|
| 677 |
- jmon.await(10 * time.Minute) |
|
| 674 |
+ data = j.ReadJenkinsJob("build-job-clone.xml", oc.Namespace())
|
|
| 675 |
+ j.CreateItem(jobName, data) |
|
| 676 |
+ jmon = j.StartJob(jobName) |
|
| 677 |
+ jmon.Await(10 * time.Minute) |
|
| 678 | 678 |
g.By("get clone build console logs and see if succeeded")
|
| 679 |
- logs, err = j.waitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 679 |
+ logs, err = j.WaitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 680 | 680 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 681 | 681 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 682 | 682 |
|
| ... | ... |
@@ -693,10 +336,10 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 693 | 693 |
g.It("jenkins-plugin test trigger build with slave", func() {
|
| 694 | 694 |
|
| 695 | 695 |
jobName := "test-build-job-slave" |
| 696 |
- data := j.readJenkinsJob("build-job-slave.xml", oc.Namespace())
|
|
| 697 |
- j.createItem(jobName, data) |
|
| 698 |
- jmon := j.startJob(jobName) |
|
| 699 |
- jmon.await(10 * time.Minute) |
|
| 696 |
+ data := j.ReadJenkinsJob("build-job-slave.xml", oc.Namespace())
|
|
| 697 |
+ j.CreateItem(jobName, data) |
|
| 698 |
+ jmon := j.StartJob(jobName) |
|
| 699 |
+ jmon.Await(10 * time.Minute) |
|
| 700 | 700 |
|
| 701 | 701 |
// the build and deployment is by far the most time consuming portion of the test jenkins job; |
| 702 | 702 |
// we leverage some of the openshift utilities for waiting for the deployment before we poll |
| ... | ... |
@@ -708,12 +351,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 708 | 708 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 709 | 709 |
|
| 710 | 710 |
g.By("get build console logs and see if succeeded")
|
| 711 |
- logs, err := j.waitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 711 |
+ logs, err := j.WaitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 712 | 712 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 713 | 713 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 714 | 714 |
|
| 715 | 715 |
g.By("get build console logs and confirm ran on slave")
|
| 716 |
- logs, err = j.waitForContent("Building remotely on", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 716 |
+ logs, err = j.WaitForContent("Building remotely on", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 717 | 717 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 718 | 718 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 719 | 719 |
|
| ... | ... |
@@ -723,17 +366,17 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 723 | 723 |
|
| 724 | 724 |
jobsToCreate := map[string]string{"test-create-obj": "create-job.xml", "test-delete-obj": "delete-job.xml", "test-delete-obj-labels": "delete-job-labels.xml", "test-delete-obj-keys": "delete-job-keys.xml"}
|
| 725 | 725 |
for jobName, jobConfig := range jobsToCreate {
|
| 726 |
- data := j.readJenkinsJob(jobConfig, oc.Namespace()) |
|
| 727 |
- j.createItem(jobName, data) |
|
| 726 |
+ data := j.ReadJenkinsJob(jobConfig, oc.Namespace()) |
|
| 727 |
+ j.CreateItem(jobName, data) |
|
| 728 | 728 |
} |
| 729 | 729 |
|
| 730 | 730 |
jobsToRun := []apiObjJob{{"test-create-obj", true}, {"test-delete-obj", false}, {"test-create-obj", true}, {"test-delete-obj-labels", false}, {"test-create-obj", true}, {"test-delete-obj-keys", false}}
|
| 731 | 731 |
for _, job := range jobsToRun {
|
| 732 |
- jmon := j.startJob(job.jobName) |
|
| 733 |
- jmon.await(10 * time.Minute) |
|
| 732 |
+ jmon := j.StartJob(job.jobName) |
|
| 733 |
+ jmon.Await(10 * time.Minute) |
|
| 734 | 734 |
|
| 735 | 735 |
g.By("get build console logs and see if succeeded")
|
| 736 |
- logs, err := j.waitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", job.jobName)
|
|
| 736 |
+ logs, err := j.WaitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", job.jobName)
|
|
| 737 | 737 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 738 | 738 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 739 | 739 |
out, err := oc.Run("get").Args("bc", "forcepull-bldr").Output()
|
| ... | ... |
@@ -747,12 +390,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 747 | 747 |
g.It("jenkins-plugin test trigger build with envs", func() {
|
| 748 | 748 |
|
| 749 | 749 |
jobName := "test-build-with-env-job" |
| 750 |
- data := j.readJenkinsJob("build-with-env-job.xml", oc.Namespace())
|
|
| 751 |
- j.createItem(jobName, data) |
|
| 752 |
- jmon := j.startJob(jobName) |
|
| 753 |
- jmon.await(10 * time.Minute) |
|
| 750 |
+ data := j.ReadJenkinsJob("build-with-env-job.xml", oc.Namespace())
|
|
| 751 |
+ j.CreateItem(jobName, data) |
|
| 752 |
+ jmon := j.StartJob(jobName) |
|
| 753 |
+ jmon.Await(10 * time.Minute) |
|
| 754 | 754 |
|
| 755 |
- logs, err := j.getLastJobConsoleLogs(jobName) |
|
| 755 |
+ logs, err := j.GetLastJobConsoleLogs(jobName) |
|
| 756 | 756 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", logs)
|
| 757 | 757 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 758 | 758 |
|
| ... | ... |
@@ -764,7 +407,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 764 | 764 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 765 | 765 |
|
| 766 | 766 |
g.By("get build console logs and see if succeeded")
|
| 767 |
- _, err = j.waitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 767 |
+ _, err = j.WaitForContent("Finished: SUCCESS", 200, 10*time.Minute, "job/%s/lastBuild/consoleText", jobName)
|
|
| 768 | 768 |
|
| 769 | 769 |
assertEnvVars(oc, "frontend-", map[string]string{
|
| 770 | 770 |
"a": "b", |
| ... | ... |
@@ -779,16 +422,16 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 779 | 779 |
buildsBefore, err := oc.Client().Builds(oc.Namespace()).List(kapi.ListOptions{})
|
| 780 | 780 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 781 | 781 |
|
| 782 |
- data, err := j.buildDSLJob(oc.Namespace(), |
|
| 782 |
+ data, err := j.BuildDSLJob(oc.Namespace(), |
|
| 783 | 783 |
"node{",
|
| 784 | 784 |
"openshiftBuild( namespace:'PROJECT_NAME', bldCfg: 'frontend', env: [ [ name : 'a', value : 'b' ], [ name : 'C', value : 'D' ], [ name : 'e', value : '' ] ] )", |
| 785 | 785 |
"}", |
| 786 | 786 |
) |
| 787 | 787 |
|
| 788 | 788 |
jobName := "test-build-dsl-job" |
| 789 |
- j.createItem(jobName, data) |
|
| 790 |
- monitor := j.startJob(jobName) |
|
| 791 |
- err = monitor.await(10 * time.Minute) |
|
| 789 |
+ j.CreateItem(jobName, data) |
|
| 790 |
+ monitor := j.StartJob(jobName) |
|
| 791 |
+ err = monitor.Await(10 * time.Minute) |
|
| 792 | 792 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 793 | 793 |
|
| 794 | 794 |
err = wait.Poll(10*time.Second, 10*time.Minute, func() (bool, error) {
|
| ... | ... |
@@ -801,7 +444,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 801 | 801 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 802 | 802 |
o.Expect(len(buildsAfter.Items)).To(o.Equal(len(buildsBefore.Items) + 1)) |
| 803 | 803 |
|
| 804 |
- log, err := j.getLastJobConsoleLogs(jobName) |
|
| 804 |
+ log, err := j.GetLastJobConsoleLogs(jobName) |
|
| 805 | 805 |
ginkgolog("Job logs>>\n%s\n\n", log)
|
| 806 | 806 |
|
| 807 | 807 |
assertEnvVars(oc, "frontend-", map[string]string{
|
| ... | ... |
@@ -817,7 +460,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 817 | 817 |
targetPod := initExecPod(oc) |
| 818 | 818 |
targetContainer := targetPod.Spec.Containers[0] |
| 819 | 819 |
|
| 820 |
- data, err := j.buildDSLJob(oc.Namespace(), |
|
| 820 |
+ data, err := j.BuildDSLJob(oc.Namespace(), |
|
| 821 | 821 |
"node{",
|
| 822 | 822 |
fmt.Sprintf("openshiftExec( namespace:'PROJECT_NAME', pod: '%s', command: [ 'echo', 'hello', 'world', '1' ] )", targetPod.Name),
|
| 823 | 823 |
fmt.Sprintf("openshiftExec( namespace:'PROJECT_NAME', pod: '%s', command: 'echo', arguments : [ 'hello', 'world', '2' ] )", targetPod.Name),
|
| ... | ... |
@@ -829,12 +472,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 829 | 829 |
) |
| 830 | 830 |
|
| 831 | 831 |
jobName := "test-exec-dsl-job" |
| 832 |
- j.createItem(jobName, data) |
|
| 833 |
- monitor := j.startJob(jobName) |
|
| 834 |
- err = monitor.await(10 * time.Minute) |
|
| 832 |
+ j.CreateItem(jobName, data) |
|
| 833 |
+ monitor := j.StartJob(jobName) |
|
| 834 |
+ err = monitor.Await(10 * time.Minute) |
|
| 835 | 835 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 836 | 836 |
|
| 837 |
- log, err := j.getLastJobConsoleLogs(jobName) |
|
| 837 |
+ log, err := j.GetLastJobConsoleLogs(jobName) |
|
| 838 | 838 |
ginkgolog("Job logs>>\n%s\n\n", log)
|
| 839 | 839 |
|
| 840 | 840 |
o.Expect(strings.Contains(log, "hello world 1")).To(o.BeTrue()) |
| ... | ... |
@@ -851,16 +494,16 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 851 | 851 |
targetContainer := targetPod.Spec.Containers[0] |
| 852 | 852 |
|
| 853 | 853 |
jobName := "test-build-with-env-steps" |
| 854 |
- data := j.readJenkinsJobUsingVars("build-with-exec-steps.xml", oc.Namespace(), map[string]string{
|
|
| 854 |
+ data := j.ReadJenkinsJobUsingVars("build-with-exec-steps.xml", oc.Namespace(), map[string]string{
|
|
| 855 | 855 |
"POD_NAME": targetPod.Name, |
| 856 | 856 |
"CONTAINER_NAME": targetContainer.Name, |
| 857 | 857 |
}) |
| 858 | 858 |
|
| 859 |
- j.createItem(jobName, data) |
|
| 860 |
- jmon := j.startJob(jobName) |
|
| 861 |
- jmon.await(2 * time.Minute) |
|
| 859 |
+ j.CreateItem(jobName, data) |
|
| 860 |
+ jmon := j.StartJob(jobName) |
|
| 861 |
+ jmon.Await(2 * time.Minute) |
|
| 862 | 862 |
|
| 863 |
- log, err := j.getLastJobConsoleLogs(jobName) |
|
| 863 |
+ log, err := j.GetLastJobConsoleLogs(jobName) |
|
| 864 | 864 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", log)
|
| 865 | 865 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 866 | 866 |
|
| ... | ... |
@@ -868,16 +511,16 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 868 | 868 |
|
| 869 | 869 |
// Now run without specifying container |
| 870 | 870 |
jobName = "test-build-with-env-steps-no-container" |
| 871 |
- data = j.readJenkinsJobUsingVars("build-with-exec-steps.xml", oc.Namespace(), map[string]string{
|
|
| 871 |
+ data = j.ReadJenkinsJobUsingVars("build-with-exec-steps.xml", oc.Namespace(), map[string]string{
|
|
| 872 | 872 |
"POD_NAME": targetPod.Name, |
| 873 | 873 |
"CONTAINER_NAME": "", |
| 874 | 874 |
}) |
| 875 | 875 |
|
| 876 |
- j.createItem(jobName, data) |
|
| 877 |
- jmon = j.startJob(jobName) |
|
| 878 |
- jmon.await(2 * time.Minute) |
|
| 876 |
+ j.CreateItem(jobName, data) |
|
| 877 |
+ jmon = j.StartJob(jobName) |
|
| 878 |
+ jmon.Await(2 * time.Minute) |
|
| 879 | 879 |
|
| 880 |
- log, err = j.getLastJobConsoleLogs(jobName) |
|
| 880 |
+ log, err = j.GetLastJobConsoleLogs(jobName) |
|
| 881 | 881 |
ginkgolog("\n\nJenkins logs>\n%s\n\n", log)
|
| 882 | 882 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 883 | 883 |
|
| ... | ... |
@@ -898,13 +541,13 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 898 | 898 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 899 | 899 |
|
| 900 | 900 |
jobName := "test-multitag-job" |
| 901 |
- data := j.readJenkinsJob("multitag-job.xml", oc.Namespace())
|
|
| 902 |
- j.createItem(jobName, data) |
|
| 903 |
- monitor := j.startJob(jobName) |
|
| 904 |
- err = monitor.await(10 * time.Minute) |
|
| 901 |
+ data := j.ReadJenkinsJob("multitag-job.xml", oc.Namespace())
|
|
| 902 |
+ j.CreateItem(jobName, data) |
|
| 903 |
+ monitor := j.StartJob(jobName) |
|
| 904 |
+ err = monitor.Await(10 * time.Minute) |
|
| 905 | 905 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 906 | 906 |
|
| 907 |
- log, err := j.getLastJobConsoleLogs(jobName) |
|
| 907 |
+ log, err := j.GetLastJobConsoleLogs(jobName) |
|
| 908 | 908 |
ginkgolog("Job logs>>\n%s\n\n", log)
|
| 909 | 909 |
|
| 910 | 910 |
// Assert stream tagging results |
| ... | ... |
@@ -966,14 +609,14 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 966 | 966 |
|
| 967 | 967 |
// Allow jenkins service account to edit the new namespace |
| 968 | 968 |
oc.SetNamespace(anotherNamespace) |
| 969 |
- err = oc.Run("policy").Args("add-role-to-user", "edit", "system:serviceaccount:"+j.namespace+":jenkins").Execute()
|
|
| 969 |
+ err = oc.Run("policy").Args("add-role-to-user", "edit", "system:serviceaccount:"+j.Namespace()+":jenkins").Execute()
|
|
| 970 | 970 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 971 | 971 |
|
| 972 | 972 |
oc.SetNamespace(testNamespace) |
| 973 | 973 |
|
| 974 | 974 |
ginkgolog("Using testNamespace: %q and currentNamespace: %q", testNamespace, oc.Namespace())
|
| 975 | 975 |
|
| 976 |
- data, err := j.buildDSLJob(oc.Namespace(), |
|
| 976 |
+ data, err := j.BuildDSLJob(oc.Namespace(), |
|
| 977 | 977 |
"node{",
|
| 978 | 978 |
"openshiftTag( namespace:'PROJECT_NAME', srcStream: 'multitag', srcTag: 'orig', destStream: 'multitag', destTag: 'prod' )", |
| 979 | 979 |
"openshiftTag( namespace:'PROJECT_NAME', srcStream: 'multitag', srcTag: 'orig', destStream: 'multitag2', destTag: 'prod1, prod2, prod3' )", |
| ... | ... |
@@ -987,14 +630,14 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 987 | 987 |
) |
| 988 | 988 |
|
| 989 | 989 |
jobName := "test-multitag-dsl-job" |
| 990 |
- j.createItem(jobName, data) |
|
| 991 |
- monitor := j.startJob(jobName) |
|
| 992 |
- err = monitor.await(10 * time.Minute) |
|
| 990 |
+ j.CreateItem(jobName, data) |
|
| 991 |
+ monitor := j.StartJob(jobName) |
|
| 992 |
+ err = monitor.Await(10 * time.Minute) |
|
| 993 | 993 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 994 | 994 |
|
| 995 | 995 |
time.Sleep(10 * time.Second) |
| 996 | 996 |
|
| 997 |
- log, err := j.getLastJobConsoleLogs(jobName) |
|
| 997 |
+ log, err := j.GetLastJobConsoleLogs(jobName) |
|
| 998 | 998 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 999 | 999 |
ginkgolog("Job logs>>\n%s\n\n", log)
|
| 1000 | 1000 |
|
| ... | ... |
@@ -1028,8 +671,8 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 1028 | 1028 |
testImageStreamSCM := func(jobXMLFile string) {
|
| 1029 | 1029 |
jobName := "test-imagestream-scm" |
| 1030 | 1030 |
g.By("creating a jenkins job with an imagestream SCM")
|
| 1031 |
- data := j.readJenkinsJob(jobXMLFile, oc.Namespace()) |
|
| 1032 |
- j.createItem(jobName, data) |
|
| 1031 |
+ data := j.ReadJenkinsJob(jobXMLFile, oc.Namespace()) |
|
| 1032 |
+ j.CreateItem(jobName, data) |
|
| 1033 | 1033 |
|
| 1034 | 1034 |
// Because polling is enabled, a job should start automatically and fail |
| 1035 | 1035 |
// Wait for it to run and fail |
| ... | ... |
@@ -1038,7 +681,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 1038 | 1038 |
jobStatusURI := "api/xml?tree=%s&xpath=%s" |
| 1039 | 1039 |
g.By("waiting for initial job to complete")
|
| 1040 | 1040 |
wait.Poll(10*time.Second, 10*time.Minute, func() (bool, error) {
|
| 1041 |
- result, status, err := j.getResource(jobStatusURI, tree, xpath) |
|
| 1041 |
+ result, status, err := j.GetResource(jobStatusURI, tree, xpath) |
|
| 1042 | 1042 |
o.Expect(err).NotTo(o.HaveOccurred()) |
| 1043 | 1043 |
if status == 200 && strings.Contains(result, "red") {
|
| 1044 | 1044 |
return true, nil |
| ... | ... |
@@ -1069,12 +712,12 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 1069 | 1069 |
g.It("jenkins-plugin test connection test", func() {
|
| 1070 | 1070 |
|
| 1071 | 1071 |
jobName := "test-build-job" |
| 1072 |
- data := j.readJenkinsJob("build-job.xml", oc.Namespace())
|
|
| 1073 |
- j.createItem(jobName, data) |
|
| 1072 |
+ data := j.ReadJenkinsJob("build-job.xml", oc.Namespace())
|
|
| 1073 |
+ j.CreateItem(jobName, data) |
|
| 1074 | 1074 |
|
| 1075 | 1075 |
g.By("trigger test connection logic, check for success")
|
| 1076 | 1076 |
testConnectionBody := bytes.NewBufferString("apiURL=&authToken=")
|
| 1077 |
- result, code, err := j.post(testConnectionBody, "job/test-build-job/descriptorByName/com.openshift.jenkins.plugins.pipeline.OpenShiftBuilder/testConnection", "application/x-www-form-urlencoded") |
|
| 1077 |
+ result, code, err := j.Post(testConnectionBody, "job/test-build-job/descriptorByName/com.openshift.jenkins.plugins.pipeline.OpenShiftBuilder/testConnection", "application/x-www-form-urlencoded") |
|
| 1078 | 1078 |
if code != 200 {
|
| 1079 | 1079 |
err = fmt.Errorf("Expected return code of 200")
|
| 1080 | 1080 |
} |
| ... | ... |
@@ -1085,7 +728,7 @@ var _ = g.Describe("[image_ecosystem][jenkins][Slow] openshift pipeline plugin",
|
| 1085 | 1085 |
|
| 1086 | 1086 |
g.By("trigger test connection logic, check for failure")
|
| 1087 | 1087 |
testConnectionBody = bytes.NewBufferString("apiURL=https%3A%2F%2F1.2.3.4&authToken=")
|
| 1088 |
- result, code, err = j.post(testConnectionBody, "job/test-build-job/descriptorByName/com.openshift.jenkins.plugins.pipeline.OpenShiftBuilder/testConnection", "application/x-www-form-urlencoded") |
|
| 1088 |
+ result, code, err = j.Post(testConnectionBody, "job/test-build-job/descriptorByName/com.openshift.jenkins.plugins.pipeline.OpenShiftBuilder/testConnection", "application/x-www-form-urlencoded") |
|
| 1089 | 1089 |
if code != 200 {
|
| 1090 | 1090 |
err = fmt.Errorf("Expected return code of 200")
|
| 1091 | 1091 |
} |
| 1092 | 1092 |
deleted file mode 100644 |
| ... | ... |
@@ -1,88 +0,0 @@ |
| 1 |
-{
|
|
| 2 |
- "kind": "Template", |
|
| 3 |
- "apiVersion": "v1", |
|
| 4 |
- "metadata": {
|
|
| 5 |
- "name": "jenkins-pipeline-example", |
|
| 6 |
- "annotations": {
|
|
| 7 |
- "description": "This is used to test the jenkins pipeline strategy", |
|
| 8 |
- "iconClass": "icon-jenkins" |
|
| 9 |
- } |
|
| 10 |
- }, |
|
| 11 |
- "objects": [ |
|
| 12 |
- {
|
|
| 13 |
- "kind": "BuildConfig", |
|
| 14 |
- "apiVersion": "v1", |
|
| 15 |
- "metadata": {
|
|
| 16 |
- "name": "sample-pipeline", |
|
| 17 |
- "labels": {
|
|
| 18 |
- "name": "sample-pipeline" |
|
| 19 |
- }, |
|
| 20 |
- "annotations": {
|
|
| 21 |
- "pipeline.alpha.openshift.io/uses": "[{\"name\": \"frontend\", \"namespace\": \"\", \"kind\": \"DeploymentConfig\"}]"
|
|
| 22 |
- } |
|
| 23 |
- }, |
|
| 24 |
- "spec": {
|
|
| 25 |
- "strategy": {
|
|
| 26 |
- "type": "JenkinsPipeline", |
|
| 27 |
- "jenkinsPipelineStrategy": {
|
|
| 28 |
- "jenkinsfile": "node{\nstage 'build'\nopenshiftBuild(buildConfig: 'ruby-sample-build', showBuildLogs: 'true')\n}"
|
|
| 29 |
- } |
|
| 30 |
- } |
|
| 31 |
- } |
|
| 32 |
- }, |
|
| 33 |
- {
|
|
| 34 |
- "kind": "ImageStream", |
|
| 35 |
- "apiVersion": "v1", |
|
| 36 |
- "metadata": {
|
|
| 37 |
- "name": "origin-ruby-sample" |
|
| 38 |
- }, |
|
| 39 |
- "spec": {},
|
|
| 40 |
- "status": {
|
|
| 41 |
- "dockerImageRepository": "" |
|
| 42 |
- } |
|
| 43 |
- }, |
|
| 44 |
- {
|
|
| 45 |
- "kind": "BuildConfig", |
|
| 46 |
- "apiVersion": "v1", |
|
| 47 |
- "metadata": {
|
|
| 48 |
- "name": "ruby-sample-build", |
|
| 49 |
- "labels": {
|
|
| 50 |
- "name": "ruby-sample-build" |
|
| 51 |
- } |
|
| 52 |
- }, |
|
| 53 |
- "spec": {
|
|
| 54 |
- "source": {
|
|
| 55 |
- "type": "Git", |
|
| 56 |
- "git": {
|
|
| 57 |
- "uri": "https://github.com/openshift/ruby-hello-world.git" |
|
| 58 |
- } |
|
| 59 |
- }, |
|
| 60 |
- "strategy": {
|
|
| 61 |
- "type": "Source", |
|
| 62 |
- "sourceStrategy": {
|
|
| 63 |
- "from": {
|
|
| 64 |
- "kind": "ImageStreamTag", |
|
| 65 |
- "name": "ruby:2.2", |
|
| 66 |
- "namespace": "openshift" |
|
| 67 |
- } |
|
| 68 |
- } |
|
| 69 |
- }, |
|
| 70 |
- "output": {
|
|
| 71 |
- "to": {
|
|
| 72 |
- "kind": "ImageStreamTag", |
|
| 73 |
- "name": "origin-ruby-sample:latest" |
|
| 74 |
- } |
|
| 75 |
- }, |
|
| 76 |
- "resources": {}
|
|
| 77 |
- }, |
|
| 78 |
- "status": {
|
|
| 79 |
- "lastVersion": 0 |
|
| 80 |
- } |
|
| 81 |
- } |
|
| 82 |
- ], |
|
| 83 |
- "parameters": [ |
|
| 84 |
- ], |
|
| 85 |
- "labels": {
|
|
| 86 |
- "template": "jenkins-pipeline-test" |
|
| 87 |
- } |
|
| 88 |
-} |
| 89 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,55 @@ |
| 0 |
+package jenkins |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "strings" |
|
| 4 |
+ "time" |
|
| 5 |
+ |
|
| 6 |
+ o "github.com/onsi/gomega" |
|
| 7 |
+ |
|
| 8 |
+ "k8s.io/kubernetes/pkg/util/wait" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// JobMon is a Jenkins job monitor |
|
| 12 |
+type JobMon struct {
|
|
| 13 |
+ j *JenkinsRef |
|
| 14 |
+ lastBuildNumber string |
|
| 15 |
+ buildNumber string |
|
| 16 |
+ jobName string |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// Await waits for the timestamp on the Jenkins job to change. Returns |
|
| 20 |
+// and error if the timeout expires. |
|
| 21 |
+func (jmon *JobMon) Await(timeout time.Duration) error {
|
|
| 22 |
+ err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 23 |
+ |
|
| 24 |
+ buildNumber, err := jmon.j.GetJobBuildNumber(jmon.jobName, time.Minute) |
|
| 25 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 26 |
+ |
|
| 27 |
+ ginkgolog("Checking build number for job %q current[%v] vs last[%v]", jmon.jobName, buildNumber, jmon.lastBuildNumber)
|
|
| 28 |
+ if buildNumber == jmon.lastBuildNumber {
|
|
| 29 |
+ return false, nil |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ if jmon.buildNumber == "" {
|
|
| 33 |
+ jmon.buildNumber = buildNumber |
|
| 34 |
+ } |
|
| 35 |
+ body, status, err := jmon.j.GetResource("job/%s/%s/api/json?depth=1", jmon.jobName, jmon.buildNumber)
|
|
| 36 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 37 |
+ o.ExpectWithOffset(1, status).To(o.Equal(200)) |
|
| 38 |
+ |
|
| 39 |
+ body = strings.ToLower(body) |
|
| 40 |
+ if strings.Contains(body, "\"building\":true") {
|
|
| 41 |
+ ginkgolog("Jenkins job %q still building:\n%s\n\n", jmon.jobName, body)
|
|
| 42 |
+ return false, nil |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ if strings.Contains(body, "\"result\":null") {
|
|
| 46 |
+ ginkgolog("Jenkins job %q still building result:\n%s\n\n", jmon.jobName, body)
|
|
| 47 |
+ return false, nil |
|
| 48 |
+ } |
|
| 49 |
+ |
|
| 50 |
+ ginkgolog("Jenkins job %q build complete:\n%s\n\n", jmon.jobName, body)
|
|
| 51 |
+ return true, nil |
|
| 52 |
+ }) |
|
| 53 |
+ return err |
|
| 54 |
+} |
| 0 | 55 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,349 @@ |
| 0 |
+package jenkins |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/xml" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io" |
|
| 7 |
+ "io/ioutil" |
|
| 8 |
+ "net/http" |
|
| 9 |
+ "regexp" |
|
| 10 |
+ "strings" |
|
| 11 |
+ "time" |
|
| 12 |
+ |
|
| 13 |
+ g "github.com/onsi/ginkgo" |
|
| 14 |
+ o "github.com/onsi/gomega" |
|
| 15 |
+ |
|
| 16 |
+ kapi "k8s.io/kubernetes/pkg/api" |
|
| 17 |
+ "k8s.io/kubernetes/pkg/util/wait" |
|
| 18 |
+ |
|
| 19 |
+ exutil "github.com/openshift/origin/test/extended/util" |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 22 |
+// JenkinsRef represents a Jenkins instance running on an OpenShift server |
|
| 23 |
+type JenkinsRef struct {
|
|
| 24 |
+ oc *exutil.CLI |
|
| 25 |
+ host string |
|
| 26 |
+ port string |
|
| 27 |
+ // The namespace in which the Jenkins server is running |
|
| 28 |
+ namespace string |
|
| 29 |
+ password string |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+// FlowDefinition can be marshalled into XML to represent a Jenkins workflow job definition. |
|
| 33 |
+type FlowDefinition struct {
|
|
| 34 |
+ XMLName xml.Name `xml:"flow-definition"` |
|
| 35 |
+ Plugin string `xml:"plugin,attr"` |
|
| 36 |
+ KeepDependencies bool `xml:"keepDependencies"` |
|
| 37 |
+ Definition Definition |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// Definition is part of a FlowDefinition |
|
| 41 |
+type Definition struct {
|
|
| 42 |
+ XMLName xml.Name `xml:"definition"` |
|
| 43 |
+ Class string `xml:"class,attr"` |
|
| 44 |
+ Plugin string `xml:"plugin,attr"` |
|
| 45 |
+ Script string `xml:"script"` |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// ginkgolog creates simple entry in the GinkgoWriter. |
|
| 49 |
+func ginkgolog(format string, a ...interface{}) {
|
|
| 50 |
+ fmt.Fprintf(g.GinkgoWriter, format+"\n", a...) |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+// NewRef creates a jenkins reference from an OC client |
|
| 54 |
+func NewRef(oc *exutil.CLI) *JenkinsRef {
|
|
| 55 |
+ g.By("get ip and port for jenkins service")
|
|
| 56 |
+ serviceIP, err := oc.Run("get").Args("svc", "jenkins", "--config", exutil.KubeConfigPath()).Template("{{.spec.clusterIP}}").Output()
|
|
| 57 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 58 |
+ port, err := oc.Run("get").Args("svc", "jenkins", "--config", exutil.KubeConfigPath()).Template("{{ $x := index .spec.ports 0}}{{$x.port}}").Output()
|
|
| 59 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 60 |
+ |
|
| 61 |
+ g.By("get admin password")
|
|
| 62 |
+ password := GetAdminPassword(oc) |
|
| 63 |
+ o.Expect(password).ShouldNot(o.BeEmpty()) |
|
| 64 |
+ |
|
| 65 |
+ j := &JenkinsRef{
|
|
| 66 |
+ oc: oc, |
|
| 67 |
+ host: serviceIP, |
|
| 68 |
+ port: port, |
|
| 69 |
+ namespace: oc.Namespace(), |
|
| 70 |
+ password: password, |
|
| 71 |
+ } |
|
| 72 |
+ return j |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+// Namespace returns the Jenkins namespace |
|
| 76 |
+func (j *JenkinsRef) Namespace() string {
|
|
| 77 |
+ return j.namespace |
|
| 78 |
+} |
|
| 79 |
+ |
|
| 80 |
+// BuildURI builds a URI for the Jenkins server. |
|
| 81 |
+func (j *JenkinsRef) BuildURI(resourcePathFormat string, a ...interface{}) string {
|
|
| 82 |
+ resourcePath := fmt.Sprintf(resourcePathFormat, a...) |
|
| 83 |
+ return fmt.Sprintf("http://%s:%v/%s", j.host, j.port, resourcePath)
|
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// GetResource submits a GET request to this Jenkins server. |
|
| 87 |
+// Returns a response body and status code or an error. |
|
| 88 |
+func (j *JenkinsRef) GetResource(resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 89 |
+ uri := j.BuildURI(resourcePathFormat, a...) |
|
| 90 |
+ ginkgolog("Retrieving Jenkins resource: %q", uri)
|
|
| 91 |
+ req, err := http.NewRequest("GET", uri, nil)
|
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return "", 0, fmt.Errorf("Unable to build request for uri %q: %v", uri, err)
|
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ // http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi |
|
| 97 |
+ req.Close = true |
|
| 98 |
+ |
|
| 99 |
+ req.SetBasicAuth("admin", j.password)
|
|
| 100 |
+ client := &http.Client{}
|
|
| 101 |
+ resp, err := client.Do(req) |
|
| 102 |
+ |
|
| 103 |
+ if err != nil {
|
|
| 104 |
+ return "", 0, fmt.Errorf("Unable to GET uri %q: %v", uri, err)
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ defer resp.Body.Close() |
|
| 108 |
+ status := resp.StatusCode |
|
| 109 |
+ |
|
| 110 |
+ body, err := ioutil.ReadAll(resp.Body) |
|
| 111 |
+ if err != nil {
|
|
| 112 |
+ return "", 0, fmt.Errorf("Error reading GET response %q: %v", uri, err)
|
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ return string(body), status, nil |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+// Post sends a POST to the Jenkins server. Returns response body and status code or an error. |
|
| 119 |
+func (j *JenkinsRef) Post(reqBody io.Reader, resourcePathFormat, contentType string, a ...interface{}) (string, int, error) {
|
|
| 120 |
+ uri := j.BuildURI(resourcePathFormat, a...) |
|
| 121 |
+ |
|
| 122 |
+ req, err := http.NewRequest("POST", uri, reqBody)
|
|
| 123 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 124 |
+ |
|
| 125 |
+ // http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi |
|
| 126 |
+ req.Close = true |
|
| 127 |
+ |
|
| 128 |
+ if reqBody != nil {
|
|
| 129 |
+ req.Header.Set("Content-Type", contentType)
|
|
| 130 |
+ req.Header.Del("Expect") // jenkins will return 417 if we have an expect hdr
|
|
| 131 |
+ } |
|
| 132 |
+ req.SetBasicAuth("admin", j.password)
|
|
| 133 |
+ |
|
| 134 |
+ client := &http.Client{}
|
|
| 135 |
+ ginkgolog("Posting to Jenkins resource: %q", uri)
|
|
| 136 |
+ resp, err := client.Do(req) |
|
| 137 |
+ if err != nil {
|
|
| 138 |
+ return "", 0, fmt.Errorf("Error posting request to %q: %v", uri, err)
|
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ defer resp.Body.Close() |
|
| 142 |
+ status := resp.StatusCode |
|
| 143 |
+ |
|
| 144 |
+ body, err := ioutil.ReadAll(resp.Body) |
|
| 145 |
+ if err != nil {
|
|
| 146 |
+ return "", 0, fmt.Errorf("Error reading Post response body %q: %v", uri, err)
|
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ return string(body), status, nil |
|
| 150 |
+} |
|
| 151 |
+ |
|
| 152 |
+// PostXML sends a POST to the Jenkins server. If a body is specified, it should be XML. |
|
| 153 |
+// Returns response body and status code or an error. |
|
| 154 |
+func (j *JenkinsRef) PostXML(reqBody io.Reader, resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 155 |
+ return j.Post(reqBody, resourcePathFormat, "application/xml", a...) |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 158 |
+// GetResourceWithStatus repeatedly tries to GET a jenkins resource with an acceptable |
|
| 159 |
+// HTTP status. Retries for the specified duration. |
|
| 160 |
+func (j *JenkinsRef) GetResourceWithStatus(validStatusList []int, timeout time.Duration, resourcePathFormat string, a ...interface{}) (string, int, error) {
|
|
| 161 |
+ var retBody string |
|
| 162 |
+ var retStatus int |
|
| 163 |
+ err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 164 |
+ body, status, err := j.GetResource(resourcePathFormat, a...) |
|
| 165 |
+ if err != nil {
|
|
| 166 |
+ ginkgolog("Error accessing resource: %v", err)
|
|
| 167 |
+ return false, nil |
|
| 168 |
+ } |
|
| 169 |
+ var found bool |
|
| 170 |
+ for _, s := range validStatusList {
|
|
| 171 |
+ if status == s {
|
|
| 172 |
+ found = true |
|
| 173 |
+ break |
|
| 174 |
+ } |
|
| 175 |
+ } |
|
| 176 |
+ if !found {
|
|
| 177 |
+ ginkgolog("Expected http status [%v] during GET by recevied [%v]", validStatusList, status)
|
|
| 178 |
+ return false, nil |
|
| 179 |
+ } |
|
| 180 |
+ retBody = body |
|
| 181 |
+ retStatus = status |
|
| 182 |
+ return true, nil |
|
| 183 |
+ }) |
|
| 184 |
+ if err != nil {
|
|
| 185 |
+ uri := j.BuildURI(resourcePathFormat, a...) |
|
| 186 |
+ return "", retStatus, fmt.Errorf("Error waiting for status %v from resource path %s: %v", validStatusList, uri, err)
|
|
| 187 |
+ } |
|
| 188 |
+ return retBody, retStatus, nil |
|
| 189 |
+} |
|
| 190 |
+ |
|
| 191 |
+// WaitForContent waits for a particular HTTP status and HTML matching a particular |
|
| 192 |
+// pattern to be returned by this Jenkins server. An error will be returned |
|
| 193 |
+// if the condition is not matched within the timeout period. |
|
| 194 |
+func (j *JenkinsRef) WaitForContent(verificationRegEx string, verificationStatus int, timeout time.Duration, resourcePathFormat string, a ...interface{}) (string, error) {
|
|
| 195 |
+ var matchingContent = "" |
|
| 196 |
+ err := wait.Poll(10*time.Second, timeout, func() (bool, error) {
|
|
| 197 |
+ |
|
| 198 |
+ content, _, err := j.GetResourceWithStatus([]int{verificationStatus}, timeout, resourcePathFormat, a...)
|
|
| 199 |
+ if err != nil {
|
|
| 200 |
+ return false, nil |
|
| 201 |
+ } |
|
| 202 |
+ |
|
| 203 |
+ if len(verificationRegEx) > 0 {
|
|
| 204 |
+ re := regexp.MustCompile(verificationRegEx) |
|
| 205 |
+ if re.MatchString(content) {
|
|
| 206 |
+ matchingContent = content |
|
| 207 |
+ return true, nil |
|
| 208 |
+ } else {
|
|
| 209 |
+ ginkgolog("Content did not match verification regex %q:\n %v", verificationRegEx, content)
|
|
| 210 |
+ return false, nil |
|
| 211 |
+ } |
|
| 212 |
+ } else {
|
|
| 213 |
+ matchingContent = content |
|
| 214 |
+ return true, nil |
|
| 215 |
+ } |
|
| 216 |
+ }) |
|
| 217 |
+ |
|
| 218 |
+ if err != nil {
|
|
| 219 |
+ uri := j.BuildURI(resourcePathFormat, a...) |
|
| 220 |
+ return "", fmt.Errorf("Error waiting for status %v and verification regex %q from resource path %s: %v", verificationStatus, verificationRegEx, uri, err)
|
|
| 221 |
+ } else {
|
|
| 222 |
+ return matchingContent, nil |
|
| 223 |
+ } |
|
| 224 |
+} |
|
| 225 |
+ |
|
| 226 |
+// CreateItem submits XML to create a named item on the Jenkins server. |
|
| 227 |
+func (j *JenkinsRef) CreateItem(name string, itemDefXML string) {
|
|
| 228 |
+ g.By(fmt.Sprintf("Creating new jenkins item: %s", name))
|
|
| 229 |
+ _, status, err := j.PostXML(bytes.NewBufferString(itemDefXML), "CreateItem?name=%s", name) |
|
| 230 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 231 |
+ o.ExpectWithOffset(1, status).To(o.Equal(200)) |
|
| 232 |
+} |
|
| 233 |
+ |
|
| 234 |
+// GetJobBuildNumber returns the current buildNumber on the named project OR "new" if |
|
| 235 |
+// there are no builds against a job yet. |
|
| 236 |
+func (j *JenkinsRef) GetJobBuildNumber(name string, timeout time.Duration) (string, error) {
|
|
| 237 |
+ body, status, err := j.GetResourceWithStatus([]int{200, 404}, timeout, "job/%s/lastBuild/buildNumber", name)
|
|
| 238 |
+ if err != nil {
|
|
| 239 |
+ return "", err |
|
| 240 |
+ } |
|
| 241 |
+ if status != 200 {
|
|
| 242 |
+ return "new", nil |
|
| 243 |
+ } |
|
| 244 |
+ return body, nil |
|
| 245 |
+} |
|
| 246 |
+ |
|
| 247 |
+// StartJob triggers a named Jenkins job. The job can be monitored with the |
|
| 248 |
+// returned object. |
|
| 249 |
+func (j *JenkinsRef) StartJob(jobName string) *JobMon {
|
|
| 250 |
+ lastBuildNumber, err := j.GetJobBuildNumber(jobName, time.Minute) |
|
| 251 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 252 |
+ |
|
| 253 |
+ jmon := &JobMon{
|
|
| 254 |
+ j: j, |
|
| 255 |
+ lastBuildNumber: lastBuildNumber, |
|
| 256 |
+ buildNumber: "", |
|
| 257 |
+ jobName: jobName, |
|
| 258 |
+ } |
|
| 259 |
+ |
|
| 260 |
+ ginkgolog("Current timestamp for [%s]: %q", jobName, jmon.lastBuildNumber)
|
|
| 261 |
+ g.By(fmt.Sprintf("Starting jenkins job: %s", jobName))
|
|
| 262 |
+ _, status, err := j.PostXML(nil, "job/%s/build?delay=0sec", jobName) |
|
| 263 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 264 |
+ o.ExpectWithOffset(1, status).To(o.Equal(201)) |
|
| 265 |
+ |
|
| 266 |
+ return jmon |
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+// ReadJenkinsJobUsingVars returns the content of a Jenkins job XML file. Instances of the |
|
| 270 |
+// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 271 |
+// Variables named in the vars map will also be replaced with their |
|
| 272 |
+// corresponding value. |
|
| 273 |
+func (j *JenkinsRef) ReadJenkinsJobUsingVars(filename, namespace string, vars map[string]string) string {
|
|
| 274 |
+ pre := exutil.FixturePath("testdata", "jenkins-plugin", filename)
|
|
| 275 |
+ post := exutil.ArtifactPath(filename) |
|
| 276 |
+ |
|
| 277 |
+ if vars == nil {
|
|
| 278 |
+ vars = map[string]string{}
|
|
| 279 |
+ } |
|
| 280 |
+ vars["PROJECT_NAME"] = namespace |
|
| 281 |
+ err := exutil.VarSubOnFile(pre, post, vars) |
|
| 282 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 283 |
+ |
|
| 284 |
+ data, err := ioutil.ReadFile(post) |
|
| 285 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 286 |
+ return string(data) |
|
| 287 |
+} |
|
| 288 |
+ |
|
| 289 |
+// ReadJenkinsJob returns the content of a Jenkins job XML file. Instances of the |
|
| 290 |
+// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 291 |
+func (j *JenkinsRef) ReadJenkinsJob(filename, namespace string) string {
|
|
| 292 |
+ return j.ReadJenkinsJobUsingVars(filename, namespace, nil) |
|
| 293 |
+} |
|
| 294 |
+ |
|
| 295 |
+// BuildDSLJob returns an XML string defining a Jenkins workflow/pipeline DSL job. Instances of the |
|
| 296 |
+// string "PROJECT_NAME" are replaced with the specified namespace. |
|
| 297 |
+func (j *JenkinsRef) BuildDSLJob(namespace string, scriptLines ...string) (string, error) {
|
|
| 298 |
+ script := strings.Join(scriptLines, "\n") |
|
| 299 |
+ script = strings.Replace(script, "PROJECT_NAME", namespace, -1) |
|
| 300 |
+ fd := FlowDefinition{
|
|
| 301 |
+ Plugin: "workflow-job@2.7", |
|
| 302 |
+ Definition: Definition{
|
|
| 303 |
+ Class: "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition", |
|
| 304 |
+ Plugin: "workflow-cps@2.18", |
|
| 305 |
+ Script: script, |
|
| 306 |
+ }, |
|
| 307 |
+ } |
|
| 308 |
+ output, err := xml.MarshalIndent(fd, " ", " ") |
|
| 309 |
+ ginkgolog("Formulated DSL Project XML:\n%s\n\n", output)
|
|
| 310 |
+ return string(output), err |
|
| 311 |
+} |
|
| 312 |
+ |
|
| 313 |
+// GetJobConsoleLogs returns the console logs of a particular buildNumber. |
|
| 314 |
+func (j *JenkinsRef) GetJobConsoleLogs(jobName, buildNumber string) (string, error) {
|
|
| 315 |
+ return j.WaitForContent("", 200, 10*time.Minute, "job/%s/%s/consoleText", jobName, buildNumber)
|
|
| 316 |
+} |
|
| 317 |
+ |
|
| 318 |
+// GetLastJobConsoleLogs returns the last build associated with a Jenkins job. |
|
| 319 |
+func (j *JenkinsRef) GetLastJobConsoleLogs(jobName string) (string, error) {
|
|
| 320 |
+ return j.GetJobConsoleLogs(jobName, "lastBuild") |
|
| 321 |
+} |
|
| 322 |
+ |
|
| 323 |
+func GetAdminPassword(oc *exutil.CLI) string {
|
|
| 324 |
+ envs, err := oc.Run("set").Args("env", "dc/jenkins", "--list").Output()
|
|
| 325 |
+ o.Expect(err).NotTo(o.HaveOccurred()) |
|
| 326 |
+ kvs := strings.Split(envs, "\n") |
|
| 327 |
+ for _, kv := range kvs {
|
|
| 328 |
+ if strings.HasPrefix(kv, "JENKINS_PASSWORD=") {
|
|
| 329 |
+ s := strings.Split(kv, "=") |
|
| 330 |
+ fmt.Fprintf(g.GinkgoWriter, "\nJenkins admin password %s\n", s[1]) |
|
| 331 |
+ return s[1] |
|
| 332 |
+ } |
|
| 333 |
+ } |
|
| 334 |
+ return "password" |
|
| 335 |
+} |
|
| 336 |
+ |
|
| 337 |
+// Finds the pod running Jenkins |
|
| 338 |
+func FindJenkinsPod(oc *exutil.CLI) *kapi.Pod {
|
|
| 339 |
+ pods, err := exutil.GetDeploymentConfigPods(oc, "jenkins") |
|
| 340 |
+ o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred()) |
|
| 341 |
+ |
|
| 342 |
+ if pods == nil || pods.Items == nil {
|
|
| 343 |
+ g.Fail("No pods matching jenkins deploymentconfig in namespace " + oc.Namespace())
|
|
| 344 |
+ } |
|
| 345 |
+ |
|
| 346 |
+ o.ExpectWithOffset(1, len(pods.Items)).To(o.Equal(1)) |
|
| 347 |
+ return &pods.Items[0] |
|
| 348 |
+} |