diff --git a/pkg/install/operators.go b/pkg/install/operators.go index 2e1af8a5..c5786009 100644 --- a/pkg/install/operators.go +++ b/pkg/install/operators.go @@ -735,7 +735,10 @@ func (o *Operators) provisionOperators(ctx context.Context) error { return err } - return o.installOperator(ctx, o.config.Channel.Everest, everestOperatorName)() + if err := o.installOperator(ctx, o.config.Channel.Everest, everestOperatorName)(); err != nil { + return err + } + return o.restartEverestOperatorPod(ctx) } func (o *Operators) installOperator(ctx context.Context, channel, operatorName string) func() error { @@ -1002,3 +1005,8 @@ func (o *Operators) getServiceAccountKubeConfig(ctx context.Context) (string, er return o.kubeClient.GenerateKubeConfigWithToken(everestServiceAccount, secret) } + +func (o *Operators) restartEverestOperatorPod(ctx context.Context) error { + return o.kubeClient.RestartEverestOperator(ctx, o.config.Namespace) + +} diff --git a/pkg/kubernetes/client/client.go b/pkg/kubernetes/client/client.go index 0b6ff5ad..749d4f41 100644 --- a/pkg/kubernetes/client/client.go +++ b/pkg/kubernetes/client/client.go @@ -490,6 +490,11 @@ func (c *Client) GetPods( return c.clientset.CoreV1().Pods(namespace).List(ctx, options) } +// GetPods returns list of pods. +func (c *Client) DeletePod(ctx context.Context, namespace, name string) error { + return c.clientset.CoreV1().Pods(namespace).Delete(ctx, name, metav1.DeleteOptions{}) +} + // GetNodes returns list of nodes. func (c *Client) GetNodes(ctx context.Context) (*corev1.NodeList, error) { return c.clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) diff --git a/pkg/kubernetes/client/kubeclient_interface.go b/pkg/kubernetes/client/kubeclient_interface.go index 3a50d264..5e665b4c 100644 --- a/pkg/kubernetes/client/kubeclient_interface.go +++ b/pkg/kubernetes/client/kubeclient_interface.go @@ -52,6 +52,8 @@ type KubeClientConnector interface { GetPersistentVolumes(ctx context.Context) (*corev1.PersistentVolumeList, error) // GetPods returns list of pods. GetPods(ctx context.Context, namespace string, labelSelector *metav1.LabelSelector) (*corev1.PodList, error) + // GetPods returns list of pods. + DeletePod(ctx context.Context, namespace, name string) error // GetNodes returns list of nodes. GetNodes(ctx context.Context) (*corev1.NodeList, error) // GetLogs returns logs for pod. diff --git a/pkg/kubernetes/client/mock_kube_client_connector.go b/pkg/kubernetes/client/mock_kube_client_connector.go index 21963fe1..8deed84b 100644 --- a/pkg/kubernetes/client/mock_kube_client_connector.go +++ b/pkg/kubernetes/client/mock_kube_client_connector.go @@ -177,6 +177,20 @@ func (_m *MockKubeClientConnector) DeleteObject(obj runtime.Object) error { return r0 } +// DeletePod provides a mock function with given fields: ctx, namespace, name +func (_m *MockKubeClientConnector) DeletePod(ctx context.Context, namespace string, name string) error { + ret := _m.Called(ctx, namespace, name) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { + r0 = rf(ctx, namespace, name) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DoCSVWait provides a mock function with given fields: ctx, key func (_m *MockKubeClientConnector) DoCSVWait(ctx context.Context, key types.NamespacedName) error { ret := _m.Called(ctx, key) diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index bd96f24a..b9fbf933 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -832,3 +832,41 @@ func (k *Kubernetes) updateClusterRoleBindingNamespace(o map[string]interface{}, return nil } + +func (k *Kubernetes) RestartEverestOperator(ctx context.Context, namespace string) error { + pod, err := k.getEverestOperatorPod(ctx, namespace) + if err != nil { + return err + } + podUid := pod.UID + err = k.client.DeletePod(ctx, namespace, pod.Name) + if err != nil { + return err + } + + return wait.PollImmediate(5*time.Second, time.Minute, func() (done bool, err error) { + pod, err := k.getEverestOperatorPod(ctx, namespace) + if pod.UID != podUid && err != nil { + return false, nil + } + return pod.Status.Phase == corev1.PodRunning && pod.Status.ContainerStatuses[0].Ready, nil + }) +} + +func (k *Kubernetes) getEverestOperatorPod(ctx context.Context, namespace string) (corev1.Pod, error) { + podList, err := k.client.GetPods(ctx, namespace, &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": "everest-operator", + }, + }) + if err != nil { + return corev1.Pod{}, err + } + if len(podList.Items) == 0 { + return corev1.Pod{}, errors.New("no instances of everest-opeator are running") + } + if len(podList.Items) > 1 { + return corev1.Pod{}, errors.New("multiple instances of everest-operator found") + } + return podList.Items[0], nil +}