#12 Allow configure Jenkins and Jenkins slave services

This commit is contained in:
Tomasz Sęk
2019-03-08 17:06:53 +01:00
parent 75c403b941
commit 90c6f25610
11 changed files with 168 additions and 57 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ func (jenkins *jenkins) CreateOrUpdateJob(config, jobName string) (job *gojenkin
}
// BuildJenkinsAPIUrl returns Jenkins API URL
func BuildJenkinsAPIUrl(namespace, serviceName string, portNumber int, local, minikube bool) (string, error) {
func BuildJenkinsAPIUrl(namespace, serviceName string, portNumber int32, local, minikube bool) (string, error) {
// Get Jenkins URL from minikube command
if local && minikube {
cmd := exec.Command("minikube", "service", "--url", "-n", namespace, serviceName)
@@ -136,10 +136,14 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod
}
r.logger.V(log.VDebug).Info("Service account, role and role binding are present")
if err := r.createService(metaObject); err != nil {
if err := r.createService(metaObject, resources.GetJenkinsHTTPServiceName(r.jenkins), r.jenkins.Spec.Service); err != nil {
return err
}
r.logger.V(log.VDebug).Info("Service is present")
r.logger.V(log.VDebug).Info("Jenkins HTTP Service is present")
if err := r.createService(metaObject, resources.GetJenkinsSlavesServiceName(r.jenkins), r.jenkins.Spec.SlaveService); err != nil {
return err
}
r.logger.V(log.VDebug).Info("Jenkins slave Service is present")
return nil
}
@@ -296,13 +300,29 @@ func (r *ReconcileJenkinsBaseConfiguration) createRBAC(meta metav1.ObjectMeta) e
return nil
}
func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta) error {
err := r.createResource(resources.NewService(meta, r.minikube))
if err != nil && !apierrors.IsAlreadyExists(err) {
func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta, name string, config v1alpha1.Service) error {
service := corev1.Service{}
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &service)
if err != nil && errors.IsNotFound(err) {
service = resources.UpdateService(corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: meta.Namespace,
Labels: meta.Labels,
},
Spec: corev1.ServiceSpec{
Selector: meta.Labels,
},
}, config)
if err = r.createResource(&service); err != nil {
return stackerr.WithStack(err)
}
} else if err != nil {
return stackerr.WithStack(err)
}
return nil
service = resources.UpdateService(service, config)
return stackerr.WithStack(r.updateResource(&service))
}
func (r *ReconcileJenkinsBaseConfiguration) getJenkinsMasterPod(meta metav1.ObjectMeta) (*corev1.Pod, error) {
@@ -425,7 +445,7 @@ func (r *ReconcileJenkinsBaseConfiguration) waitForJenkins(meta metav1.ObjectMet
func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClient(meta metav1.ObjectMeta) (jenkinsclient.Jenkins, error) {
jenkinsURL, err := jenkinsclient.BuildJenkinsAPIUrl(
r.jenkins.ObjectMeta.Namespace, meta.Name, resources.HTTPPortInt, r.local, r.minikube)
r.jenkins.ObjectMeta.Namespace, resources.GetJenkinsHTTPServiceName(r.jenkins), r.jenkins.Spec.Service.Port, r.local, r.minikube)
if err != nil {
return nil, err
}
@@ -115,13 +115,21 @@ ServiceAccountCredential serviceAccountCredential = new ServiceAccountCredential
)
SystemCredentialsProvider.getInstance().getStore().addCredentials(Domain.global(), serviceAccountCredential)
KubernetesCloud kubernetes = new KubernetesCloud("kubernetes")
def kubernetes = Jenkins.instance.clouds.getByName("kubernetes")
def add = false
if (kubernetes == null) {
add = true
kubernetes = new KubernetesCloud("kubernetes")
}
kubernetes.setServerUrl("https://kubernetes.default")
kubernetes.setNamespace("%s")
kubernetes.setCredentialsId(kubernetesCredentialsId)
kubernetes.setJenkinsUrl("http://%s:%d")
kubernetes.setJenkinsUrl("%s")
kubernetes.setJenkinsTunnel("%s")
kubernetes.setRetentionTimeout(15)
jenkins.clouds.add(kubernetes)
if (add) {
jenkins.clouds.add(kubernetes)
}
jenkins.save()
`
@@ -176,7 +184,10 @@ func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha1.Jen
"4-enable-master-access-control.groovy": enableMasterAccessControl,
"5-disable-insecure-features.groovy": disableInsecureFeatures,
"6-configure-kubernetes-plugin.groovy": fmt.Sprintf(configureKubernetesPluginFmt,
jenkins.ObjectMeta.Namespace, GetResourceName(jenkins), HTTPPortInt),
jenkins.ObjectMeta.Namespace,
fmt.Sprintf("http://%s.%s:%d", GetJenkinsHTTPServiceName(jenkins), jenkins.ObjectMeta.Namespace, jenkins.Spec.Service.Port),
fmt.Sprintf("%s.%s:%d", GetJenkinsSlavesServiceName(jenkins), jenkins.ObjectMeta.Namespace, jenkins.Spec.SlaveService.Port),
),
"7-configure-views.groovy": configureViews,
},
}
@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -42,10 +43,7 @@ const (
httpPortName = "http"
slavePortName = "slavelistener"
// HTTPPortInt defines Jenkins master HTTP port
HTTPPortInt = 8080
slavePortInt = 50000
httpPortInt32 = int32(8080)
slavePortInt32 = int32(50000)
HTTPPortInt = 8080
jenkinsUserUID = int64(1000) // build in Docker image jenkins user UID
)
@@ -109,12 +107,12 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha1.Jenkins
},
Ports: []corev1.ContainerPort{
{
Name: slavePortName,
ContainerPort: slavePortInt32,
Name: httpPortName,
ContainerPort: constants.DefaultHTTPPortInt32,
},
{
Name: httpPortName,
ContainerPort: httpPortInt32,
Name: slavePortName,
ContainerPort: constants.DefaultSlavePortInt32,
},
},
Env: []corev1.EnvVar{
@@ -1,9 +1,13 @@
package resources
import (
"fmt"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
func buildServiceTypeMeta() metav1.TypeMeta {
@@ -13,37 +17,32 @@ func buildServiceTypeMeta() metav1.TypeMeta {
}
}
// NewService builds the Kubernetes service resource
func NewService(meta metav1.ObjectMeta, minikube bool) *corev1.Service {
service := &corev1.Service{
TypeMeta: buildServiceTypeMeta(),
ObjectMeta: meta,
Spec: corev1.ServiceSpec{
Selector: meta.Labels,
// The first port have to be Jenkins http port because when run with minikube
// command 'minikube service' returns endpoints in the same sequence
Ports: []corev1.ServicePort{
{
Name: httpPortName,
Port: httpPortInt32,
TargetPort: intstr.FromInt(HTTPPortInt),
},
{
Name: slavePortName,
Port: slavePortInt32,
TargetPort: intstr.FromInt(slavePortInt),
},
},
},
// UpdateService returns new service with override fields from config
func UpdateService(actual corev1.Service, config v1alpha1.Service) corev1.Service {
actual.ObjectMeta.Annotations = config.Annotations
for key, value := range config.Labels {
actual.ObjectMeta.Labels[key] = value
}
actual.Spec.Type = config.Type
actual.Spec.LoadBalancerIP = config.LoadBalancerIP
actual.Spec.LoadBalancerSourceRanges = config.LoadBalancerSourceRanges
if len(actual.Spec.Ports) == 0 {
actual.Spec.Ports = []corev1.ServicePort{{}}
}
actual.Spec.Ports[0].Port = config.Port
if config.NodePort != 0 {
actual.Spec.Ports[0].NodePort = config.NodePort
}
if minikube {
// When running locally with minikube cluster Jenkins Service have to be exposed via node port
// to allow communication operator -> Jenkins API
service.Spec.Type = corev1.ServiceTypeNodePort
} else {
service.Spec.Type = corev1.ServiceTypeClusterIP
}
return actual
}
return service
// GetJenkinsHTTPServiceName returns Kubernetes service name used for expose Jenkins HTTP endpoint
func GetJenkinsHTTPServiceName(jenkins *v1alpha1.Jenkins) string {
return fmt.Sprintf("%s-http-%s", constants.OperatorName, jenkins.ObjectMeta.Name)
}
// GetJenkinsSlavesServiceName returns Kubernetes service name used for expose Jenkins slave endpoint
func GetJenkinsSlavesServiceName(jenkins *v1alpha1.Jenkins) string {
return fmt.Sprintf("%s-slave-%s", constants.OperatorName, jenkins.ObjectMeta.Name)
}
@@ -13,4 +13,8 @@ const (
UserConfigurationJobName = OperatorName + "-user-configuration"
// UserConfigurationCASCJobName is the Jenkins job name used to configure Jenkins by Configuration as code yaml configs provided by user
UserConfigurationCASCJobName = OperatorName + "-user-configuration-casc"
// DefaultHTTPPortInt32 is the default Jenkins HTTP port
DefaultHTTPPortInt32 = int32(8080)
// DefaultSlavePortInt32 is the default Jenkins port for slaves
DefaultSlavePortInt32 = int32(50000)
)
@@ -3,6 +3,7 @@ package jenkins
import (
"context"
"fmt"
"reflect"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base"
@@ -246,6 +247,30 @@ func (r *ReconcileJenkins) setDefaults(jenkins *v1alpha1.Jenkins, logger logr.Lo
},
}
}
if reflect.DeepEqual(jenkins.Spec.Service, v1alpha1.Service{}) {
logger.Info("Setting default Jenkins master service")
changed = true
var serviceType corev1.ServiceType
if r.minikube {
// When running locally with minikube cluster Jenkins Service have to be exposed via node port
// to allow communication operator -> Jenkins API
serviceType = corev1.ServiceTypeNodePort
} else {
serviceType = corev1.ServiceTypeClusterIP
}
jenkins.Spec.Service = v1alpha1.Service{
Type: serviceType,
Port: constants.DefaultHTTPPortInt32,
}
}
if reflect.DeepEqual(jenkins.Spec.SlaveService, v1alpha1.Service{}) {
logger.Info("Setting default Jenkins slave service")
changed = true
jenkins.Spec.SlaveService = v1alpha1.Service{
Type: corev1.ServiceTypeClusterIP,
Port: constants.DefaultSlavePortInt32,
}
}
if changed {
return errors.WithStack(r.client.Update(context.TODO(), jenkins))