fix: refactored to support context API

- Context API support is added to the Jenkins API interface.
This commit is contained in:
Ansh Garhewal 2024-07-21 16:12:28 +05:30
parent 62a1e7c077
commit 9d12e547d4
No known key found for this signature in database
10 changed files with 68 additions and 63 deletions

View File

@ -2,6 +2,7 @@ package client
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
@ -20,41 +21,41 @@ var (
// Jenkins defines Jenkins API.
type Jenkins interface {
GenerateToken(userName, tokenName string) (*UserToken, error)
Info() (*gojenkins.ExecutorResponse, error)
SafeRestart() error
CreateNode(name string, numExecutors int, description string, remoteFS string, label string, options ...interface{}) (*gojenkins.Node, error)
DeleteNode(name string) (bool, error)
CreateFolder(name string, parents ...string) (*gojenkins.Folder, error)
CreateJobInFolder(config string, jobName string, parentIDs ...string) (*gojenkins.Job, error)
CreateJob(config string, options ...interface{}) (*gojenkins.Job, error)
Info(ctx context.Context) (*gojenkins.ExecutorResponse, error)
SafeRestart(ctx context.Context) error
CreateNode(ctx context.Context, name string, numExecutors int, description string, remoteFS string, label string, options ...interface{}) (*gojenkins.Node, error)
DeleteNode(ctx context.Context, name string) (bool, error)
CreateFolder(ctx context.Context, name string, parents ...string) (*gojenkins.Folder, error)
CreateJobInFolder(ctx context.Context, config string, jobName string, parentIDs ...string) (*gojenkins.Job, error)
CreateJob(ctx context.Context, config string, options ...interface{}) (*gojenkins.Job, error)
CreateOrUpdateJob(config, jobName string) (*gojenkins.Job, bool, error)
RenameJob(job string, name string) *gojenkins.Job
CopyJob(copyFrom string, newName string) (*gojenkins.Job, error)
DeleteJob(name string) (bool, error)
BuildJob(name string, options ...interface{}) (int64, error)
GetNode(name string) (*gojenkins.Node, error)
GetLabel(name string) (*gojenkins.Label, error)
RenameJob(ctx context.Context, job string, name string) *gojenkins.Job
CopyJob(ctx context.Context, copyFrom string, newName string) (*gojenkins.Job, error)
CreateView(ctx context.Context, name string, viewType string) (*gojenkins.View, error)
DeleteJob(ctx context.Context, name string) (bool, error)
BuildJob(ctx context.Context, name string, options map[string]string) (int64, error)
GetNode(ctx context.Context, name string) (*gojenkins.Node, error)
GetLabel(ctx context.Context, name string) (*gojenkins.Label, error)
GetBuild(jobName string, number int64) (*gojenkins.Build, error)
GetJob(id string, parentIDs ...string) (*gojenkins.Job, error)
GetSubJob(parentID string, childID string) (*gojenkins.Job, error)
GetFolder(id string, parents ...string) (*gojenkins.Folder, error)
GetAllNodes() ([]*gojenkins.Node, error)
GetAllBuildIds(job string) ([]gojenkins.JobBuild, error)
GetAllJobNames() ([]gojenkins.InnerJob, error)
GetAllJobs() ([]*gojenkins.Job, error)
GetQueue() (*gojenkins.Queue, error)
GetJob(ctx context.Context, id string, parentIDs ...string) (*gojenkins.Job, error)
GetSubJob(ctx context.Context, parentID string, childID string) (*gojenkins.Job, error)
GetFolder(ctx context.Context, id string, parents ...string) (*gojenkins.Folder, error)
GetAllNodes(ctx context.Context) ([]*gojenkins.Node, error)
GetAllBuildIds(ctx context.Context, job string) ([]gojenkins.JobBuild, error)
GetAllJobNames(context.Context) ([]gojenkins.InnerJob, error)
GetAllJobs(context.Context) ([]*gojenkins.Job, error)
GetQueue(context.Context) (*gojenkins.Queue, error)
GetQueueUrl() string
GetQueueItem(id int64) (*gojenkins.Task, error)
GetArtifactData(id string) (*gojenkins.FingerPrintResponse, error)
GetQueueItem(ctx context.Context, id int64) (*gojenkins.Task, error)
GetArtifactData(ctx context.Context, id string) (*gojenkins.FingerPrintResponse, error)
GetPlugins(depth int) (*gojenkins.Plugins, error)
UninstallPlugin(name string) error
HasPlugin(name string) (*gojenkins.Plugin, error)
InstallPlugin(name string, version string) error
ValidateFingerPrint(id string) (bool, error)
GetView(name string) (*gojenkins.View, error)
GetAllViews() ([]*gojenkins.View, error)
CreateView(name string, viewType string) (*gojenkins.View, error)
Poll() (int, error)
UninstallPlugin(ctx context.Context, name string) error
HasPlugin(ctx context.Context, name string) (*gojenkins.Plugin, error)
InstallPlugin(ctx context.Context, name string, version string) error
ValidateFingerPrint(ctx context.Context, id string) (bool, error)
GetView(ctx context.Context, name string) (*gojenkins.View, error)
GetAllViews(context.Context) ([]*gojenkins.View, error)
Poll(ctx context.Context) (int, error)
ExecuteScript(groovyScript string) (logs string, err error)
GetNodeSecret(name string) (string, error)
}
@ -90,15 +91,15 @@ func (t *setBearerToken) RoundTrip(r *http.Request) (*http.Response, error) {
// CreateOrUpdateJob creates or updates a job from config.
func (jenkins *jenkins) CreateOrUpdateJob(config, jobName string) (job *gojenkins.Job, created bool, err error) {
// create or update
job, err = jenkins.GetJob(jobName)
job, err = jenkins.GetJob(context.TODO(), jobName)
if isNotFoundError(err) {
job, err = jenkins.CreateJob(config, jobName)
job, err = jenkins.CreateJob(context.TODO(), config, jobName)
return job, true, errors.WithStack(err)
} else if err != nil {
return job, false, errors.WithStack(err)
}
err = job.UpdateConfig(config)
err = job.UpdateConfig(context.TODO(), config)
return job, false, errors.WithStack(err)
}
@ -173,11 +174,11 @@ func newClient(url, userName, passwordOrToken string) (Jenkins, error) {
Client: httpClient,
BasicAuth: basicAuth,
}
if _, err := jenkinsClient.Init(); err != nil {
if _, err := jenkinsClient.Init(context.TODO()); err != nil {
return nil, errors.Wrap(err, "couldn't init Jenkins API client")
}
status, err := jenkinsClient.Poll()
status, err := jenkinsClient.Poll(context.TODO())
if err != nil {
return nil, errors.Wrap(err, "couldn't poll data from Jenkins API")
}
@ -234,7 +235,7 @@ func (jenkins *jenkins) GetNodeSecret(name string) (string, error) {
// You can supply depth parameter, to limit how much data is returned.
func (jenkins *jenkins) GetPlugins(depth int) (*gojenkins.Plugins, error) {
p := gojenkins.Plugins{Jenkins: &jenkins.Jenkins, Raw: new(gojenkins.PluginResponse), Base: "/pluginManager", Depth: depth}
statusCode, err := p.Poll()
statusCode, err := p.Poll(context.TODO())
if err != nil {
return nil, err
}

View File

@ -1,13 +1,14 @@
package client
import (
"context"
"net/url"
"github.com/bndr/gojenkins"
)
func (jenkins *jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build, error) {
job, err := jenkins.GetJob(jobName)
job, err := jenkins.GetJob(context.TODO(), jobName)
if err != nil {
return nil, err
}
@ -21,7 +22,7 @@ func (jenkins *jenkins) GetBuild(jobName string, number int64) (*gojenkins.Build
job.Raw.URL = jobURL.RequestURI()
// workaround end
build, err := job.GetBuild(number)
build, err := job.GetBuild(context.TODO(), number)
if err != nil {
return nil, err

View File

@ -5,6 +5,7 @@
package client
import (
"context"
"reflect"
"github.com/bndr/gojenkins"
@ -63,7 +64,7 @@ func (mr *MockJenkinsMockRecorder) GenerateToken(userName, tokenName interface{}
}
// Info mocks base method
func (m *MockJenkins) Info() (*gojenkins.ExecutorResponse, error) {
func (m *MockJenkins) Info(context.Context) (*gojenkins.ExecutorResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Info")
ret0, _ := ret[0].(*gojenkins.ExecutorResponse)
@ -78,7 +79,7 @@ func (mr *MockJenkinsMockRecorder) Info() *gomock.Call {
}
// SafeRestart mocks base method
func (m *MockJenkins) SafeRestart() error {
func (m *MockJenkins) SafeRestart(context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SafeRestart")
ret0, _ := ret[0].(error)
@ -92,7 +93,7 @@ func (mr *MockJenkinsMockRecorder) SafeRestart() *gomock.Call {
}
// CreateNode mocks base method
func (m *MockJenkins) CreateNode(name string, numExecutors int, description, remoteFS, label string, options ...interface{}) (*gojenkins.Node, error) {
func (m *MockJenkins) CreateNode(ctx context.Context,name string, numExecutors int, description, remoteFS, label string, options ...interface{}) (*gojenkins.Node, error) {
m.ctrl.T.Helper()
varargs := []interface{}{name, numExecutors, description, remoteFS, label}
for _, a := range options {
@ -112,7 +113,7 @@ func (mr *MockJenkinsMockRecorder) CreateNode(name, numExecutors, description, r
}
// DeleteNode mocks base method
func (m *MockJenkins) DeleteNode(name string) (bool, error) {
func (m *MockJenkins) DeleteNode(ctx context.Context,name string) (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteNode", name)
ret0, _ := ret[0].(bool)
@ -127,7 +128,7 @@ func (mr *MockJenkinsMockRecorder) DeleteNode(name interface{}) *gomock.Call {
}
// CreateFolder mocks base method
func (m *MockJenkins) CreateFolder(name string, parents ...string) (*gojenkins.Folder, error) {
func (m *MockJenkins) CreateFolder(ctx context.Context,name string, parents ...string) (*gojenkins.Folder, error) {
m.ctrl.T.Helper()
varargs := []interface{}{name}
for _, a := range parents {
@ -147,7 +148,7 @@ func (mr *MockJenkinsMockRecorder) CreateFolder(name interface{}, parents ...int
}
// CreateJobInFolder mocks base method
func (m *MockJenkins) CreateJobInFolder(config, jobName string, parentIDs ...string) (*gojenkins.Job, error) {
func (m *MockJenkins) CreateJobInFolder(ctx context.Context,config, jobName string, parentIDs ...string) (*gojenkins.Job, error) {
m.ctrl.T.Helper()
varargs := []interface{}{config, jobName}
for _, a := range parentIDs {
@ -160,14 +161,14 @@ func (m *MockJenkins) CreateJobInFolder(config, jobName string, parentIDs ...str
}
// CreateJobInFolder indicates an expected call of CreateJobInFolder
func (mr *MockJenkinsMockRecorder) CreateJobInFolder(config, jobName interface{}, parentIDs ...interface{}) *gomock.Call {
func (mr *MockJenkinsMockRecorder) CreateJobInFolder(ctx context.Context,config, jobName interface{}, parentIDs ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{config, jobName}, parentIDs...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateJobInFolder", reflect.TypeOf((*MockJenkins)(nil).CreateJobInFolder), varargs...)
}
// CreateJob mocks base method
func (m *MockJenkins) CreateJob(config string, options ...interface{}) (*gojenkins.Job, error) {
func (m *MockJenkins) CreateJob(ctx context.Context,config string, options ...interface{}) (*gojenkins.Job, error) {
m.ctrl.T.Helper()
varargs := []interface{}{config}
for _, a := range options {

View File

@ -2,6 +2,7 @@ package client
import (
"bytes"
"context"
"fmt"
"net/http"
"net/url"
@ -38,13 +39,13 @@ func (jenkins *jenkins) executeScript(script string, verifier string) (string, e
data.Set("script", fullScript)
ar := gojenkins.NewAPIRequest("POST", "/scriptText", bytes.NewBufferString(data.Encode()))
if err := jenkins.Requester.SetCrumb(ar); err != nil {
if err := jenkins.Requester.SetCrumb(context.TODO(), ar); err != nil {
return output, err
}
ar.SetHeader("Content-Type", "application/x-www-form-urlencoded")
ar.Suffix = ""
r, err := jenkins.Requester.Do(ar, &output, nil)
r, err := jenkins.Requester.Do(context.TODO(), ar, &output, nil)
if err != nil {
return "", errors.Wrapf(err, "couldn't execute groovy script, logs '%s'", output)
}

View File

@ -1,6 +1,7 @@
package client
import (
"context"
"fmt"
"net/http"
@ -34,7 +35,7 @@ func (jenkins *jenkins) GenerateToken(userName, tokenName string) (*UserToken, e
base: fmt.Sprintf("/user/%s/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken", userName)}
endpoint := token.base
data := map[string]string{"newTokenName": tokenName}
r, err := jenkins.Requester.Post(endpoint, nil, token.raw, data)
r, err := jenkins.Requester.Post(context.TODO(), endpoint, nil, token.raw, data)
if err != nil {
return nil, errors.Wrap(err, "couldn't generate API token")
}

View File

@ -369,11 +369,11 @@ func (s *seedJobs) isRecreatePodNeeded(jenkins v1alpha2.Jenkins) bool {
// createAgent deploys Jenkins agent to Kubernetes cluster
func (s *seedJobs) createAgent(jenkinsClient jenkinsclient.Jenkins, k8sClient client.Client, jenkinsManifest *v1alpha2.Jenkins, namespace string, agentName string) error {
_, err := jenkinsClient.GetNode(agentName)
_, err := jenkinsClient.GetNode(context.TODO(), agentName)
// Create node if not exists
if err != nil && err.Error() == "No node found" {
_, err = jenkinsClient.CreateNode(agentName, 5, "The jenkins-operator generated agent", "/home/jenkins", agentName)
_, err = jenkinsClient.CreateNode(context.TODO(), agentName, 5, "The jenkins-operator generated agent", "/home/jenkins", agentName)
if err != nil {
return stackerr.WithStack(err)
}

View File

@ -103,7 +103,7 @@ var _ = Describe("Jenkins controller", func() {
jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name)
defer cleanUpFunc()
checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient)
err := jenkinsClient.SafeRestart()
err := jenkinsClient.SafeRestart(context.TODO())
Expect(err).NotTo(HaveOccurred())
waitForJenkinsSafeRestart(jenkinsClient)
checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient)

View File

@ -25,7 +25,7 @@ func waitForJobCreation(jenkinsClient client.Jenkins, jobID string) {
var err error
Eventually(func() (bool, error) {
_, err = jenkinsClient.GetJob(jobID)
_, err = jenkinsClient.GetJob(context.TODO(), jobID)
if err != nil {
return false, err
}
@ -38,9 +38,9 @@ func waitForJobCreation(jenkinsClient client.Jenkins, jobID string) {
func verifyJobBuildsAfterRestoreBackup(jenkinsClient client.Jenkins, jobID string) {
By("checking if job builds after restoring backup")
job, err := jenkinsClient.GetJob(jobID)
job, err := jenkinsClient.GetJob(context.TODO(), jobID)
Expect(err).NotTo(HaveOccurred())
build, err := job.GetLastBuild()
build, err := job.GetLastBuild(context.TODO())
Expect(err).NotTo(HaveOccurred())
Expect(build.GetBuildNumber()).To(Equal(int64(1)))

View File

@ -68,7 +68,7 @@ func verifyJenkinsSeedJobs(jenkinsClient jenkinsclient.Jenkins, seedJobs []seedJ
for _, requireJobName := range seedJob.JobNames {
err = try.Until(func() (end bool, err error) {
_, err = jenkinsClient.GetJob(requireJobName)
_, err = jenkinsClient.GetJob(context.TODO(), requireJobName)
return err == nil, err
}, time.Second*2, time.Minute*2)
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Jenkins job '%s' not created by seed job ID '%s'\n", requireJobName, seedJob.ID))
@ -244,11 +244,11 @@ for (BuildStep step : jobRef.getBuildersList()) {
func verifyJobCanBeRun(jenkinsClient jenkinsclient.Jenkins, jobID string) {
By("retrieving created Jenkins job")
job, err := jenkinsClient.GetJob(jobID)
job, err := jenkinsClient.GetJob(context.TODO(), jobID)
Expect(err).To(BeNil())
By("running Jenkins job")
_, err = job.InvokeSimple(map[string]string{})
_, err = job.InvokeSimple(context.TODO(), map[string]string{})
Expect(err).To(BeNil())
// FIXME: waitForJobToFinish use
@ -265,12 +265,12 @@ func verifyJobHasBeenRunCorrectly(jenkinsClient jenkinsclient.Jenkins, jobID str
)
Eventually(func() (bool, error) {
job, err = jenkinsClient.GetJob(jobID)
job, err = jenkinsClient.GetJob(context.TODO(), jobID)
Expect(err).To(BeNil())
build, err = job.GetLastBuild()
build, err = job.GetLastBuild(context.TODO())
Expect(err).To(BeNil())
By("evaluating correctness of the outcome")
return build.IsGood(), err
return build.IsGood(context.TODO()), err
}, time.Duration(110)*retryInterval, retryInterval).Should(BeTrue())
}

View File

@ -87,7 +87,7 @@ func waitForJenkinsSafeRestart(jenkinsClient jenkinsclient.Jenkins) {
ginkgo.By("waiting for Jenkins safe restart")
gomega.Eventually(func() (bool, error) {
status, err := jenkinsClient.Poll()
status, err := jenkinsClient.Poll(context.TODO())
_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Safe restart status: %+v, err: %s\n", status, err)
if err != nil {
return false, err