func ImageName(image, param string) string {
	if image == "" {
		param := viper.GetString(param)
		if strings.IndexByte(param, ':') == -1 {
			image = fmt.Sprintf("%s:%s", param, version.Get().Jaeger)
		} else {
			image = param
		}
	}
	return image
}
ImageName returns the image associated with the supplied image if defined, otherwise
uses the parameter name to retrieve the value. If the parameter value does not
include a tag/digest, the Jaeger version will be appended.
package util
import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"strconv"
	"strings"
	"github.com/spf13/viper"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	v1 "github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1"
	"github.com/jaegertracing/jaeger-operator/pkg/version"
)
func RemoveDuplicatedVolumes(volumes []corev1.Volume) []corev1.Volume {
	var results []corev1.Volume
	existing := map[string]bool{}
	for _, volume := range volumes {
		if existing[volume.Name] {
			continue
		}
		results = append(results, volume)
		existing[volume.Name] = true
	}
	return results
}
func RemoveDuplicatedVolumeMounts(volumeMounts []corev1.VolumeMount) []corev1.VolumeMount {
	var results []corev1.VolumeMount
	existing := map[string]bool{}
	for _, volumeMount := range volumeMounts {
		if existing[volumeMount.Name] {
			continue
		}
		results = append(results, volumeMount)
		existing[volumeMount.Name] = true
	}
	return results
}
func RemoveDuplicatedImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference) []corev1.LocalObjectReference {
	var results []corev1.LocalObjectReference
	existing := map[string]bool{}
	for _, imagePullSecret := range imagePullSecrets {
		if existing[imagePullSecret.Name] {
			continue
		}
		results = append(results, imagePullSecret)
		existing[imagePullSecret.Name] = true
	}
	return results
}
func Merge(commonSpecs []v1.JaegerCommonSpec) *v1.JaegerCommonSpec {
	annotations := make(map[string]string)
	labels := make(map[string]string)
	var volumeMounts []corev1.VolumeMount
	var volumes []corev1.Volume
	resources := &corev1.ResourceRequirements{}
	var affinity *corev1.Affinity
	var tolerations []corev1.Toleration
	var securityContext *corev1.PodSecurityContext
	var serviceAccount string
	for _, commonSpec := range commonSpecs {
		for k, v := range commonSpec.Annotations {
			if _, ok := annotations[k]; !ok {
				annotations[k] = v
			}
		}
		for k, v := range commonSpec.Labels {
			if _, ok := labels[k]; !ok {
				labels[k] = v
			}
		}
		volumeMounts = append(volumeMounts, commonSpec.VolumeMounts...)
		volumes = append(volumes, commonSpec.Volumes...)
		MergeResources(resources, commonSpec.Resources)
		if affinity == nil {
			affinity = commonSpec.Affinity
		}
		tolerations = append(tolerations, commonSpec.Tolerations...)
		if securityContext == nil {
			securityContext = commonSpec.SecurityContext
		}
		if serviceAccount == "" {
			serviceAccount = commonSpec.ServiceAccount
		}
	}
	return &v1.JaegerCommonSpec{
		Annotations:     annotations,
		Labels:          labels,
		VolumeMounts:    RemoveDuplicatedVolumeMounts(volumeMounts),
		Volumes:         RemoveDuplicatedVolumes(volumes),
		Resources:       *resources,
		Affinity:        affinity,
		Tolerations:     tolerations,
		SecurityContext: securityContext,
		ServiceAccount:  serviceAccount,
	}
}
func MergeResources(resources *corev1.ResourceRequirements, res corev1.ResourceRequirements) {
	for k, v := range res.Limits {
		if _, ok := resources.Limits[k]; !ok {
			if resources.Limits == nil {
				resources.Limits = make(corev1.ResourceList)
			}
			resources.Limits[k] = v
		}
	}
	for k, v := range res.Requests {
		if _, ok := resources.Requests[k]; !ok {
			if resources.Requests == nil {
				resources.Requests = make(corev1.ResourceList)
			}
			resources.Requests[k] = v
		}
	}
}
func AsOwner(jaeger *v1.Jaeger) metav1.OwnerReference {
	b := true
	return metav1.OwnerReference{
		APIVersion: jaeger.APIVersion,
		Kind:       jaeger.Kind,
		Name:       jaeger.Name,
		UID:        jaeger.UID,
		Controller: &b,
	}
}
func Labels(name, component string, jaeger v1.Jaeger) map[string]string {
	return map[string]string{
		"app":                          "jaeger",  
		"app.kubernetes.io/name":       Truncate(name, 63),
		"app.kubernetes.io/instance":   Truncate(jaeger.Name, 63),
		"app.kubernetes.io/component":  Truncate(component, 63),
		"app.kubernetes.io/part-of":    "jaeger",
		"app.kubernetes.io/managed-by": "jaeger-operator",
	}
}
func GetEsHostname(opts map[string]interface{}) string {
	urls, ok := opts["es.server-urls"]
	if !ok {
		return ""
	}
	urlsString, isString := urls.(string)
	if !isString {
		return ""
	}
	urlArr := strings.Split(urlsString, ",")
	return urlArr[0]
}
func FindItem(prefix string, args []string) string {
	for _, v := range args {
		if strings.HasPrefix(v, prefix) {
			return v
		}
	}
	return ""
}
func ReplaceArgument(prefix string, newValue string, args []string) int {
	found := 0
	for argIndex, arg := range args {
		if strings.HasPrefix(arg, prefix) {
			args[argIndex] = newValue
			found++
		}
	}
	return found
}
func GetPort(arg string, args []string, port int32) int32 {
	portArg := FindItem(arg, args)
	if len(portArg) > 0 {
		i := strings.Index(portArg, ":")
		if i > -1 {
			newPort, err := strconv.ParseInt(portArg[i+1:], 10, 32)
			if err == nil {
				port = int32(newPort)
			}
		}
	}
	return port
}
func GetAdminPort(args []string, port int32) int32 {
	if portArg := FindItem("--admin.http.host-port=", args); len(portArg) > 0 {
		port = GetPort("--admin.http.host-port=", args, port)
	} else {
		port = GetPort("--admin-http-port=", args, port)
	}
	return port
}
func InitObjectMeta(obj metav1.Object) {
	if obj.GetLabels() == nil {
		obj.SetLabels(map[string]string{})
	}
	if obj.GetAnnotations() == nil {
		obj.SetAnnotations(map[string]string{})
	}
}