Patching deployments via kubernetes/client-go

12/21/2018

Having trouble figuring out what is wrong. I have a remote kubernetes cluster up and have copied the config locally. I know it is correct because I have gotten other commands to work for me.

The one I can't get to work is a deployment patch. My code:

const namespace = "default"

var clientset *kubernetes.Clientset

func init() {
    kubeconfig := "/Users/$USER/go/k8s-api/config"
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }

    // create the clientset
    clientset, err = kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
}

func main() {
    deploymentsClient := clientset.ExtensionsV1beta1().Deployments("default")

    patch := []byte(`[{"spec":{"template":{"spec":{"containers":[{"name":"my-deploy-test","image":"$ORG/$REPO:my-deploy0.0.1"}]}}}}]`)
    res, err := deploymentsClient.Patch("my-deploy", types.JSONPatchType, patch)
    if err != nil {
        panic(err)
    }
    fmt.Println(res)

}

All I get back is: panic: the server rejected our request due to an error in our request

Any help appreciated, thanks!

-- L. Norman
client-go
kubernetes
kubernetes-go-client

2 Answers

12/22/2018

You have mixed up JSONPatchType with MergePatchType; JSONPatchType wants the input to be RFC 6902 formatted "commands", and in that case can be a JSON array, because there can be multiple commands applied in order to the input document

However, your payload looks much closer to you wanting MergePatchType, in which case the input should not be a JSON array because the source document is not an array of "spec" objects.

Thus, I'd bet just dropping the leading [ and trailing ], changing the argument to be types.MergePatchType will get you much further along

-- mdaniel
Source: StackOverflow

12/22/2018

Actually you should use types.StrategicMergePatchType and remove leading([) and trailing(]) parenthesis from patching string.

Merge-patch: With a JSON merge patch, if you want to update a list, you have to specify the entire new list. And the new list completely replaces the existing list.

Strategic-merge-patch: With a strategic merge patch, a list is either replaced or merged depending on its patch strategy. The patch strategy is specified by the value of the patchStrategy key in a field tag in the Kubernetes source code. For example, the Containers field of PodSpec struct has a patchStrategy of merge:

type PodSpec struct {
  ...
  Containers []Container `json:"containers" patchStrategy:"merge" patchMergeKey:"name" ...`

N.B: kubectl by-default uses strategic merge patch to patch kubernetes resources.

-- Abu Hanifa
Source: StackOverflow