@@ -25,10 +25,16 @@ package main
2525import (
2626 "context"
2727 "io"
28+ "net"
2829 "os"
2930 "path/filepath"
31+ "strconv"
3032 "time"
3133
34+ "github.com/arangodb/kube-arangodb/pkg/backup/utils"
35+
36+ "github.com/arangodb/kube-arangodb/pkg/util/retry"
37+
3238 "github.com/arangodb/kube-arangodb/pkg/version"
3339
3440 "github.com/spf13/cobra"
5460 Run : cmdLifecyclePreStopRunFinalizer ,
5561 Hidden : true ,
5662 }
63+ cmdLifecyclePreStopPort = & cobra.Command {
64+ Use : "port" ,
65+ Hidden : true ,
66+ }
5767 cmdLifecycleCopy = & cobra.Command {
5868 Use : "copy" ,
5969 Run : cmdLifecycleCopyRun ,
6878func init () {
6979 cmdMain .AddCommand (cmdLifecycle )
7080
71- cmdLifecyclePreStop .AddCommand (cmdLifecyclePreStopFinalizers )
81+ var preStopPort cmdLifecyclePreStopRunPort
82+
83+ cmdLifecyclePreStopPort .RunE = preStopPort .run
84+
85+ f := cmdLifecyclePreStopPort .Flags ()
86+
87+ f .DurationVar (& preStopPort .timeout , "timeout" , 6 * 60 * time .Minute , "PreStopTimeout" )
88+
89+ cmdLifecyclePreStop .AddCommand (cmdLifecyclePreStopFinalizers , cmdLifecyclePreStopPort )
7290
7391 cmdLifecycle .AddCommand (cmdLifecyclePreStop )
7492 cmdLifecycle .AddCommand (cmdLifecycleCopy )
@@ -162,3 +180,63 @@ func cmdLifecycleCopyRun(cmd *cobra.Command, args []string) {
162180
163181 cliLog .Info ().Msgf ("Executable copied to %s" , targetPath )
164182}
183+
184+ type cmdLifecyclePreStopRunPort struct {
185+ timeout time.Duration
186+ }
187+
188+ // Wait until port 8529 is closed.
189+ func (c * cmdLifecyclePreStopRunPort ) run (cmd * cobra.Command , args []string ) error {
190+ address := net .JoinHostPort ("127.0.0.1" , strconv .Itoa (k8sutil .ArangoPort ))
191+
192+ // Get environment
193+ namespace := os .Getenv (constants .EnvOperatorPodNamespace )
194+ if len (namespace ) == 0 {
195+ cliLog .Fatal ().Msgf ("%s environment variable missing" , constants .EnvOperatorPodNamespace )
196+ }
197+ name := os .Getenv (constants .EnvOperatorPodName )
198+ if len (name ) == 0 {
199+ cliLog .Fatal ().Msgf ("%s environment variable missing" , constants .EnvOperatorPodName )
200+ }
201+
202+ // Create kubernetes client
203+ kubecli , err := k8sutil .NewKubeClient ()
204+ if err != nil {
205+ cliLog .Fatal ().Err (err ).Msg ("Failed to create Kubernetes client" )
206+ }
207+
208+ pods := kubecli .CoreV1 ().Pods (namespace )
209+
210+ recentErrors := 0
211+
212+ return retry .NewTimeout (func () error {
213+ conn , err := net .DialTimeout ("tcp" , address , 500 * time .Millisecond )
214+
215+ if err != nil {
216+ return retry .Interrput ()
217+ }
218+
219+ conn .Close ()
220+
221+ p , err := pods .Get (context .Background (), name , metav1.GetOptions {})
222+ if k8sutil .IsNotFound (err ) {
223+ cliLog .Warn ().Msg ("Pod not found" )
224+ return nil
225+ } else if err != nil {
226+ recentErrors ++
227+ cliLog .Error ().Err (err ).Msg ("Failed to get pod" )
228+ if recentErrors > 20 {
229+ cliLog .Fatal ().Err (err ).Msg ("Too many recent errors" )
230+ return nil
231+ }
232+ } else {
233+ // We got our pod
234+ finalizers := utils .StringList (p .GetFinalizers ())
235+ if ! finalizers .Has (constants .FinalizerPodGracefulShutdown ) {
236+ return retry .Interrput ()
237+ }
238+ }
239+
240+ return nil
241+ }).Timeout (125 * time .Millisecond , c .timeout )
242+ }
0 commit comments