Refactoring for jenkins client (#366)

This commit is contained in:
khelil 2020-05-06 11:31:16 +02:00 committed by GitHub
parent 12ecfaa2b3
commit eb8b2e32e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 302 additions and 295 deletions

2
go.mod
View File

@ -23,7 +23,7 @@ require (
go.uber.org/zap v1.14.1
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
golang.org/x/tools v0.0.0-20200504022951-6b6965ac5dd1 // indirect
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
k8s.io/api v0.17.4

2
go.sum
View File

@ -958,6 +958,8 @@ golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200504022951-6b6965ac5dd1 h1:C8rdnd6KieI73Z2Av0sS0t4kW+geIH/M8kNX8Hmvn9E=
golang.org/x/tools v0.0.0-20200504022951-6b6965ac5dd1/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 h1:BMFHd4OFnFtWX46Xj4DN6vvT1btiBxyq+s0orYBqcQY=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -147,7 +147,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O
}
// Check if this Pod already exists
currentJenkinsMasterPod, err := r.getJenkinsMasterPod()
currentJenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
if err != nil && apierrors.IsNotFound(err) {
jenkinsMasterPod := resources.NewJenkinsMasterPod(meta, r.Configuration.Jenkins)
*r.Notifications <- event.Event{

View File

@ -83,7 +83,7 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
}
r.logger.V(log.VDebug).Info("Jenkins master pod is ready")
jenkinsClient, err := r.ensureJenkinsClient()
jenkinsClient, err := r.Configuration.GetJenkinsClient()
if err != nil {
return reconcile.Result{}, nil, err
}
@ -110,32 +110,6 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
return result, jenkinsClient, err
}
// GetJenkinsOpts gets JENKINS_OPTS env parameter, parses it's values and returns it as a map`
func GetJenkinsOpts(jenkins v1alpha2.Jenkins) map[string]string {
envs := jenkins.Spec.Master.Containers[0].Env
jenkinsOpts := make(map[string]string)
for key, value := range envs {
if value.Name == "JENKINS_OPTS" {
jenkinsOptsEnv := envs[key]
jenkinsOptsWithDashes := jenkinsOptsEnv.Value
if len(jenkinsOptsWithDashes) == 0 {
return nil
}
jenkinsOptsWithEqOperators := strings.Split(jenkinsOptsWithDashes, " ")
for _, vx := range jenkinsOptsWithEqOperators {
opt := strings.Split(vx, "=")
jenkinsOpts[strings.ReplaceAll(opt[0], "--", "")] = opt[1]
}
return jenkinsOpts
}
}
return nil
}
func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod(metaObject metav1.ObjectMeta) error {
if err := r.createOperatorCredentialsSecret(metaObject); err != nil {
return err
@ -216,16 +190,6 @@ func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta
return stackerr.WithStack(r.UpdateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins)))
}
func (r *ReconcileJenkinsBaseConfiguration) getJenkinsMasterPod() (*corev1.Pod, error) {
jenkinsMasterPodName := resources.GetJenkinsMasterPodName(*r.Configuration.Jenkins)
currentJenkinsMasterPod := &corev1.Pod{}
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: jenkinsMasterPodName, Namespace: r.Configuration.Jenkins.Namespace}, currentJenkinsMasterPod)
if err != nil {
return nil, err // don't wrap error
}
return currentJenkinsMasterPod, nil
}
func (r *ReconcileJenkinsBaseConfiguration) calculateUserAndPasswordHash() (string, error) {
credentialsSecret := &corev1.Secret{}
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, credentialsSecret)
@ -309,7 +273,7 @@ func (r *ReconcileJenkinsBaseConfiguration) compareVolumes(actualPod corev1.Pod)
}
func (r *ReconcileJenkinsBaseConfiguration) detectJenkinsMasterPodStartingIssues() (stopReconcileLoop bool, err error) {
jenkinsMasterPod, err := r.getJenkinsMasterPod()
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
if err != nil {
return false, err
}
@ -360,7 +324,7 @@ func (r *ReconcileJenkinsBaseConfiguration) filterEvents(source corev1.EventList
}
func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins() (reconcile.Result, error) {
jenkinsMasterPod, err := r.getJenkinsMasterPod()
jenkinsMasterPod, err := r.Configuration.GetJenkinsMasterPod()
if err != nil {
return reconcile.Result{}, err
}
@ -400,106 +364,6 @@ func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins() (reconcile.Result,
return reconcile.Result{}, nil
}
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClient() (jenkinsclient.Jenkins, error) {
switch r.Configuration.Jenkins.Spec.JenkinsAPISettings.AuthorizationStrategy {
case v1alpha2.ServiceAccountAuthorizationStrategy:
return r.ensureJenkinsClientFromServiceAccount()
case v1alpha2.CreateUserAuthorizationStrategy:
return r.ensureJenkinsClientFromSecret()
default:
return nil, stackerr.Errorf("unrecognized '%s' spec.jenkinsAPISettings.authorizationStrategy", r.Configuration.Jenkins.Spec.JenkinsAPISettings.AuthorizationStrategy)
}
}
func (r *ReconcileJenkinsBaseConfiguration) getJenkinsAPIUrl() (string, error) {
var service corev1.Service
err := r.Client.Get(context.TODO(), types.NamespacedName{
Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace,
Name: resources.GetJenkinsHTTPServiceName(r.Configuration.Jenkins),
}, &service)
if err != nil {
return "", err
}
jenkinsURL := r.jenkinsAPIConnectionSettings.BuildJenkinsAPIUrl(service.Name, service.Namespace, service.Spec.Ports[0].Port, service.Spec.Ports[0].NodePort)
if prefix, ok := GetJenkinsOpts(*r.Configuration.Jenkins)["prefix"]; ok {
jenkinsURL = jenkinsURL + prefix
}
return jenkinsURL, nil
}
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClientFromServiceAccount() (jenkinsclient.Jenkins, error) {
jenkinsAPIUrl, err := r.getJenkinsAPIUrl()
if err != nil {
return nil, err
}
podName := resources.GetJenkinsMasterPodName(*r.Configuration.Jenkins)
token, _, err := r.Configuration.Exec(podName, resources.JenkinsMasterContainerName, []string{"cat", "/var/run/secrets/kubernetes.io/serviceaccount/token"})
if err != nil {
return nil, err
}
return jenkinsclient.NewBearerTokenAuthorization(jenkinsAPIUrl, token.String())
}
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClientFromSecret() (jenkinsclient.Jenkins, error) {
jenkinsURL, err := r.getJenkinsAPIUrl()
if err != nil {
return nil, err
}
r.logger.V(log.VDebug).Info(fmt.Sprintf("Jenkins API URL '%s'", jenkinsURL))
credentialsSecret := &corev1.Secret{}
err = r.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, credentialsSecret)
if err != nil {
return nil, stackerr.WithStack(err)
}
currentJenkinsMasterPod, err := r.getJenkinsMasterPod()
if err != nil {
return nil, err
}
var tokenCreationTime *time.Time
tokenCreationTimeBytes := credentialsSecret.Data[resources.OperatorCredentialsSecretTokenCreationKey]
if tokenCreationTimeBytes != nil {
tokenCreationTime = &time.Time{}
err = tokenCreationTime.UnmarshalText(tokenCreationTimeBytes)
if err != nil {
tokenCreationTime = nil
}
}
if credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey] == nil ||
tokenCreationTimeBytes == nil || tokenCreationTime == nil ||
currentJenkinsMasterPod.ObjectMeta.CreationTimestamp.Time.UTC().After(tokenCreationTime.UTC()) {
r.logger.Info("Generating Jenkins API token for operator")
userName := string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey])
jenkinsClient, err := jenkinsclient.NewUserAndPasswordAuthorization(
jenkinsURL,
userName,
string(credentialsSecret.Data[resources.OperatorCredentialsSecretPasswordKey]))
if err != nil {
return nil, err
}
token, err := jenkinsClient.GenerateToken(userName, "token")
if err != nil {
return nil, err
}
credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey] = []byte(token.GetToken())
now, _ := time.Now().UTC().MarshalText()
credentialsSecret.Data[resources.OperatorCredentialsSecretTokenCreationKey] = now
err = r.UpdateResource(credentialsSecret)
if err != nil {
return nil, stackerr.WithStack(err)
}
}
return jenkinsclient.NewUserAndPasswordAuthorization(
jenkinsURL,
string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey]),
string(credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey]))
}
func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) {
customization := v1alpha2.GroovyScripts{
Customization: v1alpha2.Customization{
@ -517,14 +381,14 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClien
}
func (r *ReconcileJenkinsBaseConfiguration) waitUntilCreateJenkinsMasterPod() (currentJenkinsMasterPod *corev1.Pod, err error) {
currentJenkinsMasterPod, err = r.getJenkinsMasterPod()
currentJenkinsMasterPod, err = r.Configuration.GetJenkinsMasterPod()
for {
if err != nil && !apierrors.IsNotFound(err) {
return nil, stackerr.WithStack(err)
} else if err == nil {
break
}
currentJenkinsMasterPod, err = r.getJenkinsMasterPod()
currentJenkinsMasterPod, err = r.Configuration.GetJenkinsMasterPod()
time.Sleep(time.Millisecond * 10)
}
return

View File

@ -9,7 +9,6 @@ import (
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
"github.com/jenkinsci/kubernetes-operator/pkg/log"
"github.com/bndr/gojenkins"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
@ -22,140 +21,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
func TestGetJenkinsOpts(t *testing.T) {
t.Run("JENKINS_OPTS is uninitialized", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "", Value: ""},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 0, len(opts))
})
t.Run("JENKINS_OPTS is empty", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: ""},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 0, len(opts))
})
t.Run("JENKINS_OPTS have --prefix argument ", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "httpPort")
assert.Contains(t, opts, "prefix")
assert.Equal(t, opts["prefix"], "/jenkins")
})
t.Run("JENKINS_OPTS have --prefix and --httpPort argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins --httpPort=8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 2, len(opts))
assert.Contains(t, opts, "prefix")
assert.Equal(t, opts["prefix"], "/jenkins")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "8080")
})
t.Run("JENKINS_OPTS have --httpPort argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--httpPort=8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "prefix")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "8080")
})
t.Run("JENKINS_OPTS have --httpPort=--8080 argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--httpPort=--8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "prefix")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "--8080")
})
}
func TestCompareContainerVolumeMounts(t *testing.T) {
t.Run("happy with service account", func(t *testing.T) {

View File

@ -3,12 +3,14 @@ package configuration
import (
"bytes"
"context"
"strings"
"time"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/reason"
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client"
stackerr "github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
@ -25,17 +27,18 @@ import (
// Configuration holds required for Jenkins configuration
type Configuration struct {
Client client.Client
ClientSet kubernetes.Clientset
Notifications *chan event.Event
Jenkins *v1alpha2.Jenkins
Scheme *runtime.Scheme
Config *rest.Config
Client client.Client
ClientSet kubernetes.Clientset
Notifications *chan event.Event
Jenkins *v1alpha2.Jenkins
Scheme *runtime.Scheme
Config *rest.Config
JenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings
}
// RestartJenkinsMasterPod terminate Jenkins master pod and notifies about it
func (c *Configuration) RestartJenkinsMasterPod(reason reason.Reason) error {
currentJenkinsMasterPod, err := c.getJenkinsMasterPod()
currentJenkinsMasterPod, err := c.GetJenkinsMasterPod()
if err != nil {
return err
}
@ -54,7 +57,8 @@ func (c *Configuration) RestartJenkinsMasterPod(reason reason.Reason) error {
return stackerr.WithStack(c.Client.Delete(context.TODO(), currentJenkinsMasterPod))
}
func (c *Configuration) getJenkinsMasterPod() (*corev1.Pod, error) {
// GetJenkinsMasterPod gets the jenkins master pod
func (c *Configuration) GetJenkinsMasterPod() (*corev1.Pod, error) {
jenkinsMasterPodName := resources.GetJenkinsMasterPodName(*c.Jenkins)
currentJenkinsMasterPod := &corev1.Pod{}
err := c.Client.Get(context.TODO(), types.NamespacedName{Name: jenkinsMasterPodName, Namespace: c.Jenkins.Namespace}, currentJenkinsMasterPod)
@ -159,3 +163,130 @@ func (c *Configuration) GetJenkinsMasterContainer() *v1alpha2.Container {
}
return nil
}
// GetJenkinsClient gets jenkins client from a configuration
func (c *Configuration) GetJenkinsClient() (jenkinsclient.Jenkins, error) {
switch c.Jenkins.Spec.JenkinsAPISettings.AuthorizationStrategy {
case v1alpha2.ServiceAccountAuthorizationStrategy:
return c.GetJenkinsClientFromServiceAccount()
case v1alpha2.CreateUserAuthorizationStrategy:
return c.GetJenkinsClientFromSecret()
default:
return nil, stackerr.Errorf("unrecognized '%s' spec.jenkinsAPISettings.authorizationStrategy", c.Jenkins.Spec.JenkinsAPISettings.AuthorizationStrategy)
}
}
func (c *Configuration) getJenkinsAPIUrl() (string, error) {
var service corev1.Service
err := c.Client.Get(context.TODO(), types.NamespacedName{
Namespace: c.Jenkins.ObjectMeta.Namespace,
Name: resources.GetJenkinsHTTPServiceName(c.Jenkins),
}, &service)
if err != nil {
return "", err
}
jenkinsURL := c.JenkinsAPIConnectionSettings.BuildJenkinsAPIUrl(service.Name, service.Namespace, service.Spec.Ports[0].Port, service.Spec.Ports[0].NodePort)
if prefix, ok := GetJenkinsOpts(*c.Jenkins)["prefix"]; ok {
jenkinsURL = jenkinsURL + prefix
}
return jenkinsURL, nil
}
// GetJenkinsClientFromServiceAccount gets jenkins client from a serviceAccount
func (c *Configuration) GetJenkinsClientFromServiceAccount() (jenkinsclient.Jenkins, error) {
jenkinsAPIUrl, err := c.getJenkinsAPIUrl()
if err != nil {
return nil, err
}
podName := resources.GetJenkinsMasterPodName(*c.Jenkins)
token, _, err := c.Exec(podName, resources.JenkinsMasterContainerName, []string{"cat", "/var/run/secrets/kubernetes.io/serviceaccount/token"})
if err != nil {
return nil, err
}
return jenkinsclient.NewBearerTokenAuthorization(jenkinsAPIUrl, token.String())
}
// GetJenkinsClientFromSecret gets jenkins client from a secret
func (c *Configuration) GetJenkinsClientFromSecret() (jenkinsclient.Jenkins, error) {
jenkinsURL, err := c.getJenkinsAPIUrl()
if err != nil {
return nil, err
}
credentialsSecret := &corev1.Secret{}
err = c.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(c.Jenkins), Namespace: c.Jenkins.ObjectMeta.Namespace}, credentialsSecret)
if err != nil {
return nil, stackerr.WithStack(err)
}
currentJenkinsMasterPod, err := c.GetJenkinsMasterPod()
if err != nil {
return nil, err
}
var tokenCreationTime *time.Time
tokenCreationTimeBytes := credentialsSecret.Data[resources.OperatorCredentialsSecretTokenCreationKey]
if tokenCreationTimeBytes != nil {
tokenCreationTime = &time.Time{}
err = tokenCreationTime.UnmarshalText(tokenCreationTimeBytes)
if err != nil {
tokenCreationTime = nil
}
}
if credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey] == nil ||
tokenCreationTimeBytes == nil || tokenCreationTime == nil ||
currentJenkinsMasterPod.ObjectMeta.CreationTimestamp.Time.UTC().After(tokenCreationTime.UTC()) {
userName := string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey])
jenkinsClient, err := jenkinsclient.NewUserAndPasswordAuthorization(
jenkinsURL,
userName,
string(credentialsSecret.Data[resources.OperatorCredentialsSecretPasswordKey]))
if err != nil {
return nil, err
}
token, err := jenkinsClient.GenerateToken(userName, "token")
if err != nil {
return nil, err
}
credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey] = []byte(token.GetToken())
now, _ := time.Now().UTC().MarshalText()
credentialsSecret.Data[resources.OperatorCredentialsSecretTokenCreationKey] = now
err = c.UpdateResource(credentialsSecret)
if err != nil {
return nil, stackerr.WithStack(err)
}
}
return jenkinsclient.NewUserAndPasswordAuthorization(
jenkinsURL,
string(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey]),
string(credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey]))
}
// GetJenkinsOpts gets JENKINS_OPTS env parameter, parses it's values and returns it as a map`
func GetJenkinsOpts(jenkins v1alpha2.Jenkins) map[string]string {
envs := jenkins.Spec.Master.Containers[0].Env
jenkinsOpts := make(map[string]string)
for key, value := range envs {
if value.Name == "JENKINS_OPTS" {
jenkinsOptsEnv := envs[key]
jenkinsOptsWithDashes := jenkinsOptsEnv.Value
if len(jenkinsOptsWithDashes) == 0 {
return nil
}
jenkinsOptsWithEqOperators := strings.Split(jenkinsOptsWithDashes, " ")
for _, vx := range jenkinsOptsWithEqOperators {
opt := strings.Split(vx, "=")
jenkinsOpts[strings.ReplaceAll(opt[0], "--", "")] = opt[1]
}
return jenkinsOpts
}
}
return nil
}

