diff --git a/controllers/placementapi_controller.go b/controllers/placementapi_controller.go index 4bcfc610..901ac790 100644 --- a/controllers/placementapi_controller.go +++ b/controllers/placementapi_controller.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -51,6 +52,7 @@ import ( common_rbac "github.com/openstack-k8s-operators/lib-common/modules/common/rbac" "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" util "github.com/openstack-k8s-operators/lib-common/modules/common/util" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" @@ -357,6 +359,52 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } + // TLS input validation + // + // Validate the CA cert secret if provided + if instance.Spec.TLS.CaBundleSecretName != "" { + hash, ctrlResult, err := tls.ValidateCACertSecret( + ctx, + h.GetClient(), + types.NamespacedName{ + Name: instance.Spec.TLS.CaBundleSecretName, + Namespace: instance.Namespace, + }, + ) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + + if hash != "" { + configMapVars[tls.CABundleKey] = env.SetValue(hash) + } + } + + // Validate API service certs secrets + certsHash, ctrlResult, err := instance.Spec.TLS.API.ValidateCertSecrets(ctx, h, instance.Namespace) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.TLSInputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.TLSInputErrorMessage, + err.Error())) + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + configMapVars[tls.TLSHashName] = env.SetValue(certsHash) + + instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // create hash over all the different input resources to identify if any those changed // and a restart/recreate is required. // @@ -424,9 +472,10 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, nil } -func getServiceLabels() map[string]string { +func getServiceLabels(instance *placementv1.PlacementAPI) map[string]string { return map[string]string{ - common.AppSelector: placement.ServiceName, + common.AppSelector: placement.ServiceName, + common.OwnerSelector: instance.Name, } } @@ -451,7 +500,7 @@ func (r *PlacementAPIReconciler) ensureServiceExposed( } exportLabels := util.MergeStringMaps( - getServiceLabels(), + getServiceLabels(instance), map[string]string{ service.AnnotationEndpointKey: endpointTypeStr, }, @@ -463,7 +512,7 @@ func (r *PlacementAPIReconciler) ensureServiceExposed( Name: endpointName, Namespace: instance.Namespace, Labels: exportLabels, - Selector: getServiceLabels(), + Selector: getServiceLabels(instance), Port: service.GenericServicePort{ Name: endpointName, Port: data.Port, @@ -524,7 +573,12 @@ func (r *PlacementAPIReconciler) ensureServiceExposed( } // create service - end - // TODO: TLS, pass in https as protocol, create TLS cert + // if TLS is enabled + if instance.Spec.TLS.API.Enabled(endpointType) { + // set endpoint protocol to https + data.Protocol = ptr.To(service.ProtocolHTTPS) + } + apiEndpoints[string(endpointType)], err = svc.GetAPIEndpoint( svcOverride.EndpointURL, data.Protocol, data.Path) if err != nil { @@ -593,7 +647,7 @@ func (r *PlacementAPIReconciler) ensureKeystoneServiceUser( Secret: instance.Spec.Secret, PasswordSelector: instance.Spec.PasswordSelectors.Service, } - serviceLabels := getServiceLabels() + serviceLabels := getServiceLabels(instance) ksSvc := keystonev1.NewKeystoneService(ksSvcSpec, instance.Namespace, serviceLabels, time.Duration(10)*time.Second) _, err := ksSvc.CreateOrPatch(ctx, h) if err != nil { @@ -625,7 +679,7 @@ func (r *PlacementAPIReconciler) ensureKeystoneEndpoint( placement.ServiceName, instance.Namespace, ksEndptSpec, - getServiceLabels(), + getServiceLabels(instance), time.Duration(10)*time.Second, ) ctrlResult, err := ksEndpt.CreateOrPatch(ctx, h) @@ -733,6 +787,10 @@ func (r *PlacementAPIReconciler) initConditions( condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage), + condition.UnknownCondition( + condition.TLSInputReadyCondition, + condition.InitReason, + condition.InputReadyInitMessage), ) instance.Status.Conditions.Init(&cl) @@ -988,7 +1046,7 @@ func (r *PlacementAPIReconciler) ensureDbSync( serviceAnnotations map[string]string, ) (ctrl.Result, error) { Log := r.GetLogger(ctx) - serviceLabels := getServiceLabels() + serviceLabels := getServiceLabels(instance) dbSyncHash := instance.Status.Hash[placementv1.DbSyncHash] jobDef := placement.DbSyncJob(instance, serviceLabels, serviceAnnotations) dbSyncjob := job.NewJob( @@ -1037,10 +1095,20 @@ func (r *PlacementAPIReconciler) ensureDeployment( Log := r.GetLogger(ctx) Log.Info("Reconciling Service") - serviceLabels := getServiceLabels() + serviceLabels := getServiceLabels(instance) // Define a new Deployment object - deplDef := placement.Deployment(instance, inputHash, serviceLabels, serviceAnnotations) + deplDef, err := placement.Deployment(ctx, h, instance, inputHash, serviceLabels, serviceAnnotations) + + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DeploymentReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.DeploymentReadyErrorMessage, + err.Error())) + } + depl := deployment.NewDeployment( deplDef, time.Duration(5)*time.Second, @@ -1155,6 +1223,21 @@ func (r *PlacementAPIReconciler) generateServiceConfigMaps( "log_file": "/var/log/placement/placement-api.log", } + // create httpd vhost template parameters + httpdVhostConfig := map[string]interface{}{} + for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} { + endptConfig := map[string]interface{}{} + endptConfig["ServerName"] = fmt.Sprintf("placement-%s.%s.svc", endpt.String(), instance.Namespace) + endptConfig["TLS"] = false // default TLS to false, and set it bellow to true if enabled + if instance.Spec.TLS.API.Enabled(endpt) { + endptConfig["TLS"] = true + endptConfig["SSLCertificateFile"] = fmt.Sprintf("/etc/pki/tls/certs/%s.crt", endpt.String()) + endptConfig["SSLCertificateKeyFile"] = fmt.Sprintf("/etc/pki/tls/private/%s.key", endpt.String()) + } + httpdVhostConfig[endpt.String()] = endptConfig + } + templateParameters["VHosts"] = httpdVhostConfig + extraTemplates := map[string]string{ "placement.conf": "placementapi/config/placement.conf", } diff --git a/pkg/placement/dbsync.go b/pkg/placement/dbsync.go index 3170d07e..4b36444d 100644 --- a/pkg/placement/dbsync.go +++ b/pkg/placement/dbsync.go @@ -89,7 +89,5 @@ func DbSyncJob( }, } - job.Spec.Template.Spec.Volumes = getVolumes(instance.Name) - return job } diff --git a/pkg/placement/deployment.go b/pkg/placement/deployment.go index ab45eef3..592c1634 100644 --- a/pkg/placement/deployment.go +++ b/pkg/placement/deployment.go @@ -199,5 +199,5 @@ func Deployment( deployment.Spec.Template.Spec.NodeSelector = instance.Spec.NodeSelector } - return deployment + return deployment, nil } diff --git a/tests/functional/placementapi_controller_test.go b/tests/functional/placementapi_controller_test.go index 462af74d..b8647616 100644 --- a/tests/functional/placementapi_controller_test.go +++ b/tests/functional/placementapi_controller_test.go @@ -757,7 +757,7 @@ var _ = Describe("PlacementAPI controller", func() { Expect(container.ReadinessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) Expect(container.LivenessProbe.HTTPGet.Scheme).To(Equal(corev1.URISchemeHTTPS)) - configDataMap := th.GetConfigMap(names.ConfigMapName) + configDataMap := th.GetSecret(names.ConfigMapName) Expect(configDataMap).ShouldNot(BeNil()) Expect(configDataMap.Data).Should(HaveKey("httpd.conf")) Expect(configDataMap.Data).Should(HaveKey("ssl.conf"))