diff --git a/apis/bases/memcached.openstack.org_memcacheds.yaml b/apis/bases/memcached.openstack.org_memcacheds.yaml index 017450a5..1708c11d 100644 --- a/apis/bases/memcached.openstack.org_memcacheds.yaml +++ b/apis/bases/memcached.openstack.org_memcacheds.yaml @@ -134,6 +134,9 @@ spec: items: type: string type: array + tlsSupport: + description: Whether TLS is supported by the memcached instance + type: boolean type: object type: object served: true diff --git a/apis/memcached/v1beta1/memcached_funcs.go b/apis/memcached/v1beta1/memcached_funcs.go new file mode 100644 index 00000000..419bee42 --- /dev/null +++ b/apis/memcached/v1beta1/memcached_funcs.go @@ -0,0 +1,95 @@ +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "context" + "strings" + + condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/util" + "k8s.io/apimachinery/pkg/types" +) + +// IsReady - returns true if Memcached is reconciled successfully +func (instance Memcached) IsReady() bool { + return instance.Status.Conditions.IsTrue(condition.ReadyCondition) +} + +// RbacConditionsSet - set the conditions for the rbac object +func (instance Memcached) RbacConditionsSet(c *condition.Condition) { + instance.Status.Conditions.Set(c) +} + +// RbacNamespace - return the namespace +func (instance Memcached) RbacNamespace() string { + return instance.Namespace +} + +// RbacResourceName - return the name to be used for rbac objects (serviceaccount, role, rolebinding) +func (instance Memcached) RbacResourceName() string { + return "memcached-" + instance.Name +} + +// SetupDefaults - initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) +func SetupDefaults() { + // Acquire environmental defaults and initialize Memcached defaults with them + memcachedDefaults := MemcachedDefaults{ + ContainerImageURL: util.GetEnvVar("RELATED_IMAGE_INFRA_MEMCACHED_IMAGE_URL_DEFAULT", MemcachedContainerImage), + } + + SetupMemcachedDefaults(memcachedDefaults) +} + +// GetMemcachedServerListString - return the memcached servers as comma separated list +// to be used in OpenStack config. +func (instance *Memcached) GetMemcachedServerListString() string { + return strings.Join(instance.Status.ServerList, ",") +} + +// GetMemcachedServerListWithInetString - return the memcached servers as comma separated list +// to be used in OpenStack config. +func (instance *Memcached) GetMemcachedServerListWithInetString() string { + return strings.Join(instance.Status.ServerListWithInet, ",") +} + +// GetMemcachedTLSSupport - return the TLS support of the memcached instance +func (instance *Memcached) GetMemcachedTLSSupport() bool { + return instance.Status.TLSSupport +} + +// GetMemcachedByName - gets the Memcached instance +func GetMemcachedByName( + ctx context.Context, + h *helper.Helper, + name string, + namespace string, +) (*Memcached, error) { + memcached := &Memcached{} + err := h.GetClient().Get( + ctx, + types.NamespacedName{ + Name: name, + Namespace: namespace, + }, + memcached) + if err != nil { + return nil, err + } + return memcached, err +} diff --git a/apis/memcached/v1beta1/memcached_types.go b/apis/memcached/v1beta1/memcached_types.go index 2b446f4a..f4f915ee 100644 --- a/apis/memcached/v1beta1/memcached_types.go +++ b/apis/memcached/v1beta1/memcached_types.go @@ -19,7 +19,6 @@ package v1beta1 import ( condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/tls" - "github.com/openstack-k8s-operators/lib-common/modules/common/util" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -69,6 +68,9 @@ type MemcachedStatus struct { // ServerListWithInet - List of memcached endpoints with inet(6) prefix ServerListWithInet []string `json:"serverListWithInet,omitempty" optional:"true"` + + // Whether TLS is supported by the memcached instance + TLSSupport bool `json:"tlsSupport,omitempty"` } // +kubebuilder:object:root=true @@ -97,33 +99,3 @@ type MemcachedList struct { func init() { SchemeBuilder.Register(&Memcached{}, &MemcachedList{}) } - -// IsReady - returns true if Memcached is reconciled successfully -func (instance Memcached) IsReady() bool { - return instance.Status.Conditions.IsTrue(condition.ReadyCondition) -} - -// RbacConditionsSet - set the conditions for the rbac object -func (instance Memcached) RbacConditionsSet(c *condition.Condition) { - instance.Status.Conditions.Set(c) -} - -// RbacNamespace - return the namespace -func (instance Memcached) RbacNamespace() string { - return instance.Namespace -} - -// RbacResourceName - return the name to be used for rbac objects (serviceaccount, role, rolebinding) -func (instance Memcached) RbacResourceName() string { - return "memcached-" + instance.Name -} - -// SetupDefaults - initializes any CRD field defaults based on environment variables (the defaulting mechanism itself is implemented via webhooks) -func SetupDefaults() { - // Acquire environmental defaults and initialize Memcached defaults with them - memcachedDefaults := MemcachedDefaults{ - ContainerImageURL: util.GetEnvVar("RELATED_IMAGE_INFRA_MEMCACHED_IMAGE_URL_DEFAULT", MemcachedContainerImage), - } - - SetupMemcachedDefaults(memcachedDefaults) -} diff --git a/config/crd/bases/memcached.openstack.org_memcacheds.yaml b/config/crd/bases/memcached.openstack.org_memcacheds.yaml index 017450a5..1708c11d 100644 --- a/config/crd/bases/memcached.openstack.org_memcacheds.yaml +++ b/config/crd/bases/memcached.openstack.org_memcacheds.yaml @@ -134,6 +134,9 @@ spec: items: type: string type: array + tlsSupport: + description: Whether TLS is supported by the memcached instance + type: boolean type: object type: object served: true diff --git a/controllers/memcached/memcached_controller.go b/controllers/memcached/memcached_controller.go index da51b3e5..d9220690 100644 --- a/controllers/memcached/memcached_controller.go +++ b/controllers/memcached/memcached_controller.go @@ -341,8 +341,10 @@ func (r *Reconciler) generateConfigMaps( "-o ssl_chain_cert=/etc/pki/tls/certs/memcached.crt " + "-o ssl_key=/etc/pki/tls/private/memcached.key " + "-o ssl_ca_cert=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" + instance.Status.TLSSupport = true } else { memcachedTLSConfig = "" + instance.Status.TLSSupport = false } templateParameters := map[string]interface{}{ "memcachedTLSConfig": memcachedTLSConfig, @@ -460,7 +462,7 @@ func (r *Reconciler) GetServerLists( } for i := int32(0); i < *(instance.Spec.Replicas); i++ { - server := fmt.Sprintf("%s-%d.%s", instance.Name, i, instance.Name) + server := fmt.Sprintf("%s-%d.%s.%s.svc", instance.Name, i, instance.Name, instance.Namespace) serverList = append(serverList, fmt.Sprintf("%s:%d", server, memcached.MemcachedPort)) // python-memcached requires inet(6) prefix according to the IP version diff --git a/tests/kuttl/tests/memcached/01-assert.yaml b/tests/kuttl/tests/memcached/01-assert.yaml index f688fc72..2d1cf16b 100644 --- a/tests/kuttl/tests/memcached/01-assert.yaml +++ b/tests/kuttl/tests/memcached/01-assert.yaml @@ -12,7 +12,41 @@ spec: replicas: 1 status: readyCount: 1 - serverList: - - 'memcached-0.memcached:11211' - serverListWithInet: - - 'inet:[memcached-0.memcached]:11211' +--- +# the namespace of the fqdn of the serverList is namespace +# dependent, so we can't rely on kuttl asserts to check them. This short script +# gathers the first entry and checks that it matches the regex +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + # get the first memcached from serverList and validate + template='{{ (index .status.serverList 0) }}' + regex="memcached-0.memcached.$NAMESPACE.svc:11211" + memcached=$(oc get -n $NAMESPACE memcached memcached -o go-template="$template") + matches=$(echo "$memcached" | sed -e "s?$regex??") + if [ -z "$matches" ]; then + exit 0 + else + echo "Memcached Server: $memcached do not match regex" + exit 1 + fi +--- +# the namespace of the fqdn of the serverListWithInet is namespace +# dependent, so we can't rely on kuttl asserts to check them. This short script +# gathers the first entry and checks that it matches the regex +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + # get the first memcached from serverListWithInet and validate + template='{{ (index .status.serverListWithInet 0) }}' + regex="inet:\[memcached-0.memcached.$NAMESPACE.svc\]:11211" + memcached=$(oc get -n $NAMESPACE memcached memcached -o go-template="$template") + matches=$(echo "$memcached" | sed -e "s?$regex??") + if [ -z "$matches" ]; then + exit 0 + else + echo "Memcached ServerListWithInet: $memcached do not match regex" + exit 1 + fi