util.go 6.3 KB
Newer Older
L
liqingping 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
package util

import (
	"fmt"
	"math/rand"
	"strings"
	"time"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	utilrand "k8s.io/apimachinery/pkg/util/rand"

16
	div2alpha1 "opendilab.org/di-orchestrator/pkg/api/v2alpha1"
L
liqingping 已提交
17
	dicommon "opendilab.org/di-orchestrator/pkg/common"
L
liqingping 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31
)

const (
	randomLength = 5
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

func GenerateName(name string) string {
	return fmt.Sprintf("%s-%s", name, utilrand.String(randomLength))
}

L
liqingping 已提交
32 33 34 35 36 37 38
func NamespacedName(namespace, name string) string {
	return fmt.Sprintf("%s/%s", namespace, name)
}

func SplitNamespaceName(namespaceName string) (types.NamespacedName, error) {
	strs := strings.Split(namespaceName, "/")
	if len(strs) != 2 {
39
		return types.NamespacedName{}, fmt.Errorf("invalid namespace/name %s", namespaceName)
L
liqingping 已提交
40 41 42 43
	}
	return types.NamespacedName{Namespace: strs[0], Name: strs[1]}, nil
}

44 45 46 47
func ReplicaName(jobName string, generation, rank int) string {
	return fmt.Sprintf("%s-%d-%d", jobName, generation, rank)
}

48 49
func IsSucceeded(job *div2alpha1.DIJob) bool {
	return job.Status.Phase == div2alpha1.JobSucceeded
50 51
}

52 53
func IsFailed(job *div2alpha1.DIJob) bool {
	return job.Status.Phase == div2alpha1.JobFailed
54 55 56 57 58 59
}

func IsTerminating(pod *corev1.Pod) bool {
	return pod.DeletionTimestamp != nil
}

L
liqingping 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72
func GetObjectFromUnstructured(obj interface{}, dest interface{}) error {
	us, ok := obj.(*unstructured.Unstructured)
	if !ok {
		return fmt.Errorf("the object %s is not unstructured", obj)
	}
	err := runtime.DefaultUnstructuredConverter.FromUnstructured(us.UnstructuredContent(), dest)
	if err != nil {
		return err
	}

	return nil
}

L
liqingping 已提交
73
func GetDefaultPortFromPod(pod *corev1.Pod) (int32, bool) {
L
liqingping 已提交
74
	for _, c := range pod.Spec.Containers {
L
liqingping 已提交
75
		if c.Name != dicommon.DefaultContainerName {
L
liqingping 已提交
76 77 78
			continue
		}
		for _, port := range c.Ports {
L
liqingping 已提交
79
			if port.Name == dicommon.DefaultPortName {
L
liqingping 已提交
80 81 82 83 84 85 86
				return port.ContainerPort, true
			}
		}
	}
	return -1, false
}

87
func AddPortToPod(pod *corev1.Pod, port corev1.ContainerPort) {
L
liqingping 已提交
88
	for i := range pod.Spec.Containers {
L
liqingping 已提交
89
		if pod.Spec.Containers[i].Name != dicommon.DefaultContainerName {
L
liqingping 已提交
90 91 92 93 94
			continue
		}
		if pod.Spec.Containers[i].Ports == nil {
			pod.Spec.Containers[i].Ports = []corev1.ContainerPort{}
		}
95
		pod.Spec.Containers[i].Ports = append(pod.Spec.Containers[i].Ports, port)
L
liqingping 已提交
96 97 98
	}
}

99
func GenLabels(job div2alpha1.DIJob) map[string]string {
L
liqingping 已提交
100
	return map[string]string{
101 102
		dicommon.LabelGroup:    job.Spec.Group,
		dicommon.LabelJob:      strings.Replace(job.Name, "/", "-", -1),
103
		dicommon.LabelOperator: dicommon.OperatorName,
L
liqingping 已提交
104 105 106 107 108 109 110 111 112 113 114 115
	}
}

func AddLabelsToPod(pod *corev1.Pod, labels map[string]string) {
	if pod.ObjectMeta.Labels == nil {
		pod.ObjectMeta.Labels = make(map[string]string)
	}
	for k, v := range labels {
		pod.ObjectMeta.Labels[k] = v
	}
}

116 117 118 119 120 121 122 123 124
func AddAnnotationsToPod(pod *corev1.Pod, annotations map[string]string) {
	if pod.ObjectMeta.Annotations == nil {
		pod.ObjectMeta.Annotations = make(map[string]string)
	}
	for k, v := range annotations {
		pod.ObjectMeta.Annotations[k] = v
	}
}

L
liqingping 已提交
125 126 127 128 129 130
func AddEnvsToPod(pod *corev1.Pod, envs map[string]string) {
	for i := range pod.Spec.Containers {
		if len(pod.Spec.Containers[i].Env) == 0 {
			pod.Spec.Containers[i].Env = make([]corev1.EnvVar, 0)
		}
		for k, v := range envs {
131
			env := corev1.EnvVar{Name: k, Value: v}
L
liqingping 已提交
132 133 134 135 136
			pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, env)
		}
	}
}

