Merge pull request #357 from akram/add-route-creation
Add Route pointing to the HTTP Service when the Route API is present
This commit is contained in:
commit
12ecfaa2b3
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants"
|
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications"
|
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications"
|
||||||
e "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event"
|
e "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/event"
|
"github.com/jenkinsci/kubernetes-operator/pkg/event"
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
"github.com/jenkinsci/kubernetes-operator/pkg/log"
|
||||||
"github.com/jenkinsci/kubernetes-operator/version"
|
"github.com/jenkinsci/kubernetes-operator/version"
|
||||||
|
|
@ -45,8 +46,6 @@ var (
|
||||||
operatorMetricsPort int32 = 8686
|
operatorMetricsPort int32 = 8686
|
||||||
)
|
)
|
||||||
|
|
||||||
//var log = logf.Log.WithName("cmd")
|
|
||||||
|
|
||||||
func printInfo() {
|
func printInfo() {
|
||||||
log.Log.Info(fmt.Sprintf("Version: %s", version.Version))
|
log.Log.Info(fmt.Sprintf("Version: %s", version.Version))
|
||||||
log.Log.Info(fmt.Sprintf("Git commit: %s", version.GitCommit))
|
log.Log.Info(fmt.Sprintf("Git commit: %s", version.GitCommit))
|
||||||
|
|
@ -120,6 +119,9 @@ func main() {
|
||||||
fatal(errors.Wrap(err, "failed to create Kubernetes client set"), *debug)
|
fatal(errors.Wrap(err, "failed to create Kubernetes client set"), *debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( resources.IsRouteAPIAvailable(clientSet) ) {
|
||||||
|
log.Log.Info("Route API found: Route creation will be performed")
|
||||||
|
}
|
||||||
c := make(chan e.Event)
|
c := make(chan e.Event)
|
||||||
go notifications.Listen(c, events, mgr.GetClient())
|
go notifications.Listen(c, events, mgr.GetClient())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package apis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
@ -17,4 +18,5 @@ func AddToScheme(s *runtime.Scheme) error {
|
||||||
func init() {
|
func init() {
|
||||||
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
|
||||||
AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme)
|
AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme)
|
||||||
|
AddToSchemes = append(AddToSchemes, routev1.AddToScheme)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,15 +177,25 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod
|
||||||
}
|
}
|
||||||
r.logger.V(log.VDebug).Info("Extra role bindings are present")
|
r.logger.V(log.VDebug).Info("Extra role bindings are present")
|
||||||
|
|
||||||
if err := r.createService(metaObject, resources.GetJenkinsHTTPServiceName(r.Configuration.Jenkins), r.Configuration.Jenkins.Spec.Service); err != nil {
|
httpServiceName := resources.GetJenkinsHTTPServiceName(r.Configuration.Jenkins)
|
||||||
|
if err := r.createService(metaObject, httpServiceName, r.Configuration.Jenkins.Spec.Service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.logger.V(log.VDebug).Info("Jenkins HTTP Service is present")
|
r.logger.V(log.VDebug).Info("Jenkins HTTP Service is present")
|
||||||
|
|
||||||
if err := r.createService(metaObject, resources.GetJenkinsSlavesServiceName(r.Configuration.Jenkins), r.Configuration.Jenkins.Spec.SlaveService); err != nil {
|
if err := r.createService(metaObject, resources.GetJenkinsSlavesServiceName(r.Configuration.Jenkins), r.Configuration.Jenkins.Spec.SlaveService); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.logger.V(log.VDebug).Info("Jenkins slave Service is present")
|
r.logger.V(log.VDebug).Info("Jenkins slave Service is present")
|
||||||
|
|
||||||
|
if resources.IsRouteAPIAvailable(&r.ClientSet) {
|
||||||
|
r.logger.V(log.VDebug).Info("Route API is available. Now creating route.")
|
||||||
|
if err := r.createRoute(metaObject, httpServiceName, r.Configuration.Jenkins); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.logger.V(log.VDebug).Info("Jenkins Route is present")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
//RouteKind the kind name for route
|
||||||
|
const RouteKind = "Route"
|
||||||
|
var isRouteAPIAvailable = false
|
||||||
|
var routeAPIChecked = false
|
||||||
|
|
||||||
|
// UpdateRoute returns new route matching the service
|
||||||
|
func UpdateRoute(actual routev1.Route,jenkins *v1alpha2.Jenkins) routev1.Route {
|
||||||
|
actualTargetService := actual.Spec.To
|
||||||
|
serviceName := GetJenkinsHTTPServiceName(jenkins)
|
||||||
|
if( actualTargetService.Name != serviceName ) {
|
||||||
|
actual.Spec.To.Name = serviceName
|
||||||
|
}
|
||||||
|
port := jenkins.Spec.Service.Port
|
||||||
|
if( actual.Spec.Port.TargetPort.IntVal != port){
|
||||||
|
actual.Spec.Port.TargetPort = intstr.FromInt(int(port))
|
||||||
|
}
|
||||||
|
return actual
|
||||||
|
}
|
||||||
|
|
||||||
|
//IsRouteAPIAvailable tells if the Route API is installed and discoverable
|
||||||
|
func IsRouteAPIAvailable(clientSet *kubernetes.Clientset) (bool) {
|
||||||
|
if (routeAPIChecked){
|
||||||
|
return isRouteAPIAvailable
|
||||||
|
}
|
||||||
|
gv := schema.GroupVersion{
|
||||||
|
Group: routev1.GroupName,
|
||||||
|
Version: routev1.SchemeGroupVersion.Version,
|
||||||
|
}
|
||||||
|
if err := discovery.ServerSupportsVersion(clientSet, gv); err != nil {
|
||||||
|
// error, API not available
|
||||||
|
routeAPIChecked = true
|
||||||
|
isRouteAPIAvailable = false
|
||||||
|
} else {
|
||||||
|
// API Exists
|
||||||
|
routeAPIChecked = true
|
||||||
|
isRouteAPIAvailable = true
|
||||||
|
}
|
||||||
|
return isRouteAPIAvailable
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
//ServiceKind the kind name for Service
|
||||||
|
const ServiceKind = "Service"
|
||||||
|
|
||||||
// UpdateService returns new service with override fields from config
|
// UpdateService returns new service with override fields from config
|
||||||
func UpdateService(actual corev1.Service, config v1alpha2.Service) corev1.Service {
|
func UpdateService(actual corev1.Service, config v1alpha2.Service) corev1.Service {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package base
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
|
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
stackerr "github.com/pkg/errors"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// createRoute takes the ServiceName and Creates the Route based on it
|
||||||
|
func (r *ReconcileJenkinsBaseConfiguration) createRoute(meta metav1.ObjectMeta, serviceName string, config *v1alpha2.Jenkins) error{
|
||||||
|
route := routev1.Route{}
|
||||||
|
name := fmt.Sprintf("%s-%s", config.ObjectMeta.Name, config.ObjectMeta.Namespace)
|
||||||
|
err := r.Client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: meta.Namespace}, &route)
|
||||||
|
if err != nil && apierrors.IsNotFound(err) {
|
||||||
|
port := &routev1.RoutePort{
|
||||||
|
TargetPort: intstr.FromString(""),
|
||||||
|
}
|
||||||
|
|
||||||
|
routeSpec := routev1.RouteSpec{
|
||||||
|
TLS: &routev1.TLSConfig{
|
||||||
|
InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect,
|
||||||
|
Termination: routev1.TLSTerminationEdge,
|
||||||
|
},
|
||||||
|
To: routev1.RouteTargetReference{
|
||||||
|
Kind: resources.ServiceKind,
|
||||||
|
Name: serviceName,
|
||||||
|
},
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
actual := routev1.Route{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: meta.Namespace,
|
||||||
|
Labels: meta.Labels,
|
||||||
|
},
|
||||||
|
Spec: routeSpec,
|
||||||
|
}
|
||||||
|
route = resources.UpdateRoute(actual, config)
|
||||||
|
if err = r.CreateResource(&route); err != nil {
|
||||||
|
return stackerr.WithStack(err)
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return stackerr.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
route.ObjectMeta.Labels = meta.Labels // make sure that user won't break service by hand
|
||||||
|
route = resources.UpdateRoute(route, config)
|
||||||
|
return stackerr.WithStack(r.UpdateResource(&route))
|
||||||
|
}
|
||||||
|
|
@ -72,7 +72,6 @@ func (e *enqueueRequestForJenkins) getOwnerReconcileRequests(object metav1.Objec
|
||||||
Name: object.GetLabels()[constants.LabelJenkinsCRKey],
|
Name: object.GetLabels()[constants.LabelJenkinsCRKey],
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@ var reconcileErrors = map[string]reconcileError{}
|
||||||
// Add creates a new Jenkins Controller and adds it to the Manager. The Manager will set fields on the Controller
|
// Add creates a new Jenkins Controller and adds it to the Manager. The Manager will set fields on the Controller
|
||||||
// and Start it when the Manager is Started.
|
// and Start it when the Manager is Started.
|
||||||
func Add(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) error {
|
func Add(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) error {
|
||||||
return add(mgr, newReconciler(mgr, jenkinsAPIConnectionSettings, clientSet, config, notificationEvents))
|
reconciler := newReconciler(mgr, jenkinsAPIConnectionSettings, clientSet, config, notificationEvents)
|
||||||
|
return add(mgr, reconciler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newReconciler returns a new reconcile.Reconciler
|
// newReconciler returns a new reconcile.Reconciler
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue