天天看點

kubectl源碼分析之rollout pause

 歡迎關注我的公衆号:

 目前剛開始寫一個月,一共寫了18篇原創文章,文章目錄如下:

​​istio多叢集探秘,部署了50次多叢集後我得出的結論​​

​​istio多叢集鍊路追蹤,附實操視訊​​

​​istio防故障利器,你知道幾個,istio新手不要讀,太難!​​

​​istio業務權限控制,原來可以這麼玩​​

​​istio實作非侵入壓縮,微服務之間如何實作壓縮​​

​​不懂envoyfilter也敢說精通istio系列-http-rbac-不要隻會用AuthorizationPolicy配置權限​​

​​不懂envoyfilter也敢說精通istio系列-02-http-corsFilter-不要隻會vs​​

​​不懂envoyfilter也敢說精通istio系列-03-http-csrf filter-再也不用再代碼裡寫csrf邏輯了​​

​​不懂envoyfilter也敢說精通istio系列http-jwt_authn-不要隻會RequestAuthorization​​

​​不懂envoyfilter也敢說精通istio系列-05-fault-filter-故障注入不止是vs​​

​​不懂envoyfilter也敢說精通istio系列-06-http-match-配置路由不隻是vs​​

​​不懂envoyfilter也敢說精通istio系列-07-負載均衡配置不止是dr​​

​​不懂envoyfilter也敢說精通istio系列-08-連接配接池和斷路器​​

​​不懂envoyfilter也敢說精通istio系列-09-http-route filter​​

​​不懂envoyfilter也敢說精通istio系列-network filter-redis proxy​​

​​不懂envoyfilter也敢說精通istio系列-network filter-HttpConnectionManager​​

​​不懂envoyfilter也敢說精通istio系列-ratelimit-istio ratelimit完全手冊​​

type PauseOptions struct {//pause結構體
  PrintFlags *genericclioptions.PrintFlags
  ToPrinter  func(string) (printers.ResourcePrinter, error)

  Pauser           polymorphichelpers.ObjectPauserFunc
  Builder          func() *resource.Builder
  Namespace        string
  EnforceNamespace bool
  Resources        []string

  resource.FilenameOptions
  genericclioptions.IOStreams
}      
//建立pause指令
func NewCmdRolloutPause(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
  o := &PauseOptions{//初始化結構體
    PrintFlags: genericclioptions.NewPrintFlags("paused").WithTypeSetter(scheme.Scheme),
    IOStreams:  streams,
  }

  validArgs := []string{"deployment"}

  cmd := &cobra.Command{//建立cobra指令
    Use:                   "pause RESOURCE",
    DisableFlagsInUseLine: true,
    Short:                 i18n.T("Mark the provided resource as paused"),
    Long:                  pauseLong,
    Example:               pauseExample,
    Run: func(cmd *cobra.Command, args []string) {
      cmdutil.CheckErr(o.Complete(f, cmd, args))//準備
      cmdutil.CheckErr(o.Validate())//校驗
      cmdutil.CheckErr(o.RunPause())//運作
    },
    ValidArgs: validArgs,//有效參數
  }

  o.PrintFlags.AddFlags(cmd)//設定列印選項

  usage := "identifying the resource to get from a server."
  cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)//設定檔案選項
  return cmd
}      
//準備方法
func (o *PauseOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
  o.Pauser = polymorphichelpers.ObjectPauserFn//設定Pauser函數

  var err error
  o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()//擷取namespace和enforcenameapace
  if err != nil {
    return err
  }

  o.Resources = args//設定resources
  o.Builder = f.NewBuilder//設定Builder

  o.ToPrinter = func(operation string) (printers.ResourcePrinter, error) {//printflag轉printer函數
    o.PrintFlags.NamePrintFlags.Operation = operation
    return o.PrintFlags.ToPrinter()
  }

  return nil
}      
//校驗函數
func (o *PauseOptions) Validate() error {
  if len(o.Resources) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) {//資源和檔案至少指定一個
    return fmt.Errorf("required resource not specified")
  }
  return nil
}      
//運作
func (o *PauseOptions) RunPause() error {
  r := o.Builder().
    WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
    NamespaceParam(o.Namespace).DefaultNamespace().
    FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
    ResourceTypeOrNameArgs(true, o.Resources...).
    ContinueOnError().
    Latest().
    Flatten().
    Do()//構造info對象
  if err := r.Err(); err != nil {
    return err
  }

  allErrs := []error{}
  infos, err := r.Infos()//擷取info對象
  if err != nil {
    // restore previous command behavior where
    // an error caused by retrieving infos due to
    // at least a single broken object did not result
    // in an immediate return, but rather an overall
    // aggregation of errors.
    allErrs = append(allErrs, err)
  }

  for _, patch := range set.CalculatePatches(infos, scheme.DefaultJSONEncoder(), set.PatchFn(o.Pauser)) {//計算patches,然後周遊
    info := patch.Info

    if patch.Err != nil {//patch有error,處理error
      resourceString := info.Mapping.Resource.Resource
      if len(info.Mapping.Resource.Group) > 0 {
        resourceString = resourceString + "." + info.Mapping.Resource.Group
      }
      allErrs = append(allErrs, fmt.Errorf("error: %s %q %v", resourceString, info.Name, patch.Err))
      continue
    }

    if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {//patch為空
      printer, err := o.ToPrinter("already paused")//printflag轉printer
      if err != nil {
        allErrs = append(allErrs, err)
        continue
      }
      if err = printer.PrintObj(info.Object, o.Out); err != nil {//列印對象
        allErrs = append(allErrs, err)
      }
      continue
    }

    obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)//應用patch到服務端
    if err != nil {
      allErrs = append(allErrs, fmt.Errorf("failed to patch: %v", err))
      continue
    }

    info.Refresh(obj, true)//重新整理obj
    printer, err := o.ToPrinter("paused")// print flag轉printer
    if err != nil {
      allErrs = append(allErrs, err)
      continue
    }
    if err = printer.PrintObj(info.Object, o.Out); err != nil {//列印結果
      allErrs = append(allErrs, err)
    }
  }

  return utilerrors.NewAggregate(allErrs)
}