code: func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taints ...*v1.Taint) error {
  	if len(taints) == 0 {
  		return nil
  	}
  	firstTry := true
  	return clientretry.RetryOnConflict(updateTaintBackoff, func() error {
  		var err error
  		var oldNode *v1.Node
  		// First we try getting node from the API server cache, as it's cheaper. If it fails
  		// we get it from etcd to be sure to have fresh data.
  		if firstTry {
  			oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"})
  			firstTry = false
  		} else {
  			oldNode, err = c.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
  		}
  		if err != nil {
  			return err
  		}
  
  		var newNode *v1.Node
  		oldNodeCopy := oldNode
  		updated := false
  		for _, taint := range taints {
  			curNewNode, ok, err := addOrUpdateTaint(oldNodeCopy, taint)
  			if err != nil {
  				return fmt.Errorf("failed to update taint of node")
  			}
  			updated = updated || ok
  			newNode = curNewNode
  			oldNodeCopy = curNewNode
  		}
  		if !updated {
  			return nil
  		}
  		return PatchNodeTaints(c, nodeName, oldNode, newNode)
  	})
  }
docs: // AddOrUpdateTaintOnNode add taints to the node. If taint was added into node, it'll issue API calls
  // to update nodes; otherwise, no API calls. Return error if any.