github.com/fafucoder/cilium@v1.6.11/cilium/cmd/policy_wait.go (about)

     1  // Copyright 2017 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cmd
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"time"
    21  
    22  	"github.com/cilium/cilium/api/v1/models"
    23  
    24  	"github.com/spf13/cobra"
    25  )
    26  
    27  var waitTime, failWaitTime, maxWaitTime int
    28  var policyWaitCmd = &cobra.Command{
    29  	Use:   "wait <revision>",
    30  	Short: "Wait for all endpoints to have updated to a given policy revision",
    31  	Run: func(cmd *cobra.Command, args []string) {
    32  		if len(args) < 1 || args[0] == "" {
    33  			Usagef(cmd, "invalid revision")
    34  		}
    35  
    36  		reqRevision, err := strconv.ParseInt(args[0], 10, 64)
    37  		if err != nil {
    38  			Fatalf("invalid revision '%s': %s", args[0], err)
    39  		}
    40  
    41  		startTime := time.Now()
    42  		failDeadline := startTime.Add(time.Duration(failWaitTime) * time.Second)
    43  		maxDeadline := startTime.Add(time.Duration(maxWaitTime) * time.Second)
    44  
    45  		haveWaited := false
    46  
    47  		for {
    48  			eps, err := client.EndpointList()
    49  			if err != nil {
    50  				Fatalf("cannot list endpoints: %s\n", err)
    51  			}
    52  
    53  			needed := len(eps)
    54  			ready := 0
    55  			notReady := 0
    56  
    57  			for _, ep := range eps {
    58  				switch {
    59  				case ep.Status.Policy == nil || ep.Status.Policy.Realized == nil:
    60  					notReady++
    61  
    62  				case ep.Status.Policy.Realized.PolicyRevision >= reqRevision &&
    63  					ep.Status.State == models.EndpointStateReady:
    64  					ready++
    65  
    66  				case ep.Status.State == models.EndpointStateNotReady:
    67  					notReady++
    68  				}
    69  			}
    70  
    71  			if ready == needed {
    72  				if haveWaited {
    73  					fmt.Printf("\n")
    74  				}
    75  				return
    76  			} else if time.Now().After(failDeadline) && notReady > 0 {
    77  				// Fail earlier if any endpoints have a failed state
    78  				Fatalf("\n%d endpoints have failed regeneration after %s\n", notReady, time.Since(startTime))
    79  			} else if time.Now().After(maxDeadline) {
    80  				// Fail after timeout
    81  				Fatalf("\n%d endpoints still not ready after %s (%d failed)\n", needed-ready, time.Since(startTime), notReady)
    82  			}
    83  
    84  			fmt.Printf("\rWaiting for endpoints to run policy revision %d: %d/%d              ",
    85  				reqRevision, ready, needed)
    86  			time.Sleep(time.Duration(waitTime) * time.Second)
    87  			haveWaited = true
    88  		}
    89  	},
    90  }
    91  
    92  func init() {
    93  	policyCmd.AddCommand(policyWaitCmd)
    94  	policyWaitCmd.Flags().IntVar(&waitTime, "sleep-time", 1, "Sleep interval between checks (seconds)")
    95  	policyWaitCmd.Flags().IntVar(&failWaitTime, "fail-wait-time", 60, "Wait time after which command fails if endpoint regeration fails (seconds)")
    96  	policyWaitCmd.Flags().IntVar(&maxWaitTime, "max-wait-time", 360, "Wait time after which command fails (seconds)")
    97  }