func syncMemberServices(
	reqLogger logr.Logger,
	cr *kdv1.KubeDirectorCluster,
	roles []*roleInfo,
) error {
	for _, role := range roles {
		if role.roleStatus != nil {
			for i := 0; i < len(role.roleStatus.Members); i++ {
				serviceErr := handleMemberService(
					reqLogger,
					cr,
					role,
					&(role.roleStatus.Members[i]),
				)
				if serviceErr != nil {
					return serviceErr
				}
			}
		}
	}
	return nil
}
syncMemberServices is responsible for dealing with the per-member services.
It and syncClusterService are the only functions in this file that are
invoked from another file (from syncCluster in cluster.go). Managing
service changes may result in operations on k8s services. This function
will also modify the status data structures to record the service names.
package kubedirectorcluster
import (
	kdv1 "github.com/bluek8s/kubedirector/pkg/apis/kubedirector/v1beta1"
	"github.com/bluek8s/kubedirector/pkg/executor"
	"github.com/bluek8s/kubedirector/pkg/observer"
	"github.com/bluek8s/kubedirector/pkg/shared"
	"github.com/go-logr/logr"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
)
var serviceShouldBeReconciled = map[memberState]bool{
	memberCreatePending: true,
	memberCreating:      true,
	memberReady:         true,
	memberConfigError:   true,
	memberDeletePending: false,
	memberDeleting:      false,
}
func syncClusterService(
	reqLogger logr.Logger,
	cr *kdv1.KubeDirectorCluster,
) error {
	clusterService, queryErr := queryService(
		reqLogger,
		cr,
		cr.Status.ClusterService,
	)
	if queryErr != nil {
		return queryErr
	}
	if clusterService == nil {
		if cr.Status.ClusterService != "" {
			shared.LogInfo(
				reqLogger,
				cr,
				shared.EventReasonCluster,
				"re-creating missing cluster service",
			)
		}
		createErr := handleClusterServiceCreate(reqLogger, cr)
		if createErr != nil {
			return createErr
		}
	} else {
		handleClusterServiceConfig(reqLogger, cr, clusterService)
	}
	return nil
}