View File

@ -0,0 +1,144 @@
package configuration
import (
"testing"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
)
func TestGetJenkinsOpts(t *testing.T) {
t.Run("JENKINS_OPTS is uninitialized", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "", Value: ""},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 0, len(opts))
})
t.Run("JENKINS_OPTS is empty", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: ""},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 0, len(opts))
})
t.Run("JENKINS_OPTS have --prefix argument ", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "httpPort")
assert.Contains(t, opts, "prefix")
assert.Equal(t, opts["prefix"], "/jenkins")
})
t.Run("JENKINS_OPTS have --prefix and --httpPort argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins --httpPort=8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 2, len(opts))
assert.Contains(t, opts, "prefix")
assert.Equal(t, opts["prefix"], "/jenkins")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "8080")
})
t.Run("JENKINS_OPTS have --httpPort argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--httpPort=8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "prefix")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "8080")
})
t.Run("JENKINS_OPTS have --httpPort=--8080 argument", func(t *testing.T) {
jenkins := v1alpha2.Jenkins{
Spec: v1alpha2.JenkinsSpec{
Master: v1alpha2.JenkinsMaster{
Containers: []v1alpha2.Container{
{
Env: []corev1.EnvVar{
{Name: "JENKINS_OPTS", Value: "--httpPort=--8080"},
},
},
},
},
},
}
opts := GetJenkinsOpts(jenkins)
assert.Equal(t, 1, len(opts))
assert.NotContains(t, opts, "prefix")
assert.Contains(t, opts, "httpPort")
assert.Equal(t, opts["httpPort"], "--8080")
})
}

View File

@ -381,7 +381,7 @@ func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName stri
if err != nil {
return nil, err
}
jenkinsHttpServiceFQDN, err := resources.GetJenkinsHTTPServiceFQDN(jenkins)
jenkinsHTTPServiceFQDN, err := resources.GetJenkinsHTTPServiceFQDN(jenkins)
if err != nil {
return nil, err
}
@ -428,7 +428,7 @@ func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName stri
{
Name: "JENKINS_URL",
Value: fmt.Sprintf("http://%s:%d",
jenkinsHttpServiceFQDN,
jenkinsHTTPServiceFQDN,
jenkins.Spec.Service.Port,
),
},

View File

@ -227,12 +227,13 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
}
config := configuration.Configuration{
Client: r.client,
ClientSet: r.clientSet,
Notifications: r.notificationEvents,
Jenkins: jenkins,
Scheme: r.scheme,
Config: &r.config,
Client: r.client,
ClientSet: r.clientSet,
Notifications: r.notificationEvents,
Jenkins: jenkins,
Scheme: r.scheme,
Config: &r.config,
JenkinsAPIConnectionSettings: r.jenkinsAPIConnectionSettings,
}
// Reconcile base configuration