forked from kyma-project/kyma
/
pod_service.go
135 lines (107 loc) · 3.73 KB
/
pod_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package k8s
import (
"fmt"
"github.com/kyma-project/kyma/components/console-backend-service/internal/apierror"
"github.com/kyma-project/kyma/components/console-backend-service/internal/domain/k8s/pretty"
"github.com/kyma-project/kyma/components/console-backend-service/pkg/resource"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"github.com/kyma-project/kyma/components/console-backend-service/internal/pager"
"k8s.io/client-go/tools/cache"
)
type podService struct {
client corev1.CoreV1Interface
informer cache.SharedIndexInformer
notifier resource.Notifier
}
func newPodService(informer cache.SharedIndexInformer, client corev1.CoreV1Interface) *podService {
notifier := resource.NewNotifier()
informer.AddEventHandler(notifier)
return &podService{
client: client,
informer: informer,
notifier: notifier,
}
}
func (svc *podService) Find(name, namespace string) (*v1.Pod, error) {
key := fmt.Sprintf("%s/%s", namespace, name)
item, exists, err := svc.informer.GetStore().GetByKey(key)
if err != nil || !exists {
return nil, err
}
pod, ok := item.(*v1.Pod)
if !ok {
return nil, fmt.Errorf("Incorrect item type: %T, should be: *Pod", item)
}
svc.ensureTypeMeta(pod)
return pod, nil
}
func (svc *podService) List(namespace string, pagingParams pager.PagingParams) ([]*v1.Pod, error) {
items, err := pager.FromIndexer(svc.informer.GetIndexer(), "namespace", namespace).Limit(pagingParams)
if err != nil {
return nil, err
}
var pods []*v1.Pod
for _, item := range items {
pod, ok := item.(*v1.Pod)
if !ok {
return nil, fmt.Errorf("Incorrect item type: %T, should be: *Pod", item)
}
svc.ensureTypeMeta(pod)
pods = append(pods, pod)
}
return pods, nil
}
func (svc *podService) Subscribe(listener resource.Listener) {
svc.notifier.AddListener(listener)
}
func (svc *podService) Unsubscribe(listener resource.Listener) {
svc.notifier.DeleteListener(listener)
}
func (svc *podService) Update(name, namespace string, update v1.Pod) (*v1.Pod, error) {
err := svc.checkUpdatePreconditions(name, namespace, update)
if err != nil {
return nil, err
}
updated, err := svc.client.Pods(namespace).Update(&update)
if err != nil {
return nil, err
}
svc.ensureTypeMeta(updated)
return updated, nil
}
func (svc *podService) Delete(name, namespace string) error {
return svc.client.Pods(namespace).Delete(name, nil)
}
func (svc *podService) checkUpdatePreconditions(name string, namespace string, update v1.Pod) error {
var errs apierror.ErrorFieldAggregate
if name != update.Name {
errs = append(errs, apierror.NewInvalidField("metadata.name", update.Name, fmt.Sprintf("name of updated object does not match the original (%s)", name)))
}
if namespace != update.Namespace {
errs = append(errs, apierror.NewInvalidField("metadata.namespace", update.Namespace, fmt.Sprintf("namespace of updated object does not match the original (%s)", namespace)))
}
typeMeta := svc.podTypeMeta()
if update.Kind != typeMeta.Kind {
errs = append(errs, apierror.NewInvalidField("kind", update.Kind, "pod's kind should not be changed"))
}
if update.APIVersion != typeMeta.APIVersion {
errs = append(errs, apierror.NewInvalidField("apiVersion", update.APIVersion, "pod's apiVersion should not be changed"))
}
if len(errs) > 0 {
return apierror.NewInvalid(pretty.Pod, errs)
}
return nil
}
// Kubernetes API used by client-go doesn't provide kind and apiVersion so we have to add it here
// See: https://github.com/kubernetes/kubernetes/issues/3030
func (svc *podService) ensureTypeMeta(pod *v1.Pod) {
pod.TypeMeta = svc.podTypeMeta()
}
func (svc *podService) podTypeMeta() metav1.TypeMeta {
return metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
}
}