mirror of
https://github.com/jenkinsci/kubernetes-operator.git
synced 2026-10-07 00:21:14 +02:00
#12 Allow configure Jenkins and Jenkins slave services
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+15
-4
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user