Skip to content

Commit

Permalink
Merge pull request #184 from kajinamit/memcached
Browse files Browse the repository at this point in the history
Enable caching using memcached
  • Loading branch information
openshift-merge-robot authored Aug 25, 2023
2 parents 5e90154 + 590cf82 commit b3dea63
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 16 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ spec:
customServiceConfig: ""
databaseInstance: openstack
databaseUser: "heat"
rabbitMqClusterName: rabbitmq
debug:
dbSync: false
heatAPI:
Expand All @@ -44,7 +43,9 @@ spec:
service: false
replicas: 1
resources: {}
memcachedInstance: memcached
preserveJobs: false
rabbitMqClusterName: rabbitmq
secret: osp-secret
serviceUser: "heat"
```
Expand Down Expand Up @@ -109,6 +110,7 @@ template:
heatEngine:
replicas: 1
resources: {}
memcachedInstance: memcached
passwordSelectors:
authEncryptionKey: HeatAuthEncryptionKey
database: HeatDatabasePassword
Expand All @@ -132,6 +134,7 @@ heat:
num_engine_workers=4
databaseInstance: openstack
databaseUser: "heat"
memcachedInstance: memcached
rabbitMqClusterName: rabbitmq
```

Expand Down
5 changes: 5 additions & 0 deletions api/bases/heat.openstack.org_heats.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ spec:
required:
- containerImage
type: object
memcachedInstance:
default: memcached
description: Memcached instance name.
type: string
nodeSelector:
additionalProperties:
type: string
Expand Down Expand Up @@ -425,6 +429,7 @@ spec:
- heatAPI
- heatCfnAPI
- heatEngine
- memcachedInstance
- rabbitMqClusterName
- secret
type: object
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/heat_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ type HeatSpec struct {
// Might not be required in future.
DatabaseInstance string `json:"databaseInstance"`

// +kubebuilder:validation:Required
// +kubebuilder:default=memcached
// Memcached instance name.
MemcachedInstance string `json:"memcachedInstance"`

// +kubebuilder:validation:Optional
// Debug - enable debug for different deploy stages. If an init container is used, it runs and the
// actual action pod gets started with sleep infinity
Expand Down
5 changes: 5 additions & 0 deletions config/crd/bases/heat.openstack.org_heats.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ spec:
required:
- containerImage
type: object
memcachedInstance:
default: memcached
description: Memcached instance name.
type: string
nodeSelector:
additionalProperties:
type: string
Expand Down Expand Up @@ -425,6 +429,7 @@ spec:
- heatAPI
- heatCfnAPI
- heatEngine
- memcachedInstance
- rabbitMqClusterName
- secret
type: object
Expand Down
8 changes: 8 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ rules:
- patch
- update
- watch
- apiGroups:
- memcached.openstack.org
resources:
- memcacheds
verbs:
- get
- list
- watch
- apiGroups:
- rabbitmq.openstack.org
resources:
Expand Down
95 changes: 94 additions & 1 deletion controllers/heat_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

k8s_errors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -45,6 +46,7 @@ import (
"github.com/openstack-k8s-operators/lib-common/modules/openstack"

heatv1beta1 "github.com/openstack-k8s-operators/heat-operator/api/v1beta1"
memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1"
keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1"
mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1"
Expand Down Expand Up @@ -81,6 +83,7 @@ var keystoneAPI *keystonev1.KeystoneAPI
// +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups=mariadb.openstack.org,resources=mariadbdatabases,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups=memcached.openstack.org,resources=memcacheds,verbs=get;list;watch;
// +kubebuilder:rbac:groups=rabbitmq.openstack.org,resources=transporturls,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch;

Expand Down Expand Up @@ -156,6 +159,7 @@ func (r *HeatReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul
cl := condition.CreateList(
condition.UnknownCondition(condition.DBReadyCondition, condition.InitReason, condition.DBReadyInitMessage),
condition.UnknownCondition(condition.DBSyncReadyCondition, condition.InitReason, condition.DBSyncReadyInitMessage),
condition.UnknownCondition(condition.MemcachedReadyCondition, condition.InitReason, condition.MemcachedReadyInitMessage),
condition.UnknownCondition(condition.RabbitMqTransportURLReadyCondition, condition.InitReason, condition.RabbitMqTransportURLReadyInitMessage),
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
Expand Down Expand Up @@ -236,6 +240,35 @@ func (r *HeatReconciler) SetupWithManager(mgr ctrl.Manager) error {
return nil
}

memcachedFn := func(o client.Object) []reconcile.Request {
result := []reconcile.Request{}

// get all Heat CRs
heats := &heatv1beta1.HeatList{}
listOpts := []client.ListOption{
client.InNamespace(o.GetNamespace()),
}
if err := r.Client.List(context.Background(), heats, listOpts...); err != nil {
r.Log.Error(err, "Unable to retrieve Heat CRs %w")
return nil
}

for _, cr := range heats.Items {
if o.GetName() == cr.Spec.MemcachedInstance {
name := client.ObjectKey{
Namespace: o.GetNamespace(),
Name: cr.Name,
}
r.Log.Info(fmt.Sprintf("Memcached %s is used by Heat CR %s", o.GetName(), cr.Name))
result = append(result, reconcile.Request{NamespacedName: name})
}
}
if len(result) > 0 {
return result
}
return nil
}

return ctrl.NewControllerManagedBy(mgr).
For(&heatv1beta1.Heat{}).
Owns(&heatv1beta1.HeatAPI{}).
Expand All @@ -251,6 +284,8 @@ func (r *HeatReconciler) SetupWithManager(mgr ctrl.Manager) error {
// Watch for TransportURL Secrets which belong to any TransportURLs created by Heat CRs
Watches(&source.Kind{Type: &corev1.Secret{}},
handler.EnqueueRequestsFromMapFunc(transportURLSecretFn)).
Watches(&source.Kind{Type: &memcachedv1.Memcached{}},
handler.EnqueueRequestsFromMapFunc(memcachedFn)).
Complete(r)
}

Expand Down Expand Up @@ -328,6 +363,41 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be

// run check OpenStack secret - end

//
// Check for required memcached used for caching
//
memcached, err := r.getHeatMemcached(ctx, helper, instance)
if err != nil {
if k8s_errors.IsNotFound(err) {
instance.Status.Conditions.Set(condition.FalseCondition(
condition.MemcachedReadyCondition,
condition.RequestedReason,
condition.SeverityInfo,
condition.MemcachedReadyWaitingMessage))
return ctrl.Result{RequeueAfter: time.Duration(10) * time.Second}, fmt.Errorf("memcached %s not found", instance.Spec.MemcachedInstance)
}
instance.Status.Conditions.Set(condition.FalseCondition(
condition.MemcachedReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
condition.MemcachedReadyErrorMessage,
err.Error()))
return ctrl.Result{}, err
}

if !memcached.IsReady() {
instance.Status.Conditions.Set(condition.FalseCondition(
condition.MemcachedReadyCondition,
condition.RequestedReason,
condition.SeverityInfo,
condition.MemcachedReadyWaitingMessage))
return ctrl.Result{RequeueAfter: time.Duration(10) * time.Second}, fmt.Errorf("memcached %s is not ready", memcached.Name)
}
// Mark the Memcached Service as Ready if we get to this point with no errors
instance.Status.Conditions.MarkTrue(
condition.MemcachedReadyCondition, condition.MemcachedReadyMessage)
// run check memcached - end

//
// create RabbitMQ transportURL CR and get the actual URL from the associated secret that is created
//
Expand Down Expand Up @@ -399,7 +469,7 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be
// - %-config configmap holding minimal heat config required to get the service up, user can add additional files to be added to the service
// - parameters which has passwords gets added from the OpenStack secret via the init container
//
err = r.generateServiceConfigMaps(ctx, instance, helper, &configMapVars)
err = r.generateServiceConfigMaps(ctx, instance, helper, &configMapVars, memcached)
if err != nil {
instance.Status.Conditions.Set(condition.FalseCondition(
condition.ServiceConfigReadyCondition,
Expand Down Expand Up @@ -776,6 +846,7 @@ func (r *HeatReconciler) generateServiceConfigMaps(
instance *heatv1beta1.Heat,
h *helper.Helper,
envVars *map[string]env.Setter,
mc *memcachedv1.Memcached,
) error {
//
// create Configmap/Secret required for heat input
Expand Down Expand Up @@ -811,6 +882,8 @@ func (r *HeatReconciler) generateServiceConfigMaps(
"ServiceUser": instance.Spec.ServiceUser,
"StackDomainAdminUsername": heat.StackDomainAdminUsername,
"StackDomainName": heat.StackDomainName,
"MemcachedServers": strings.Join(mc.Status.ServerList, ","),
"MemcachedServersWithInet": strings.Join(mc.Status.ServerListWithInet, ","),
}

cms := []util.Template{
Expand Down Expand Up @@ -944,3 +1017,23 @@ func (r *HeatReconciler) ensureStackDomain(
domainID)
return ctrl.Result{}, err
}

// getHeatMemcached - gets the Memcached instance used for heat cache backend
func (r *HeatReconciler) getHeatMemcached(
ctx context.Context,
h *helper.Helper,
instance *heatv1beta1.Heat,
) (*memcachedv1.Memcached, error) {
memcached := &memcachedv1.Memcached{}
err := h.GetClient().Get(
ctx,
types.NamespacedName{
Name: instance.Spec.MemcachedInstance,
Namespace: instance.Namespace,
},
memcached)
if err != nil {
return nil, err
}
return memcached, err
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
k8s.io/api v0.26.7
k8s.io/apimachinery v0.26.7
k8s.io/client-go v0.26.7
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
sigs.k8s.io/controller-runtime v0.14.6
)

Expand Down Expand Up @@ -81,7 +82,6 @@ require (
k8s.io/component-base v0.26.7 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1"
rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1"
keystonev1beta1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1"
mariadbv1beta1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1"
Expand All @@ -54,6 +55,7 @@ func init() {

utilruntime.Must(heatv1beta1.AddToScheme(scheme))
utilruntime.Must(mariadbv1beta1.AddToScheme(scheme))
utilruntime.Must(memcachedv1.AddToScheme(scheme))
utilruntime.Must(routev1.AddToScheme(scheme))
utilruntime.Must(rabbitmqv1.AddToScheme(scheme))
err := keystonev1beta1.AddToScheme(scheme)
Expand Down
10 changes: 6 additions & 4 deletions templates/heat/config/heat.conf
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
[DEFAULT]
region_name_for_services=regionOne
stack_user_domain_name = {{ .StackDomainName }}
stack_domain_admin = {{ .StackDomainAdminUsername }}
stack_user_domain_name={{ .StackDomainName }}
stack_domain_admin={{ .StackDomainAdminUsername }}
#stack_domain_admin_password =
num_engine_workers=4
#auth_encryption_key =
use_stderr=true

[cache]
enabled=True
memcache_servers=#TODO
backend=dogpile.cache.pymemcache
enabled=true
memcache_servers={{ .MemcachedServers }}

[database]
#connection =
Expand Down Expand Up @@ -39,6 +40,7 @@ caching=False
www_authenticate_uri={{ .KeystonePublicURL }}
auth_type=password
memcache_use_advanced_pool=True
memcached_servers={{ .MemcachedServersWithInet }}
region_name=regionOne
auth_url={{ .KeystonePublicURL }}
username={{ .ServiceUser }}
Expand Down
Loading

0 comments on commit b3dea63

Please sign in to comment.