137 138 139 140 141 142 143 144 145 146 147 148 149 150
func GetEnvFromPod(pod *corev1.Pod, envName string) (string, bool) {
	for _, container := range pod.Spec.Containers {
		if container.Name != dicommon.DefaultContainerName {
			continue
		}
		for _, env := range container.Env {
			if env.Name == envName {
				return env.Value, true
			}
		}
	}
	return "", false
}

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
func CountPodsScheduled(pods []*corev1.Pod) int {
	count := 0
	for _, pod := range pods {
		for _, c := range pod.Status.Conditions {
			if c.Type == corev1.PodScheduled && c.Status == corev1.ConditionTrue {
				count++
			}
		}
	}
	return count
}

func CountReadyPods(pods []*corev1.Pod) int {
	count := 0
	for _, pod := range pods {
		for _, c := range pod.Status.ContainerStatuses {
			if c.Ready {
				count++
			}
		}
	}
	return count
}

175 176 177 178 179 180
func SetPodResources(pod *corev1.Pod, resources corev1.ResourceRequirements) {
	for i := range pod.Spec.Containers {
		if pod.Spec.Containers[i].Name != dicommon.DefaultContainerName {
			continue
		}
		pod.Spec.Containers[i].Resources = resources
L
liqingping 已提交
181
	}
182
}
L
liqingping 已提交
183

184 185 186 187 188 189 190 191
func GetPodResources(spec *corev1.PodSpec) corev1.ResourceRequirements {
	for _, container := range spec.Containers {
		if container.Name != dicommon.DefaultContainerName {
			continue
		}
		return container.Resources
	}
	return corev1.ResourceRequirements{}
L
liqingping 已提交
192 193 194 195 196 197 198
}

func ConcatURL(name, ns string, port int32) string {
	return fmt.Sprintf("%s.%s:%d", name, ns, port)
}

func GetPodAccessURL(pod *corev1.Pod, defaultPort int32) string {
L
liqingping 已提交
199
	port, found := GetDefaultPortFromPod(pod)
L
liqingping 已提交
200 201 202 203 204 205 206 207 208
	if !found {
		port = defaultPort
	}
	return ConcatURL(pod.Name, pod.Namespace, port)
}

func GetServiceAccessURL(service *corev1.Service) string {
	url := ""
	for _, port := range service.Spec.Ports {
L
liqingping 已提交
209
		if port.Name == dicommon.DefaultPortName {
L
liqingping 已提交
210 211 212 213 214 215 216
			url = ConcatURL(service.Name, service.Namespace, port.Port)
			break
		}
	}
	return url
}

217 218
func FilterOutTerminatingPods(pods []*corev1.Pod) []*corev1.Pod {
	results := []*corev1.Pod{}
L
liqingping 已提交
219
	for _, pod := range pods {
220
		if IsTerminating(pod) {
L
liqingping 已提交
221 222
			continue
		}
223
		results = append(results, pod)
L
liqingping 已提交
224 225
	}

226 227
	return results
}
L
liqingping 已提交
228

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
func BuildService(name, namespace string, ownRefer metav1.OwnerReference, labels map[string]string, port int32) *corev1.Service {
	svc := &corev1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:            name,
			Namespace:       namespace,
			Labels:          labels,
			OwnerReferences: []metav1.OwnerReference{ownRefer},
		},
		Spec: corev1.ServiceSpec{
			Type:      corev1.ServiceTypeClusterIP,
			ClusterIP: "None",
			Selector:  labels,
			Ports: []corev1.ServicePort{
				{
					Port: port,
					Name: dicommon.DefaultPortName,
				},
			},
		},
L
liqingping 已提交
248
	}
L
liqingping 已提交
249

250
	return svc
L
liqingping 已提交
251
}
252 253 254 255 256 257 258 259 260 261

func NewOwnerReference(apiVersion, kind, name string, uid types.UID, controller bool) metav1.OwnerReference {
	return metav1.OwnerReference{
		APIVersion: apiVersion,
		Kind:       kind,
		Name:       name,
		UID:        uid,
		Controller: &controller,
	}
}